Pine v6: var vs varip vs const — State Management and Real‑Time Semantics
The most common Pine confusion is persistent state. This guide demystifies var, varip, and const, the bar update model, and safe patterns for robust indicators and strategies.
The Pine bar update model in 60 seconds
- Every historical bar executes once. The current (real-time) bar can execute multiple times as price updates.
barstate.isrealtimeis true during live updates;barstate.isconfirmedis true only after the bar closes.timeframe.change()andta.change(time(tf))help detect new bars/sessions and HTF boundaries.
What <code>var</code> does
var initializes once on the first script execution, then persists across all future bars. Use it for long‑lived state like arrays, tables, labels, rolling stats, and previous values you must remember across bars.
//@version=6
indicator("Session High/Low", overlay=true)
sess = input.session("0930-1600", "Session")
inSess = time(timeframe.period, sess)
var float sessHigh = na
var float sessLow = na
newSess = ta.change(inSess)
if newSess
sessHigh := high
sessLow := low
else
sessHigh := math.max(sessHigh, high)
sessLow := math.min(sessLow, low)
plot(sessHigh, color=color.new(color.orange, 0))
plot(sessLow, color=color.new(color.orange, 0))
What <code>varip</code> does
varip persists only within the current real‑time bar. It resets at the next bar open. Use for intrabar accumulation like micro‑high/low, tick counters, or per‑bar running stats. It won’t pollute state across bars.
//@version=6
indicator("Intrabar Extremes (varip)", overlay=false)
varip float hi = na
varip float lo = na
hi := na(hi) ? high : math.max(hi, high)
lo := na(lo) ? low : math.min(lo, low)
plot(hi, color=color.new(color.lime, 0))
plot(lo, color=color.new(color.red, 0))
What <code>const</code> does
const creates compile‑time constants. Use it for values that never change (e.g., immutable color palettes, fixed ratios) to improve clarity and allow potential compile‑time optimizations.
//@version=6
indicator("Using const", overlay=false)
const float GOLDEN = 1.618
plot(close / ta.ema(close, 55) * GOLDEN)
Choosing between var and varip
- Need state across bars? Use var.
- Need state only within the current live bar? Use varip.
- Need a constant at compile time? Use const.
Patterns: labels and arrays safely
//@version=6
indicator("Label Reuse", overlay=true)
var label lab = na
if barstate.islast
if na(lab)
lab := label.new(bar_index, close, text="Hi", style=label.style_label_down)
else
label.set_x(lab, bar_index)
label.set_y(lab, close)
Reusing a single label via var prevents memory growth. For arrays, initialize once with var and update in place.
Edge cases and gotchas in v6
- Booleans are never
nain v6. Use guards around series that can bena. - Reset
varstate on boundaries explicitly (session change, symbol change) if required. - Mixing
varandvarip? Document the intent—intrabar vs interbar—so future edits don’t regress behavior.
For repaint‑safe patterns and HTF confirmation, see our guides onrepaint pitfalls andMTF design.
FAQ
varip persist across symbols or reloads?No. varip lives only within the current bar’s intrabar updates. It resets on the very next bar.
var scalars?Use arrays for collections (watchlists, rolling windows); use var scalars for single persistent values.