Appearance
var and varip
How do you keep a value from one bar to the next? Declare it with var. A var declaration runs once, on the first bar that reaches it, and every bar after that starts with the value the bar before left. varip keeps a value the same way and also keeps what each update of a live bar writes.
pine
//@version=6
indicator("Bars since the best close")
var float best = close // set once, on the first bar
var int since = 0
if close > best
best := close
since := 0
else
since += 1
plot(since, "Bars since")var
A script runs once a bar, so a plain declaration runs on every bar. int n = 0 followed by n += 1 reads 1 on every bar, because each bar declares n again. Write var int n = 0 and the declaration runs on the first bar only, so n += 1 counts the bars.
The value after = is worked out once, on that first bar, and kept: var float first = close holds the first bar's close for good. Change a var with :=, += and the other assignments, and the next bar starts from the new value. Running the declaration's line again doesn't reset it.
A var inside a block is set the first time that block runs, which can be long after bar 0: under if bar_index >= 10, var float seen = close holds bar 10's close. Inside a function, each place the function is called from keeps its own var, so two calls never share a count. State in functions explains why.
A var that starts as na needs its type: var float level = na. Strict Pine refuses var level = na, as TradingView does.
Collections, objects and drawings
var keeps whatever the declaration made, so it's how a script builds something up over many bars:
| Declaration | Without var | With var |
|---|---|---|
array<float> closes = array.new<float>() | an empty array on every bar | one array, pushed onto by every bar |
label tag = label.new(bar_index, high, "high") | a new label on every bar, until the limit drops the oldest | one label, which label.set_xy moves |
Swing s = Swing.new() | a new object on every bar | one object whose fields each bar changes |
The same holds for a matrix, a map and every drawing type. Collections and Types and enums show them in use.
On a live bar
On a live chart the forming bar runs again on every update, and each update starts from the state the bar began with. A var goes back to its value at the start of the bar before each update, so a var counter counts bars, never updates. Each update of the live bar has the whole rule.
varip
varip declares a value that survives a live bar's updates. Like var it's set once and kept from bar to bar, and unlike var it keeps what each update wrote, so it can count the updates themselves:
pine
//@version=6
indicator("Updates of the live bar")
varip int updates = 0
if barstate.isnew
updates := 0 // a new bar starts the count again
updates += 1
plot(updates, "Updates")On history every bar runs once, so there varip reads exactly as var does, and the two part only on live updates. varip works wherever var does:
- inside a function, it keeps its value per call site;
- on a collection, it keeps what each update pushed;
- on a type's field, as in
varip int ticks = 0, it keeps its updates while the object's other fields go back to the bar's start.
A varip keeps only what live updates added since the script last ran whole. A whole run, after an input change or a newly loaded series, builds every bar again and starts it over. In bar replay a varip acts as a var, so a step reads what a jump to the same time reads.
varip and leak-safe runs
A value that depends on how many updates arrived has no equal on history, so a backtest can't reproduce it. A Pine script with varip still runs, with a leak warning, as TradingView runs it. Every AmenoScript text runs leak-safe, and a leak-safe run refuses it:
text
Leak-safe AmenoScript refuses this: `varip` keeps a value across a live
bar's updates, which history never has: use `var`See what a leak-safe run refuses. A chart runs a script with varip in your browser, never on the terminal's server, whose engine would read varip as var. See where your script runs.
Traps
- A
varholds its first bar's value.var float level = closedoesn't follow the price. Assign it with:=on the bars where it should move. - A
varin a branch starts when the branch first runs. It takes the value of the first bar that enters the block, not bar 0's. - A
varipcount isn't repeatable. It depends on how many updates the feed sent while the chart was open, and a reload starts it over. Draw with it, and keep decisions onvarand closed bars.
See also
- How a script runs, the bar-by-bar model and the forming bar
- State in functions, a
varper call site - Leak-safe runs, why AmenoScript refuses
varip - var and varip in the reference