UtilityPine Script v6

ta.barssince()First Occurrence, na and Dynamic Windows

Pine Script ta.barssince(condition) counts bars since the latest true condition. It returns 0 on each true bar and na before the first match in the available history.

Pine Script v6 reference verified: · TradingView reference

Syntax

Syntax
ta.barssince(condition) → series int

Arguments

ParameterTypeDescription
conditionseries boolA condition evaluated on every bar. Every true bar resets the count, including consecutive true bars.

Returns

A series int: 0 on a matching bar, 1 on the next nonmatching bar, then 2, 3, and so on until another match. Before any match, the result is na.

Remarks

Call ta.barssince on every bar, outside conditional branches. The result is a bar distance, not a count of events or elapsed clock time. A condition that changes on an open bar can change the current result.

Trace the first ten bars

Assume events on bars 2, 5 and 6. Bar numbers start at the first loaded bar, not at the first visible bar. The first code example repeats this event pattern every ten bars.

Bar indexEventRaw countnz(count) + 1
0falsena1
1falsena1
2true01
3false12
4false23
5true01
6true01
7false12
8false23
9false34
At bar 4, the distance from bar 2 is 4 - 2 = 2, but the inclusive window contains three bars: 2, 3 and 4. Bar 6 resets again even though bar 5 was already true. Before bar 2, length 1 is only a calculation fallback; no event has occurred.

Set the window policy before replacing na

The first example computes the high over the event bar through the current bar. Its fallback length is 1 before the first event, but its high output stays hidden until an event exists. Replacing na in the length does not establish a real event.

The 100-bar cap is a deliberate limit. With another condition, a gap longer than 99 bars would exclude the original event bar from the window. Raising max_bars_back reserves history; it does not change that cap or make an unbounded lookback safe. See TradingView's dynamic-length guidance.

An intrabar reset can disappear

Suppose the last confirmed event was bar 6 and bar 9 is open. If its price rises above its open, the live counter becomes 0. If price falls back below the open on a later update, rollback lets the counter return to 3. This is a revised condition on one bar, not three new bars arriving.

In the second example, the confirmed counter accepts an event only at the closing update. Compare both plots on an open bar, then reload after the close. Historical bars cannot reproduce the discarded ticks. Read TradingView's realtime execution model and bar confirmation rules.

Use the sequence as a debugging contract

Give the Pine Script AI Coding Agent your smallest failing script and the expected count sequence above. Ask it to preserve the pre-event behavior, event timing and maximum window when generating a correction. Run a syntax check, then compare the Data Window values in TradingView. Syntax acceptance alone does not verify event timing.

Continue with the TradingView coding guides for related Pine Script debugging tasks.

Code Examples

Deterministic event sequence and a bounded inclusive window
//@version=6
indicator("Bars since: sequence and window", max_bars_back = 100)
int phase = bar_index % 10
bool event = phase == 2 or phase == 5 or phase == 6
int count = ta.barssince(event)
int length = math.min(nz(count) + 1, 100)
float windowHigh = ta.highest(high, length)
plot(count, "Raw count", color = color.blue, style = plot.style_stepline)
plot(length, "Inclusive length", color = color.orange)
plot(event ? 1 : 0, "Event", display = display.data_window)
plot(bar_index, "Bar index", display = display.data_window)
plot(na(count) ? na : windowHigh, "Bounded high since event", display = display.data_window)
Compare a live condition with a close-confirmed event
//@version=6
indicator("Bars since: live versus confirmed")
bool liveEvent = close > open
bool confirmedEvent = barstate.isconfirmed and liveEvent
int liveCount = ta.barssince(liveEvent)
int confirmedCount = ta.barssince(confirmedEvent)
plot(liveCount, "Live condition", color = color.orange, style = plot.style_stepline)
plot(confirmedCount, "Close-confirmed condition", color = color.blue, style = plot.style_stepline)

Trading Applications

Measure signal age only after a match exists. A new true condition restarts that age.

Build a cooldown from a discrete event. A continuously true state keeps the count at zero.

Calculate an inclusive high or low after an event with a supported series length and an explicit maximum window.

Frequently Asked Questions

Each true bar resets the counter. If a condition remains true for three bars, all three return zero. Use a discrete event when you need the distance from the start of a state.

The raw result can be na or zero. For an inclusive window, nz(count) + 1 supplies a positive length. Check that the receiving function accepts series int, choose a pre-event policy, and bound the window if event gaps can grow.

No. In the second example it prevents a close-above-open event from being accepted before the chart bar closes. It does not fix future data leakage or unconfirmed data requested from another timeframe.

It counts bars in the context where the expression runs. Market closures and irregular chart bars mean a bar count is not a reliable elapsed-time measurement. A signal condition also need not coincide with an actual trade fill.

Generate ta.barssince() Code with AI

Draft Pine Script using ta.barssince() with Pineify's AI Coding Agent, then review the arguments and test the result on your chart. Usage depends on your plan and available credits.