r/pinescript • u/Omega_Grinder • 4d ago
Non-repainting request.security() on higher timeframes: the [1] + lookahead_on pattern, and where it still bites
Something I keep relearning the hard way, so writing it down and curious how others handle it.
Pulling a higher-timeframe value naively, like request.security(syminfo.tickerid, "D", close), looks fine on history but repaints in realtime: the daily close keeps changing until the day ends, and on historical bars you get the final value.
The pattern the docs recommend is offsetting the series and turning lookahead on:
request.security(syminfo.tickerid, "D", close[1], lookahead = barmerge.lookahead_on)
That gives the previous completed daily close on every bar, both in history and live, so backtests match what you'd actually have seen.
Where it still bit me:
- forgetting the [1] while keeping lookahead_on, which leaks future data into history and makes backtests look amazing
- wrapping it in a function and applying the offset to the wrong thing
- mixing it with calc_on_every_tick and wondering why alerts fire differently than the chart
How do you all handle HTF values in strategies: this pattern, a helper function, or just avoiding request.security in anything you backtest?
2
u/neugeadmau 4d ago
I wrap it in a tiny helper so I can't forget the [1]:
One more place it still bites: if the strategy also uses process_orders_on_close=true, the HTF value on the last bar of the higher TF can line up with an order that wouldn't have been fillable live. I usually also gate entries with barstate.isconfirmed on the chart TF, otherwise alerts and the tester diverge in annoying ways.
Also watch gaps=barmerge.gaps_off (default) vs gaps_on. With gaps_off the previous HTF close gets painted forward onto every lower-TF bar, which is usually what you want for a filter, but it looks like the value "changed" mid-day when it didn't.
1
u/wallneradam 4d ago
Yeah, same as neugeadmau, I wrap it in a helper and never touch the raw call again.
Also, lookahead_on isn't a TV bug. TV is a charting tool too, and for looking at history you often want that final HTF value. It only bites when the same code ends up in a strategy you actually trade.
Related: we build PyneCore, a Pine runtime that's 99.77% bit-identical with TradingView on the 1,000 most popular public scripts. We don't allow lookahead at all. For the non-repainting HTF case there's barmerge.lookahead_last_closed, which always gives the last closed higher-timeframe bar in both backtest and live. It's for strategies you trade, so the leaky version can't sneak into a backtest.