Pine Script Historical Lookback

Pine Script Event History: Tracking Signals with barssince and valuewhen

In Pine Script, event history is tracked primarily through ta.barssince() and ta.valuewhen(). ta.barssince(condition) counts the number of bars elapsed since a specific boolean condition was true, returning na if the event has never occurred. ta.valuewhen(condition, source, occurrence) retrieves the historical value of a source expression at the moment the condition was met, allowing traders to reference past signal prices and pivot levels.

Build Event Logic with AI

Comparing ta.barssince and ta.valuewhen in Pine Script v6

Tracking past market conditions without manual loop indexing is vital for time-based exits, pullback validation, and multi-stage trade confirmation.

FunctionArgumentsReturned valueTypical trading use case
ta.barssince(condition)condition (series bool)Integer bar count or naEnforcing a 5-bar cooldown between consecutive trade signals
ta.valuewhen(condition, source, 0)condition, source, occurrenceSource value at most recent eventAnchoring stop loss to the breakout candle low
ta.valuewhen(condition, source, 1)condition, source, occurrenceSource value at 2nd most recent eventComparing current swing high against the previous swing high
ta.highestbars(source, length)source, lengthZero or negative offset to highest barLocating exact candlestick of highest peak within 20 bars

Complete Pine Script v6 script: Signal tracking and price anchoring

This indicator measures confirmed RSI crossings and plots the close of the latest accepted event as a reference price, not proven support. The cooldown measures distance from the previous raw confirmed crossing, including a crossing rejected by the cooldown. With a minimum of five bars, raw events at bars 10 and 15 can both pass; an intervening event at bar 13 resets the distance and prevents bar 15 from passing. The first event is allowed.

Pine Script v6: Event lookback with barssince and valuewhenpinescript
//@version=6
indicator("Event Lookback & Anchor Tracker [v6]", overlay = true)

// Input settings
int rsiLength = input.int(14, "RSI Length", minval = 1)
float rsiOversold = input.float(30.0, "Oversold Level", minval = 0, maxval = 100)
int minCooldownBars = input.int(5, "Minimum Cooldown Bars", minval = 1)

// Calculations
float rsiVal = ta.rsi(close, rsiLength)
bool crossed = ta.crossover(rsiVal, rsiOversold)
bool rawSignal = crossed and barstate.isconfirmed

// Bars since previous signal
int barsSincePrior = ta.barssince(rawSignal[1]) + 1
bool isReady = na(barsSincePrior) or (barsSincePrior >= minCooldownBars)
bool confirmedSignal = rawSignal and isReady

// Store price of the latest confirmed signal
float anchorPrice = ta.valuewhen(confirmedSignal, close, 0)
int barsSinceSignal = ta.barssince(confirmedSignal)

// Plotting
plot(anchorPrice, "Accepted event close", color = color.blue, linewidth = 2, style = plot.style_linebr)
plotshape(confirmedSignal, "Accepted event", shape.triangleup, location.belowbar, color.green, size = size.small)

// Reuse one label rather than creating one on every elapsed realtime bar.
var label statusLabel = label.new(na, na, "", color = color.purple, textcolor = color.white, style = label.style_label_down)
if barstate.islast and not na(barsSinceSignal)
    label.set_xy(statusLabel, bar_index, high)
    label.set_text(statusLabel, "Bars since accepted event: " + str.tostring(barsSinceSignal))

Common pitfalls when working with barssince and valuewhen

Understanding how historical series buffers behave prevents confusing calculation errors:

  • Evaluating current bar triggers: Writing ta.barssince(myCond) on a bar where myCond is true returns 0. To check bars since the previous occurrence, evaluate ta.barssince(myCond[1]) + 1.
  • Initial state: barssince and numeric valuewhen lookups are na until the required event exists. A second occurrence lookup stays unavailable after only one event. Keep that state explicit.
  • Occurrence index ordering: In ta.valuewhen(), occurrence 0 is the latest event, occurrence 1 is the one before it, and so forth. Occurrence indexes must be non-negative; a requested occurrence may not yet exist.
  • Repainting risk with intrabar conditions: Ensure the condition passed to valuewhen is based on confirmed bars to prevent the recorded historical value from shifting during live candle ticks.

When to choose var variables over valuewhen

While ta.valuewhen() is concise for one-off lookbacks, declaring a var variable is often preferred when building complex state machines:

  • Choose explicit state when reset and update rules are easier to audit. Measure any performance difference with the Profiler instead of assuming a fixed speed advantage.
  • Multi-stage resets: A var variable can be reset to na when a trade completes, preventing accidental lookbacks to events from weeks earlier.
  • State persistence: A var variable can be updated across multiple conditions without duplicating nested valuewhen calls.
Where Pineify fits

Pine Script AI Coding Agent

Generate event-tracking indicators, barssince cooldown rules, and anchored multi-condition strategies in Pine Script v6 using Pineify AI.

Also useful: Visual Pine Editor. Build signal conditions, price alerts, and indicator workflows visually without coding.

Build Event Logic with AI

Frequently asked questions

Historical event tracking and price lookups reflect mathematical bar sequences on chart data. Verify execution behavior and slippage allowances when trading live markets.

Sources and verification