Aug 12, 2025 • 17 min read

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.isrealtime is true during live updates; barstate.isconfirmed is true only after the bar closes.
  • timeframe.change() and ta.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 na in v6. Use guards around series that can be na.
  • Reset var state on boundaries explicitly (session change, symbol change) if required.
  • Mixing var and varip? 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

Does varip persist across symbols or reloads?

No. varip lives only within the current bar’s intrabar updates. It resets on the very next bar.

When should I prefer arrays over var scalars?

Use arrays for collections (watchlists, rolling windows); use var scalars for single persistent values.