How Pine Script Executes#

Bar-by-Bar Execution#

The core execution concept of Pine Script is bar-by-bar execution.

When a script is applied to a chart, TradingView starts from the oldest bar on the chart and executes the full script once for each bar in sequence, all the way to the most recent bar.

A simple example:

//@version=6
indicator("Execution Demo", overlay=true)

plot(close)

This script executes plot(close) for every bar, so the chart displays a line connecting all closing prices — the cumulative result of the script running on each bar.

Historical Bars vs. Realtime Bar#

When a script executes, it encounters two types of bars:

  • Historical bars: Completed bars with fixed, unchanging values
  • Realtime bar: The current bar in progress, updated with every new tick

Execution on Historical Bars#

For historical bars, the script executes only once (at bar close), and the result never changes.

Execution on the Realtime Bar#

For the realtime bar, the script re-executes with every new tick. This means:

  • close on the realtime bar represents the latest traded price, not the final closing price
  • The script’s output changes continuously until the bar closes

After the bar closes, the result of the last execution is committed as the historical value and will not change.

You can use the built-in variable barstate.isrealtime to check whether the script is currently executing on the realtime bar:

if barstate.isrealtime
    label.new(bar_index, high, "Realtime Bar")

Series#

The most important concept in Pine Script is the Series.

A series is a collection of values that change over time, with each bar corresponding to one value in the series. The built-in variables close, open, high, low, and volume are all series.

To access past values of a series, use the [] operator:

close      // Current bar's close price
close[1]   // Previous bar's close price
close[2]   // Two bars ago's close price
close[10]  // Close price 10 bars ago

This makes calculating technical indicators very intuitive. For example, computing the 2-bar price change:

//@version=6
indicator("2-Bar Price Change")

change2 = close - close[2]
plot(change2)

bar_index#

bar_index is a built-in variable that represents the index of the current bar, starting from 0 (oldest bar is 0; newer bars have higher indices).

//@version=6
indicator("bar_index Demo")

// Label the index value on the rightmost bar
if barstate.islast
    label.new(bar_index, high, str.tostring(bar_index))

Common uses of bar_index:

  • Checking whether it’s the first or last bar
  • Calculating the number of bars between two points in time

Common barstate Variables#

VariableDescription
barstate.isfirstWhether this is the first (oldest) bar
barstate.islastWhether this is the last (most recent) bar
barstate.ishistoryWhether this is a historical bar
barstate.isrealtimeWhether this is the realtime bar
barstate.isconfirmedWhether the realtime bar has been confirmed (closed)

Comparison with MultiCharts Execution Model#

Readers with a MultiCharts/PowerLanguage background can refer to the following comparison:

Pine ScriptPowerLanguage (Signal)
Historical barsExecute once per barExecute once per bar (Bar by Bar)
Realtime bar (not closed)Execute on every tickNot executed by default (requires IOG)
Realtime bar (after close)Execute and commitExecute
Access past N barsclose[N]Close[N]

The realtime bar behavior of Pine Script is equivalent to a MultiCharts indicator script with IOG enabled.

Reference#