Spectra
Browse docs

scripting

Grammar

Keywords, types, and the expression grammar of the Spectra DSL in EBNF.


The Spectra DSL has a small grammar. If you've used Pine Script or TypeScript, almost everything will look familiar — the surface area is deliberately compact.

Keywords

let const fn if else for while in
return yield break continue
true false null
output plot mark notify draw_zone
buy sell sell_all

Primitive types

int       // 64-bit signed
float     // 64-bit double
bool      // true | false
str       // UTF-8 string
time      // bar timestamp (epoch ms)
series<T> // historical sliding window of T
color     // theme name or hex

Expressions in EBNF

expr     = literal | ident | call | binop | unop | index | block ;
binop    = expr ( "+" | "-" | "*" | "/" | "%" |
                  "==" | "!=" | "<" | ">" | "<=" | ">=" |
                  "and" | "or" ) expr ;
unop     = ( "-" | "not" ) expr ;
call     = ident "(" [ args ] ")" ;
fn_decl  = "fn" ident "(" [ ident ("," ident)* ] ")" block ;
args     = expr ("," expr)* | named ("," named)* ;
named    = ident "=" expr ;
index    = expr "[" expr "]" ;        // series[N] reads N bars back
block    = "{" stmt* "}" ;

A complete script

let fast = sma(close, 12)
let slow = sma(close, 26)
let signal = cross_up(fast, slow)
plot(fast, color: accent)
plot(slow, color: text_1)
output signal

The output line is the script's primary value. The chart, backtester, and cloud worker all read it.

Execution callbacks

step(i) is the bar callback. on_trade is the individual-execution callback and has a fixed four-argument signature:

fn on_trade(price, size, is_buy, ts) {
  // price/size: float, is_buy: bool, ts: Unix milliseconds
}

Both callbacks may exist in one script. When an execution closes a bar, on_trade runs first and the bar step runs second. See Tick-based scripting for availability and retention limits.