BarsSince
BarsSince counts the number of bars elapsed since a condition was last true in ProBuilder. Track how long ago a crossover or signal occurred on the chart.
Syntax
BarsSince(Condition)
BarsSince(Condition, Occurrence)Parameters
| Name | Type | Default | Description |
|---|---|---|---|
Condition | boolean | required | The expression whose most recent true evaluation is measured. |
Occurrence | integer | 0 | Which occurrence to measure. 0 targets the most recent, 1 the one before it, and so on. |
How it works
BarsSince walks backwards from the current bar and counts how many bars separate it from the bar on which the condition last evaluated to true. A result of 0 means the condition is true on the current bar, 1 means it was true on the previous bar, and larger values indicate older events.
The optional second argument selects earlier occurrences. BarsSince(cond) and BarsSince(cond, 0) are equivalent and target the latest occurrence; BarsSince(cond, 1) measures the distance to the occurrence before that. Comparing the two reveals the spacing between consecutive events, for example the number of bars between the last two oscillator crossings.
When the condition has never been true anywhere in the evaluated history, the function returns -1. This sentinel must be handled explicitly, because -1 passes numeric comparisons such as < 10 and can quietly satisfy freshness filters that were meant to require a real event.
Typical applications include freshness filters (only act when a signal fired within the last n bars), cooldown timers (block re-entry until enough bars have passed), and duration measurements between chart events.
Examples
Example 1, Distance to the last two RSI crossings (Indicator)
// Condition: 14-period RSI crosses above 50
a = RSI[14] CROSSES OVER 50
// Bars since the previous occurrence and the most recent one
testA = BarsSince(a, 1)
testB = BarsSince(a)
RETURN testA AS "previous occurrence", testB AS "last occurrence"The indicator plots the age in bars of the latest RSI cross above 50 and of the one before it. The gap between the two lines is the spacing between consecutive crossings.
Example 2, Entry cooldown (ProOrder)
DEFPARAM CumulateOrders = false
signal = Average[10](close) CROSSES OVER Average[40](close)
sinceSignal = BarsSince(signal)
// Trade the crossover, but not if another one fired within the last 10 bars
IF signal AND (BarsSince(signal, 1) > 10 OR BarsSince(signal, 1) = -1) THEN
BUY 1 CONTRACT AT MARKET
ENDIF
// Time-based exit once the signal is 20 bars old
IF LONGONMARKET AND sinceSignal >= 20 THEN
SELL AT MARKET
ENDIFBarsSince serves two roles here: occurrence 1 enforces a cooldown between entries, and occurrence 0 drives a time-based exit.
Example 3, Fresh breakout scan (ProScreener)
// Condition: close breaks above the highest close of the prior 50 bars
breakout = close CROSSES OVER Highest[50](close[1])
age = BarsSince(breakout)
// Keep instruments where the breakout happened within the last 3 bars
SCREENER[age >= 0 AND age <= 3] (age AS "Bars since breakout")The screener returns instruments with a recent 50-bar breakout. The age >= 0 clause excludes the -1 sentinel for instruments that never triggered.
Common errors and gotchas
- -1 means never. A condition that has never been true returns -1, which slips through filters like
BarsSince(cond) < 5. Always exclude the sentinel explicitly, for example withage >= 0. - Occurrence numbering starts at 0. The most recent occurrence is 0, not 1. Passing 1 measures the second most recent event, a frequent off-by-one source.
- The condition must be boolean. Feeding a numeric expression is invalid. Comparisons and crossover expressions qualify; raw prices do not.
- History limits the answer. Only loaded bars are examined. An event older than the loaded history is reported as never having happened, so results can change when more data is loaded.
Related instructions
BarIndex, zero-based position of the current bar in the loaded data.IntradayBarIndex, bar counter that resets each trading day.HighestBars, offset in bars of the highest value over a period.LowestBars, offset in bars of the lowest value over a period.CROSSES OVER, true on the bar where one series moves above another.CROSSES UNDER, true on the bar where one series moves below another.RSI, momentum oscillator commonly paired with BarsSince conditions.Average, moving average used in crossover conditions.
