Skip to main content

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:

SeriesValue
src.open, src.high, src.low, src.closePrices
src.volumeBase volume
src.hl2, src.hlc3, src.ohlc4, src.hlcc4Derived prices
src.timeBar 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 are i32 (or i64 for times and bar indexes). Convert explicitly: f64(length), i32(value).
  • na is NaN. Test with na(x), never x == NaN. Replace with nz(x, 0).
  • No closures over local variables. Arrow functions cannot capture a surrounding const. Use a module-level function or a class.
  • No any, undefined or union types. Every value has one concrete type.
  • Maps trap on a missing key. Use mapGet(m, key), which returns na, instead of m.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.