Pulling a higher timeframe into a lower-timeframe chart, showing the daily trend on a 5-minute chart, say, is one of the most useful things you can do in Pine Script. It is also where more indicators secretly cheat than almost anywhere else, because the naive way to do it leaks information from the future and makes backtests look far better than live results.
This guide is about doing it correctly. It builds on the execution model, especially the difference between historical and realtime bars, so if that is fuzzy, read it first. Here we focus on request.security, the lookahead parameter, and the confirmed-bar pattern that makes multi-timeframe code trustworthy.
How request.security sees higher-timeframe data
When you request a higher timeframe, the higher-timeframe bar is still forming while many lower-timeframe bars tick by underneath it. The question that determines everything is: at a given lower-timeframe bar, what value of the higher-timeframe bar do you get? The answer depends on the lookahead parameter, and getting it wrong is the single most common cause of multi-timeframe repainting.
| Setting | Behavior | Safe for signals? |
|---|---|---|
| lookahead_off (default) | Returns data known at the current bar | Yes |
| lookahead_on | Can pull the higher-timeframe close before it exists | No, leaks the future |
| lookahead_on + confirmed history | Advanced, used carefully for non-repaint display | Only with care |
The trap: lookahead_on with a live value
With barmerge.lookahead_on, the request can return the higher-timeframe bar's final value before that bar has actually closed. On historical bars this looks magical, your signal fires exactly at the perfect moment, because the script is quietly reading the future. Live, that future does not exist yet, so the signal appears late or differently, and your backtest was a fantasy. This is future-leak repainting, and it is covered among the other kinds in repainting explained.
//@version=6
indicator("The lookahead trap", overlay = true)
// DANGEROUS: lookahead_on with the current bar leaks the future
htfClose_bad = request.security(syminfo.tickerid, "D", close,
lookahead = barmerge.lookahead_on)
// SAFE: default lookahead_off returns only what is known now
htfClose_ok = request.security(syminfo.tickerid, "D", close,
lookahead = barmerge.lookahead_off)
plot(htfClose_ok, "safe daily close")The confirmed-bar pattern
The reliable way to use higher-timeframe data for signals is to request a value that is already confirmed, meaning it comes from a higher-timeframe bar that has fully closed. The common idiom is to request the previous higher-timeframe value, or to combine default lookahead with referencing the prior bar, so you are never acting on a higher-timeframe bar that is still forming.
//@version=6
indicator("Confirmed higher-timeframe trend", overlay = true)
// Request the higher-timeframe SMA with safe defaults, then use the
// value from the last CLOSED higher-timeframe bar via history reference.
htfSma = request.security(syminfo.tickerid, "D", ta.sma(close, 50))
// Using htfSma[1] guarantees the daily bar has closed
trendUp = close > htfSma[1]
bgcolor(trendUp ? color.new(color.green, 90) : color.new(color.red, 90))
plot(htfSma, "daily 50 SMA")The [1] is doing real work here: it steps back to the last fully closed higher-timeframe bar, so the trend you act on is one that genuinely existed at decision time. This costs you a small amount of lag, and that lag is the honest price of a non-repainting signal. Anyone promising higher-timeframe signals with zero lag and no repainting is describing the lookahead trap.
Realtime behavior and barstate
Even with safe requests, the current forming bar behaves differently from history. During a live higher-timeframe bar, values you display can update until that bar closes. If you are firing alerts or driving automation, gate them on barstate.isconfirmed so you only act on closed bars. That single guard is what turns a visually correct indicator into one that is safe to trade or automate, which is why it recurs in the alerts guide and the webhook guide.
A checklist for multi-timeframe code
Before you trust a multi-timeframe script, verify four things. You are using default lookahead unless you deeply understand the alternative. You reference a confirmed higher-timeframe value, typically via a history offset, for anything you act on. You gate alerts and entries on confirmed bars. And you have compared how the indicator looks live versus after a reload; if it changes its past, it repaints. If all four hold, your higher-timeframe logic is sound.
These are subtle rules, and they are exactly the kind of thing generic AI gets wrong, often defaulting to lookahead_on because it makes historical charts look impressive. PineScripter generates non-repainting multi-timeframe patterns by default, using confirmed values and safe lookahead, so the backtest you see is the behavior you get live. If your higher-timeframe indicator looks too good to be true on history, that is worth checking; you can rebuild it correctly at PineScripter.
Disclaimer: PineScripter is a coding tool for Pine Script development. It does not provide financial advice and does not guarantee trading profits. Always backtest strategies thoroughly and understand the risks before live trading.