Rules that decide whether your text compiles

One statement, one line

A newline ends a statement. That is true inside an argument list too, so a call split over several lines is a parse error. Write the call on one line however long it becomes.

Rejected, then accepted
// Rejected: "Expected expression, found"
plot.line(
  ta.sma(close, 20),
  "#22C55E"
)

// Accepted
plot.line(ta.sma(close, 20), "#22C55E", 2, "solid")

Braces open on the same line

The opening brace of an if branch or a function body must sit on the same line as the condition or the signature. A closing brace may be followed by else on the same line or on the next line. Chained else if is supported. When only a value depends on the condition, the conditional expression condition ? a : b is shorter than a branch.

if close > open {
  plot.marker(true, high, "#22C55E", "triangle", "above", 8, 2)
} else if close < open {
  plot.marker(true, low, "#EF4444", "triangle", "below", 8, 2)
} else {
  plot.marker(true, close, "#9CA3AF", "diamond", "above", 8, 2)
}

Declarations live at the top level

A top level let or var declares a series, and a series must be declared at the top level of the script, never inside an if branch. Inside an if branch you may assign to an existing var with := or a compound operator such as +=, and you may call plot functions. Inside a function body or a loop body, let declares a local instead: a plain value for the rest of that block, which may be reassigned.

// Rejected: "Series declarations must be top level"
if close > open {
  let body: float = close - open
}

// Accepted
var up_bars: float = 0
up_bars := nz(up_bars[1], 0)
if close > open {
  up_bars += 1
}

Other lexical rules

  • Comments start with // and run to the end of the line. There is no block comment.
  • Strings use double quotes, cannot span lines, and support the escapes \n, \t, \" and \\.
  • Numbers may be decimal or scientific, for example 12, 0.25, .5 and 1e3.
  • Identifiers use letters, digits and underscore, and cannot start with a digit. let, var, if, else, fn, return, true, false, while and for are reserved words. to, by, break and continue only mean something where a loop uses them.
  • math.pi, math.e and the colour names color.aqua, color.black, color.blue, color.fuchsia, color.gray, color.green, color.lime, color.maroon, color.navy, color.olive, color.orange, color.purple, color.red, color.silver, color.teal, color.white and color.yellow are constants, written without parentheses.
  • Builtin names such as ta.sma and plot.line are single names. The dot is part of the name, not property access.
  • A semicolon also separates statements, so two short statements may share a line.
  • The source is UTF-8 and is limited to 65,536 bytes.

Every layer of the market, Orderflow to optionflow, on one chart.

Institutional grade Orderflow data with backtesting and journaling built in. Join the waitlist for early access.

Get Access