Let Bindings
Naming intermediate expressions for reuse and offset-indexing.
let name = expr binds name to expr for reference later in the query: in the core-logic body, columns, sort, or a later let's own expression. let statements live in the header, alongside the pragmas, and are the only mechanism for naming an intermediate expression: there's no separate "multiline indicator" construct.
let rsiVal = rsi(14)
let isOverbought = rsiVal > 70
columns = [close, rsiVal, isOverbought]
isOverboughtTyping
A binding's type is determined by its right-hand side:
- A value expression right-hand side (
rsi(14),sma(50)) produces a numeric binding: usable anywhere a value expression is valid:columns,sort, comparator operands, and as an operand inside anotherlet's expression. - A boolean expression right-hand side (
rsi(14) > 70) produces a boolean binding: usable anywhere a boolean expression is valid (the core-logic body, and insideand/or/not), and additionally insidecolumns.
Using a binding where its type doesn't fit is a parse error: a numeric binding can't stand alone as the core-logic body (it needs a comparator), and a boolean binding can't be used as a comparator operand or inside sort.
let isOverbought = rsi(14) > 70
isOverbought and close > sma(20) // fine: boolean composes with andlet rsiVal = rsi(14)
rsiVal // parse error: numeric binding, core-logic body needs a booleanDeclare Before Use
A reference to a let name is only valid after its declaration in the query text. Forward references (including one let referencing another declared later) are rejected:
let isOverbought = rsiVal > 70 // error: rsiVal not yet declared
let rsiVal = rsi(14)The same rule applies to columns referencing a let declared later in the text, and to redeclaring a name that's already bound (let rsiVal = ... twice).
Reserved Names
A let name can't collide with any bare series identifier (close, open, high, low, volume), function name, cross primitive (crossover, crossunder, cross), logical or direction keyword (and, or, not, asc, desc), or pragma key (market, timeframe, columns, sort, limit).
let close = rsi(14) // error: reserved
let and = rsi(14) > 70 // error: reservedOffset Indexing, Not Timeframe Qualification
A let reference supports offset indexing (name[-N]) using the same grammar as any other expression:
let isOverbought = rsi(14) > 70
isOverbought[-1] // isOverbought, evaluated one bar backIt does not accept a timeframe qualifier: the binding's timeframe was already fixed by its own right-hand side at declaration time:
let isOverbought = rsi(14) > 70
h4::isOverbought // parse errorIf you need the binding on a different timeframe, qualify the timeframe inside the let's own expression instead: let isOverbought = h4::rsi(14) > 70.