Arithmetic
| Operator | Meaning | Example |
|---|---|---|
+ |
add | a + b |
- |
subtract / negate | a - b, -a |
* |
multiply | a * b |
/ |
divide | a / b |
% |
modulo | a % b |
Division is always floating-point. / on two integer operands still produces a float — use math.floor(a / b) for truncation.
Comparison
| Operator | Meaning | Returns |
|---|---|---|
== |
equal | bool |
!= |
not equal | bool |
< |
less than | bool |
> |
greater than | bool |
<= |
less than or equal | bool |
>= |
greater than or equal | bool |
NaN propagates: na == na is na (which reads as false), as is na == 0. Use na(x) to test for na.
Logical
and or not
Logical operators work on booleans (and on anything that converts to a boolean — na and 0 read as false, every other number reads as true). Short-circuit evaluation applies:
safe = volume > 0 and (high - low) / volume < 100
String concatenation
+ concatenates two strings. Mixed-type concatenation is not implicit — convert first:
msg = "Close is " + str.tostring(close)
Conditional expression
value = cond ? thenExpr : elseExpr
Nested ternaries are allowed and often read best when each branch is on its own line:
regime =
close > ta.sma(close, 50) ? "up"
: close < ta.sma(close, 50) ? "down"
: "flat"
The two branches must share a type (both int, both float, both the same UDT, etc.). An int on one side and a float on the other auto-promotes to float.
Assignment and reassignment
rsi = ta.rsi(close, 14) // declaration + initial assignment
rsi := nz(rsi, 50) // reassignment (`var`-style target)
=is first-time declaration.:=is reassignment of an existingvar/variptarget or of a local that lives inside the current function body.
A plain = cannot reassign; a plain := cannot declare.
Historical access ([])
prevClose = close[1]
rsiAgo = ta.rsi(close, 14)[5]
x[n] returns x as it was n bars ago. n must be a non-negative integer that is itself simple or series. The implementation caches each referenced series' recent history (depth grows dynamically as scripts request further-back values).
Collection indexing
Arrays, maps, and matrices use method-call accessors (array.get, map.get, matrix.get) rather than square brackets. The square-bracket form is reserved for historical lookback.
Member access (.)
syminfo.ticker
color.new(color.red, 50)
pivot.price
. navigates namespaces, UDT fields, and enum members.
in (membership test)
Used only inside for … in to iterate over an array:
for value in prices
total += value
Precedence
From highest to lowest:
[](historical access).(member access), function call(…)- Unary
-,not *,/,%+,-<,>,<=,>===,!=andor? :(ternary)=,:=(assignment / reassignment — right-associative)
Parentheses override precedence as expected.
See also
- Type system — type promotion rules
- Conditional structures —
if/switchstatements - Variable declarations —
var,varip,:=