Indicator API
The full Context, metadata schema, conditional colors, and AssemblyScript subset.
This is the reference for the indicator API: the Context object your calc() function receives, the metadata schema that shapes it, and the
AssemblyScript subset you can use.
The entry point
Every indicator defines exactly one top-level function:
function calc(ctx: Context): void It returns nothing. Outputs are written to ctx.plots. The chart calls it once
per bar, oldest first; for the live bar it's called repeatedly as ticks arrive.
Context
| Member | Type | Description |
|---|---|---|
ctx.bar | Bar | The current bar — see below. Read-only. |
ctx.bars | BarHistory | Historical ring buffer, max 200 bars. Index 0 = current bar, 1 = previous, etc. Read-only. |
ctx.inputs | generated | Your declared inputs as typed fields. Read-only. |
ctx.plots | generated | Your declared plots. Writable. Reset to NaN on every call. |
ctx.barIndex | i32 | 0-based bar index. Stable across live ticks of the same bar. |
ctx.isNewBar | bool | true on the first call for a bar; false on live ticks of the same bar. |
Bar
The current bar's OHLCV plus a timestamp:
declare class Bar {
readonly open: f64;
readonly high: f64;
readonly low: f64;
readonly close: f64;
readonly volume: f64;
readonly timestamp: f64; // Unix seconds, UTC
} Timestamp is Unix seconds, UTC. There is no timezone API and no
per-period info exposed inside the sandbox — you can't tell whether you're on 1m or 1H
from inside calc(). For hour-of-day or day-index logic, use integer math:
const t = <i32>ctx.bar.timestamp;
const utcHour = (t / 3600) % 24;
const utcDay = t / 86400; BarHistory
declare class BarHistory {
readonly count: i32; // up to 200
open(barsBack: i32): f64; // 0 = current bar
high(barsBack: i32): f64;
low(barsBack: i32): f64;
close(barsBack: i32): f64;
volume(barsBack: i32): f64;
} Returns NaN when barsBack >= count. Use only for the lookback
pattern — incremental indicators must keep state in module-level variables instead.
Inputs and Plots
These two classes are generated from your metadata, so the exact shape depends on what you declared. The editor's autocomplete reflects your current metadata in real time. As a reference, an indicator with one int input and three plots gets:
declare class Inputs {
readonly length: i32;
}
declare class Plots {
upper: f64;
middle: f64;
lower: f64;
} For plots that declare a colors array, an additional <name>Color: u32 field appears for selecting the per-bar color index.
Metadata schema
The full set of fields you can declare:
Top level
name— display name. Max 50 chars; letters / digits / spaces /-/./_/(/).shortName— short label shown on the chart. Same charset rules.overlay—truedraws on the price pane;falseopens a separate pane below (RSI, MACD).precision— optional, non-overlay only. Number of decimals on the price axis.inputs— see below.plots— see below.bands— optional horizontal reference lines.filledAreas— optional filled zones between two plots or two bands.
Inputs
| Type | AS type | Notes |
|---|---|---|
int | i32 | Supports default, min, max. |
float | f64 | Supports default, min, max. |
source | — | Price selector (close / open / high / low / hl2 / hlc3 / ohlc4). Resolved by the platform; not exposed inside calc — the selected value is written into bar data instead. |
Plots
Only type: "line" is supported (no shapes, arrows, or bar-colorers). Style
variants:
line,histogram,columns,area,stepLine,circles,cross- With breaks:
lineWithBreaks,stepLineWithBreaks,areaWithBreaks
Plot fields:
color— 6-char hex only (#RRGGBB). No alpha, norgb(), no CSS keywords. These crash the chart.linewidth1–4,linestylesolid | dotted | dashed,transparency0–100.title,visible,showOnPriceScale,showInDataWindow,showInStatusLine,trackPrice.colors— array of hex colors for conditional per-bar coloring (see below).offset— visual shift in bars. Number for fixed shift, string for input ref ("offset": "displacement"), or negated string for left shift.
Pick lineWithBreaks for intermittent plots — session
ranges, signal lines, "only when condition X" outputs. Plain line draws
straight across NaN bars, connecting gaps you don't want connected.
Bands and filled areas
Bands are horizontal reference lines: { value, name?, color?, linewidth?, linestyle?, visible? }.
Useful for RSI 30 / 70 or any oscillator zero-line.
Filled areas are semi-transparent fills between two plots or two bands: { from, to, color?, transparency?, title? }. Use them between plots for
clouds (Bollinger, Ichimoku) and between bands for zone shading (RSI 30–70).
Conditional colors
Adding a colors array to a plot creates a <name>Color: u32 field on ctx.plots that picks which color to use per bar. The static color field is ignored when colors is set; out-of-range indices
are clamped.
"hist": { "type": "line", "style": "columns",
"colors": ["#26A69A", "#B2DFDB", "#EF5350", "#FFCDD2"] } ctx.plots.hist = value;
ctx.plots.histColor = value >= 0 ? (rising ? 0 : 1) : (falling ? 2 : 3); AssemblyScript gotchas
AS is TypeScript-shaped but stricter. The traps people hit most often:
- Strict types. No
any,undefined,null, or unions. Usef64for prices,i32for counters,bool,void. - Untyped numeric literals default to
i32. Annotate floats explicitly:let x: f64 = 0.0;. - Casts use angle brackets.
<f64>(len). - No closures. Functions can't capture outer-scope variables.
- No
try / catch / throw, noasync, no Promises, no imports. - No
for..of. Use index-basedforloops. Math.minandMath.maxtake exactly two arguments, not rest args.- No dynamic property access (
obj[key]), no string manipulation beyond==, no JSON, no regex.
What you can use:
- Classes with getters/setters,
for/while/if/switch,const/let(novar). StaticArray<T>,Array<T>.Math.{sqrt, abs, pow, min, max, log, exp, floor, ceil, round, PI, E},NaN,Infinity,isNaN(),isFinite().
Something missing or wrong? Email support@strategytune.com.