PactionScript Documentation
Build custom indicators, layout themes, and interactive widgets for Paction trading terminal.
Overview
PactionScript is a safe scripting language for creating custom tools in the Paction Creator. It runs in a sandboxed environment with access only to chart data and a curated API — no access to DOM, network, or browser APIs.
- Indicator — draws on the chart: lines, shapes, fills, oscillator panels
- Layout — customizes the interface with CSS: colors, fonts, spacing, theming
- Layout + Indicator — combines both: custom UI + chart overlays
Quick Start
Open Create in the top bar, select Indicator type, paste this and press Ctrl+Enter:
var len = input.number("Length", 20, 5, 200);
var ma = sma(close, len);
plot(ma, "Moving Average", "#2962ff", 2);
This creates a simple moving average indicator with a configurable length parameter.
Script Types
Indicator
Pure chart overlay. Has access to all price data, indicator functions, and drawing API. Cannot modify page layout.
Layout
Pure CSS. Customizes the interface appearance. Write standard CSS targeting Paction's class names. No JavaScript.
Layout + Indicator (Hybrid)
Combines both. Use /* CSS */ and /* END CSS */ markers or // @css prefix for CSS lines:
/* CSS */
.top-bar { background: #1a1e2e; }
.logo { color: #ff9800; }
/* END CSS */
var ma = sma(close, 20);
plot(ma, "MA", "#ff9800", 2);
Security Sandbox
PactionScript runs in an isolated sandbox. The following are blocked:
- All DOM access:
document,createElement,querySelector,innerHTML - Network:
fetch,XMLHttpRequest,WebSocket - Execution:
eval,Function,setTimeout,setInterval - Globals:
window,navigator,location,localStorage - Prototype manipulation:
__proto__,prototype,constructor[]
Use the Widget API instead of DOM manipulation. Widgets are safe declarative objects that the engine renders for you.
Price Data DATA
These arrays contain OHLCV data for every candle on the chart:
| Variable | Type | Description |
|---|---|---|
| open | number[] | Opening price of each candle |
| high | number[] | Highest price of each candle |
| low | number[] | Lowest price of each candle |
| close | number[] | Closing price of each candle |
| volume | number[] | Volume of each candle |
| time | number[] | Unix timestamp (seconds) of each candle |
| barIndex | number[] | Index of each bar [0, 1, 2, ...] |
| barCount | number | Total number of candles |
Derived Sources DATA
| Variable | Formula | Description |
|---|---|---|
| hlc3 | (H+L+C)/3 | Typical price |
| hl2 | (H+L)/2 | Median price |
| ohlc4 | (O+H+L+C)/4 | Average price |
Math Operations FUNCTION
Array-aware math operations. All accept arrays or numbers:
| Function | Example | Description |
|---|---|---|
| add(a, b) | add(close, val(10)) | Element-wise addition |
| sub(a, b) | sub(high, low) | Element-wise subtraction |
| mult(a, b) | mult(close, 1.01) | Element-wise multiplication |
| div(a, b) | div(close, open) | Element-wise division (safe, returns null on /0) |
| abs(a) | abs(sub(close, open)) | Absolute value |
| max(a, b) | max(open, close) | Element-wise maximum |
| min(a, b) | min(open, close) | Element-wise minimum |
| neg(a) | neg(close) | Negate each element |
| val(n) | val(100) | Create constant array of value n |
| offset(a, n) | offset(close, 1) | Shift array by n bars (previous values) |
The math object provides standard functions: math.abs, math.sqrt, math.pow, math.log, math.round, math.floor, math.ceil, math.PI, math.sin, math.cos.
Built-in Indicators FUNCTION
| Function | Parameters | Returns |
|---|---|---|
| sma(src, len) | src: number[], len: int | Simple Moving Average |
| ema(src, len) | src: number[], len: int | Exponential Moving Average |
| rsi(src, len) | src: number[], len: int | Relative Strength Index (0-100) |
| stoch(src, h, l, len) | src, high, low arrays + period | Stochastic oscillator (0-100) |
| atr(len) | len: int | Average True Range |
| stdev(src, len) | src: number[], len: int | Standard deviation |
| highest(src, len) | src: number[], len: int | Highest value over period |
| lowest(src, len) | src: number[], len: int | Lowest value over period |
// Bollinger Bands example
var len = 20;
var ma = sma(close, len);
var dev = stdev(close, len);
var upper = add(ma, mult(dev, 2));
var lower = sub(ma, mult(dev, 2));
plot(ma, "MA", "#2962ff", 2);
plot(upper, "Upper", "#26a69a", 1);
plot(lower, "Lower", "#ef5350", 1);
fill(upper, lower, "rgba(41,98,255,0.08)");
Signal Detection FUNCTION
| Function | Returns | Description |
|---|---|---|
| crossover(a, b) | boolean[] | True when a crosses above b |
| crossunder(a, b) | boolean[] | True when a crosses below b |
var fast = ema(close, 9);
var slow = ema(close, 21);
var buySignal = crossover(fast, slow);
var sellSignal = crossunder(fast, slow);
arrow(buySignal, "up", "#26a69a");
arrow(sellSignal, "down", "#ef5350");
plot() DRAWING
Draw a line series on the chart.
plot(data, name, color, width, style)
| Param | Type | Default | Description |
|---|---|---|---|
| data | number[] | required | Array of values to plot |
| name | string | "Plot" | Legend label |
| color | string | "#2962ff" | Line color (hex or rgba) |
| width | number | 1.5 | Line width in pixels |
| style | string | "line" | "line", "dashed", or "dotted" |
plotShape() DRAWING
Draw shapes at specific bars based on a condition.
plotShape(condition, name, shape, location, color, size)
| Param | Type | Options |
|---|---|---|
| condition | boolean[] | Array of true/false per bar |
| shape | string | "circle", "triangleup", "triangledown", "cross" |
| location | string | "abovebar" or "belowbar" |
hline() DRAWING
Draw a horizontal line at a fixed price level.
hline(70, "Overbought", "#ef5350", 1, "dashed");
hline(30, "Oversold", "#26a69a", 1, "dashed");
fill() DRAWING
Fill the area between two data series.
fill(upperBand, lowerBand, "rgba(41,98,255,0.08)");
bgcolor() DRAWING
Color the background of specific bars based on a condition.
var bullish = crossover(ema(close,9), ema(close,21));
bgcolor(bullish, "rgba(38,166,154,0.15)");
arrow() DRAWING
Shortcut for directional arrows (buy/sell signals).
arrow(buyCondition, "up", "#26a69a"); // green up arrow below bar
arrow(sellCondition, "down", "#ef5350"); // red down arrow above bar
label() DRAWING
Place a text label at a specific bar index.
label(barCount - 1, "Latest", "#ff9800", "above");
User Inputs FUNCTION
Inputs create configurable parameters. Values are returned immediately and can be saved per-script.
| Function | Returns | Example |
|---|---|---|
| input.number(name, default, min, max) | number | input.number("Length", 14, 1, 200) |
| input.color(name, default) | string | input.color("Color", "#2962ff") |
| input.bool(name, default) | boolean | input.bool("Show Labels", true) |
| input.select(name, options, default) | string | input.select("Source", ["close","open","hlc3"], "close") |
| input.string(name, default) | string | input.string("Label", "My Label") |
var len = input.number("Length", 14, 1, 200);
var col = input.color("Line Color", "#2962ff");
var show = input.bool("Show Fill", true);
var src = input.select("Source", ["close","hlc3","hl2"], "close");
// Use the source
var srcData = src === "hlc3" ? hlc3 : src === "hl2" ? hl2 : close;
var ma = sma(srcData, len);
plot(ma, "MA", col, 2);
widget.button()
Create a fixed-position button anywhere on screen.
var btn = widget.button("Click Me", {
top: 12, right: 200,
bg: "#2962ff", color: "#fff",
fontSize: 13, radius: 8,
padding: "8px 16px",
shadow: "0 4px 12px rgba(41,98,255,0.3)"
});
btn.onClick(function() {
myPanel.toggle();
});
| Option | Type | Description |
|---|---|---|
| top, right, left, bottom | number (px) | Fixed position on screen |
| bg | string | Background color |
| color | string | Text color |
| fontSize | number | Font size in px |
| radius | number | Border radius in px |
| padding | string | CSS padding value |
| shadow | string | CSS box-shadow value |
widget.toolButton() NEW
Add a button to the left toolbox — looks like a native tool button.
var btn = widget.toolButton("\uD83D\uDCC5", "My Tool", {
position: "bottom" // "top" or "bottom"
});
btn.onClick(function() {
myPanel.toggle();
});
The first argument is an emoji or text icon. The second is the tooltip text.
widget.topBarButton() NEW
Add a button to the top navigation bar.
var btn = widget.topBarButton("My Tool", {
color: "#ff9800",
icon: "\u26A1"
});
btn.onClick(function() { /* ... */ });
widget.panel()
Create an information panel with rows of data.
var panel = widget.panel("Market Data", {
top: 60, right: 20, width: 300,
bg: "#11171f", border: "#2962ff", color: "#d1d4dc"
});
panel.addSection("Prices");
panel.addRow("BTC", "$87,424", "#26a69a");
panel.addRow("ETH", "$1,987", "#ef5350");
panel.addText("Updated every 5 seconds", "#787b86");
panel.show();
| Method | Description |
|---|---|
| .addRow(label, value, color) | Add a key-value row |
| .addSection(text) | Add a section header |
| .addText(text, color) | Add a text paragraph |
| .show() | Make panel visible |
| .hide() | Hide panel |
| .toggle() | Toggle visibility |
widget.table()
Create a data table with headers and rows.
var tbl = widget.table("Watchlist", ["Symbol","Price","Change"], {
top: 60, right: 20, width: 400
});
tbl.addRow(["BTC", {text:"$87,424",color:"#26a69a",bold:true}, "+2.3%"]);
tbl.addRow(["ETH", {text:"$1,987",color:"#ef5350",bold:true}, "-1.1%"]);
Layout CSS
Layout scripts accept standard CSS. Select Layout type in the Creator.
.top-bar {
background: linear-gradient(90deg, #0a0e17, #1a1e2e);
border-bottom: 2px solid #2962ff;
}
.logo {
color: #ff9800;
text-shadow: 0 0 10px rgba(255,152,0,0.3);
}
.toolbox {
background: #0d1117;
}
.tool-btn:hover {
background: rgba(41,98,255,0.2);
}
Hybrid Scripts
Use /* CSS */ blocks or // @css prefix to mix CSS with indicator code:
// @css .top-bar { background: #1a1e2e; }
// @css .logo { color: #26a69a; }
var ma = sma(close, 20);
plot(ma, "Trend", "#26a69a", 2);
Or use block markers:
/* CSS */
.panel-btn.active { background: #ff9800; color: #000; }
/* END CSS */
var r = rsi(close, 14);
plot(r, "RSI", "#ab47bc");
CSS Classes Reference
| Class | Element |
|---|---|
| .top-bar | Top navigation bar |
| .logo | PACTION logo text |
| .btn | Top bar buttons (Search, Alerts, etc.) |
| .toolbox | Left vertical toolbar |
| .tool-btn | Individual tool buttons |
| .tool-sep | Toolbar separator line |
| .chart-panel | Chart container panel |
| .panel-header | Chart panel header (symbol, TFs) |
| .panel-btn | Timeframe buttons |
| .panel-btn.active | Currently selected timeframe |
| .sym-btn | Symbol selector button |
| .chart-grid | Grid containing all chart panels |
| .ind-item | Indicator list items |
| .ind-dot | Indicator color dot |
| body | Page body |
Blocked CSS: @import, expression(), javascript: URLs, -moz-binding, external url() are stripped for security. data:image URLs are allowed.
Example: EMA Crossover Strategy INDICATOR
var fast = input.number("Fast", 9, 2, 50);
var slow = input.number("Slow", 21, 5, 200);
var bullCol = input.color("Bull", "#26a69a");
var bearCol = input.color("Bear", "#ef5350");
var emaF = ema(close, fast);
var emaS = ema(close, slow);
plot(emaF, "Fast EMA", bullCol, 2);
plot(emaS, "Slow EMA", bearCol, 2);
fill(emaF, emaS, "rgba(41,98,255,0.06)");
var buy = crossover(emaF, emaS);
var sell = crossunder(emaF, emaS);
arrow(buy, "up", bullCol);
arrow(sell, "down", bearCol);
bgcolor(buy, "rgba(38,166,154,0.1)");
bgcolor(sell, "rgba(239,83,80,0.1)");
Example: Bollinger Bands INDICATOR
var len = input.number("Length", 20, 5, 100);
var m = input.number("Multiplier", 2, 0.5, 5);
var basis = sma(close, len);
var dev = stdev(close, len);
var upper = add(basis, mult(dev, m));
var lower = sub(basis, mult(dev, m));
plot(basis, "Basis", "#ff9800", 1);
plot(upper, "Upper", "#2962ff", 1, "dashed");
plot(lower, "Lower", "#2962ff", 1, "dashed");
fill(upper, lower, "rgba(41,98,255,0.06)");
Example: RSI Oscillator Panel INDICATOR
oscPanel(120);
var len = input.number("RSI Length", 14, 2, 50);
var r = rsi(close, len);
plot(r, "RSI", "#ab47bc", 2);
hline(70, "Overbought", "#ef5350", 1, "dashed");
hline(30, "Oversold", "#26a69a", 1, "dashed");
hline(50, "Mid", "#787b86", 0.5, "dotted");
Note: oscPanel(120) reserves a 120px panel below the chart, similar to the built-in Cyborg indicator.
Example: Candle Coloring INDICATOR
// Highlight high-volume candles
var avgVol = sma(volume, 20);
var highVol = [];
for (var i = 0; i < barCount; i++) {
highVol.push(volume[i] > avgVol[i] * 2);
}
bgcolor(highVol, "rgba(255,152,0,0.12)");
// Mark hammer candles
var hammers = [];
for (var i = 0; i < barCount; i++) {
var body = math.abs(close[i] - open[i]);
var range = high[i] - low[i];
var lowerWick = math.min(open[i], close[i]) - low[i];
hammers.push(range > 0 && body / range < 0.3 && lowerWick / range > 0.6);
}
plotShape(hammers, "Hammer", "triangleup", "belowbar", "#26a69a", 6);
Example: Info Dashboard
var panel = widget.panel("\uD83D\uDCCA Market Info", {
top: 60, right: 20, width: 280,
bg: "#11171f", border: "#2962ff"
});
var lastClose = close[barCount - 1];
var prevClose = close[barCount - 2];
var change = ((lastClose - prevClose) / prevClose * 100);
var changeStr = (change >= 0 ? "+" : "") + change.toFixed(2) + "%";
var changeCol = change >= 0 ? "#26a69a" : "#ef5350";
panel.addRow("Price", lastClose.toFixed(2), "#d1d4dc");
panel.addRow("Change", changeStr, changeCol);
panel.addRow("High", math.max(high[barCount-1], high[barCount-2]).toFixed(2), "#26a69a");
panel.addRow("Low", math.min(low[barCount-1], low[barCount-2]).toFixed(2), "#ef5350");
panel.addRow("Volume", volume[barCount-1].toFixed(0), "#787b86");
panel.show();
Example: Economic Calendar
var ecoPanel = widget.panel("\uD83D\uDCCA Economic Calendar", {
top: 200, left: 72, width: 340,
bg: "#11171f", border: "#00ff9d", color: "#e0e7ff"
});
ecoPanel.addSection("Today's Events");
ecoPanel.addRow("NFP", "245K", "#ff4d4d");
ecoPanel.addRow("CPI YoY", "2.8%", "#00ff9d");
ecoPanel.addRow("Unemployment", "4.1%", "#ffffff");
ecoPanel.addRow("Fed Rate", "4.25%", "#ff4d4d");
ecoPanel.addRow("GDP QoQ", "2.3%", "#00ff9d");
ecoPanel.addSection("Info");
ecoPanel.addText("Click button again to close");
var btn = widget.toolButton("\uD83D\uDCC5", "Economic Calendar");
btn.onClick(function() {
ecoPanel.toggle();
});
Example: Matrix Theme LAYOUT
body {
background: #000;
color: #00ff41;
}
.top-bar {
background: #000;
border-bottom: 1px solid #00ff41;
box-shadow: 0 0 10px #00ff41;
}
.logo {
color: #00ff41;
text-shadow: 0 0 5px #00ff41, 0 0 15px #00ff41;
}
.toolbox {
background: #000;
border: 1px solid #00ff41;
}
.tool-btn:hover {
background: #00ff41;
color: #000;
}
.panel-btn.active {
background: #00ff41;
color: #000;
}
input, select {
background: #000;
color: #00ff41;
border: 1px solid #00ff41;
}
PactionScript v1.0 — Back to Paction
Last updated: March 2026