Getting started
The shape of a script
Every script is one module with two parts:
import { src, ta, param, config, series, plot, declarePlot, color } from "@coinray/strategy";
// 1. Top level: runs ONCE, when the script loads.
// Declare inputs, plot styles, alerts, extra series and data sources here.
const length = param.int("Length", 20, 2, 500);
config.warmup(100);
declarePlot("basis", color.blue, 2);
const spread = series();
// 2. onBar(): runs for every bar.
export function onBar(): void {
const basis = ta.sma(src.close, length);
spread[0] = src.close[0] - basis[0];
plot("basis", basis);
}
Some calls are only allowed at top level, because the host must know about them
before the first bar: series(), param.*, config.warmup, config.title, declarePlot,
hline, declareAlert, request.timeframe, orderflow() and
derivatives(). Everything else, including every ta.* call, belongs inside
onBar().
Naming the script
config.title sets the name shown in the chart legend and the settings dialog.
Without it the chart shows a generated id.
config.title("24-hour Volume");
config.description("Volume traded over the trailing 24 hours");
Price data
src holds the current symbol's bars as series:
| Series | Value |
|---|---|
src.open, src.high, src.low, src.close | Prices |
src.volume | Base volume |
src.hl2, src.hlc3, src.ohlc4, src.hlcc4 | Derived prices |
src.time | Bar open time, unix seconds |
Index a series to read it: src.close[0] is the current bar, src.close[1]
the previous one. Reads beyond the loaded history return na (NaN).
Inputs
Inputs appear in the script's settings dialog. Declare them at top level:
const len = param.int("Length", 14, 2, 200); // name, default, min, max
const mult = param.float("Multiplier", 2.0, 0.1, 10.0);
const showLabels = param.bool_("Show labels", true);
const mode = param.options("Mode", 0, ["Fast", "Slow"]); // returns the index
const source = param.source("Source", src.close);
const tf = param.timeframe("Higher timeframe", "240");
const upColour = param.color("Up colour", color.green); // colour picker
const since = param.time("Start", 1767225600); // date picker, unix seconds
param.meta("Length", "Main", "Bars in the lookback window"); // group, tooltip
Plots
plot(name, value) draws a line in the price pane; plotPane(name, value, pane)
draws it in a separate pane. Both accept a number or a series. Style a plot once
at top level with declarePlot, and add fixed levels with hline:
declarePlot("rsi", color.purple, 2, PlotStyle.Line, "rsi");
hline(70, color.red, Stroke.Dashed, "rsi");
hline(30, color.green, Stroke.Dashed, "rsi");
export function onBar(): void {
plotPane("rsi", ta.rsi(src.close, 14), "rsi");
}
A na value draws nothing for that bar.
PlotStyle.Columns and PlotStyle.Histogram draw bars, PlotStyle.Circles
draws dots, and fillTo shades the area between two plots in the price pane.
StepLine, Area and Cross currently draw as a line.
Pass a colour as the last argument to colour a single bar, like Pine's
plot(x, color = ...):
declarePlot("volume", color.gray, 1, PlotStyle.Columns, "vol");
export function onBar(): void {
const up = src.close[0] >= src.open[0];
plotPane("volume", src.volume, "vol", up ? color.green : color.red);
}
declarePlot's last argument, offset, shifts a plot by a number of bars
(Pine's plot(offset = n)), for example 26 for an Ichimoku cloud.
Warmup
config.warmup(bars) tells the host how much history to load before the first
bar your script cares about. Set it to the longest lookback you use. Too small
and indicators start na; too large only costs load time.
AssemblyScript in five minutes
- Numbers have types. Prices and indicator values are
f64. Integers arei32(ori64for times and bar indexes). Convert explicitly:f64(length),i32(value). naisNaN. Test withna(x), neverx == NaN. Replace withnz(x, 0).- No closures over local variables. Arrow functions cannot capture a
surrounding
const. Use a module-level function or a class. - No
any,undefinedor union types. Every value has one concrete type. - Maps trap on a missing key. Use
mapGet(m, key), which returnsna, instead ofm.get(key). - A runtime error stops the script for good (until it is reloaded). Guard
divisions and array indexes, or call
runtimeError("reason")yourself to stop with a clear message.