Since Node

The Since node remembers one condition, judged at each bar's close: how many bars ago it last held, whether it has held since a reset, and how often. How it counts, how resets work, and the trap in “first signal of the day”.

NodeBy AlgoLiftUpdated 6 min read
On this page 10How it worksResetsThe horizonBar closes onlyExample: a crossover, but only after oversoldSettingsOutputsUse something else whenWhen it doesn't behaveGoing further

A lot of good rules need a short memory. RSI was oversold at some point in the last five bars. The opening range has already been broken today. Price closed above the 20 EMA on at least 7 of the last 10 bars. The Since node remembers one condition for you, checks it at every bar's close, and tells you when it last held, whether it has held since a reset, and how often.

Takes
A condition, plus an optional reset
Gives
Bars since it last held, whether it has happened, and two counts
Reach for it
A rule depends on what happened over the last few bars

How it works

Wire any true/false value into Condition. When each bar closes, the node asks whether the condition held on that bar and updates four outputs:

  • Bars since is 0 if it held on the last completed bar, then 1, 2, 3 as bars go by without it.
  • Happened turns true the first time it holds after a reset.
  • Count is how many bars it has held on since the reset.
  • Count in last N is how many of the last N completed bars it held on, where N is the Count window.

All four look back no further than the node's memory, the horizon (more below). Before the condition has held, since a reset or within the horizon, Bars since reads never. Treat that word with care. Never is larger than any number, so a Less Than test fails on it and a Greater Than test passes.

Most rules you'd say out loud map onto one output and one Comparison against a Constant:

You meanBuild it as
X in the last N bars, the last completed bar includedBars since Less Than N
B within N bars after ABars since (of A) Less or Equal N, ANDed with B
At least K of the last N barsCount window N, then Count in last Greater or Equal K
X held on every one of the last N barsA Since of NOT X, then Bars since Greater or Equal N

The last row looks backwards until you read it twice: if NOT X hasn't held for N bars, X has held for all of them.

Resets

Reset at wipes the memory at a boundary on the exchange calendar: Never (the default), Session, RTH, Week or Month. Session means the session open, which for ES and NQ is 18:00 the evening before and for a stock is 09:30. RTH means the 09:30 regular-hours open. You can also wire your own condition into the Reset input, and both work together: either one starts a fresh memory.

The bar a reset lands on belongs to the new memory, so a condition that holds on that very bar counts. One output ignores resets on purpose: Count in last N always counts the last N bars, whatever the calendar did.

The horizon

The node remembers the last Horizon completed bars, 500 by default. Within that it's exact; past it, Bars since reads never. The horizon is also why Since stays exact while the engine runs your backtest in monthly pieces: every output depends only on the last horizon bars, and those are loaded before each month starts. Raise it when your idea really spans more than 500 bars, and leave it otherwise.

Bar closes only

Since judges its condition at bar closes, so the condition can only read values that exist at a bar close: comparisons, logic, Tally, math, indicators, modifiers, Price History, price action, a Crossover or Time Window on the Bar close clock, and a price's high, low or open.

The builder refuses, by name: Current Price reading the close of your main series (that's the live price, not a bar's close), trade values and user variables, Time Since, Conditional Value, a State Machine, an intrabar Crossover or Time Window, an external data source, and the five price-action nodes that carry memory across months (Swing Points, Market Structure, Order Block, Fair Value Gap and Multi-Bar Formation). For the close of the last completed bar, use a one-bar Price History.

The outputs have no such limits. A Comparison, a Crossover on either clock, a modifier or a Bracket Order level can all read them.

Example: a crossover, but only after oversold

You trade a 9/21 EMA crossover on NQ 5m and only want the crosses that come out of a real dip: RSI(14) below 30 at some point in the last 5 bars.

Wire RSI(14) and a Constant of 30 into a Comparison set to Less Than, and that Comparison into the Since's Condition. Leave Reset at on Never. Then compare Bars since Less Than a Constant of 5, and AND that with the Crossover's Crossed through a Logic node into a long Entry.

A cross now trades only if RSI was under 30 on one of the five bars up to and including the last completed one. Until RSI has been oversold at least once, Bars since reads never, the Less Than is false, and nothing fires.

Settings

Reset at
Default Never
Never, Session, RTH, Week or Month, on the exchange calendar. A condition wired into Reset works alongside it.
Count window
Default 20
The N in Count in last N, from 1 to 500 completed bars. It can't be longer than the horizon.
Horizon
Default 500
How many completed bars it remembers, from 50 to 5,000. Exact within it; beyond it, Bars since reads never.
Counted series
Default Follow the condition
Whose bar closes it counts. It follows what the condition reads unless you pick a series, and only shows when the strategy has more than one.

Outputs

Bars since
Number
Bars since the condition last held: 0 if it held on the last completed bar, never if it hasn't held since the reset.
Happened
True or false
True once the condition has held since the last reset.
Count
Number
How many bars it held on since the reset.
Count in last N
Number
How many of the last N completed bars it held on. Resets don't clear it.

Use something else when

You need the value at that bar, not when it happened
"The high of the bar where it crossed" is a number to keep. Capture keeps it.
The pattern has steps, or a count that resets on its own rules
"The second push after a pullback" arms, counts and starts over. That's a machine, not one remembered fact.
It's about a crossover
"Crossed within 5 bars" needs no Since. The Crossover counts its own bars since.
You mean minutes since an entry or exit
Since counts market conditions on bar closes. Time Since counts from trade events.

When it doesn't behave

My “first signal of the session” never fires

It's tempting to AND a signal with NOT Happened of a Since watching that same signal. It can never fire: by the time the signal is visible, the bar it fired on is already part of the memory, so Happened is true. Count the signal instead. Set Reset at to Session and AND the signal with Count Equal 1, which is true for the first one of the session only.

“More than 10 bars since” is true from the start

Bars since reads never until the condition first holds, and never passes every Greater Than. If you mean "it happened, but a while ago", AND in Happened as well.

The builder won't take Current Price in my condition

Current Price reading the close of your main series is the live price, which moves on every trade, and Since judges bar closes. For the last completed bar's close, use a Price History of one bar with the field set to close. If you want the moment price does something, that's a Crossover on the Intrabar clock, not a memory.

Count in last N doesn't drop to zero at the session open

That's by design: it always covers the last N completed bars, reset or not. If you want a count that starts over each session, read Count with Reset at set to Session.

Going further

For an intrabar break, "only the first one today" takes a different shape, because the break happens inside a bar the memory hasn't judged yet. Remember the completed bars that already traded through the level instead: a Since, reset each session, of a one-bar Price History's high Greater Than the level, and AND NOT Happened with the intrabar Crossover.

On the node itself only the Count window can be swept; the reset and the horizon change what the rule means, so they stay fixed. The N you compare Bars since with is a Constant, which sweeps like any other. Either way, trying "the last 3, 4, 5, 6 bars" is a search, and it counts like one. Pick N from the idea, not from the results.

Or ask the copilot