Pine Script signal timing

Non-Repainting Pine Script with barstate.isconfirmed

Use barstate.isconfirmed to hold a chart-timeframe signal until its bar closes. It is true on every historical bar and on the closing update of a realtime bar. Higher-timeframe data needs a separate fix: request a previous-bar expression such as close[1] with lookahead = barmerge.lookahead_on. Chart-bar confirmation alone cannot confirm a developing higher-timeframe candle, remove future-data leakage, or undo signals drawn into the past.

Review My Pine Script

What barstate.isconfirmed does

Indicators normally recalculate on realtime price or volume updates. A crossover can appear before the close and disappear before confirmation. The flag lets you publish only the closing decision. It does not freeze the underlying moving average while the bar is open.

  • The table describes the ordinary indicator update sequence. Strategies use their own calculation settings.
  • Waiting for confirmation delays an intrabar decision until the close; it does not inherently add a whole bar of delay.
  • Do not put barstate.isconfirmed inside request.security() to confirm the requested timeframe. TradingView documents that this usage does not work.
Indicator executionishistoryisrealtimeisnewisconfirmed
Historical bartruefalsetruetrue
Realtime opening updatefalsetruetruefalse
Realtime intermediate updatefalsetruefalsefalse
Realtime closing updatefalsetruefalsetrue

Example 1: compare an intrabar crossover with a confirmed signal

This complete Pine Script v6 indicator isolates chart-timeframe behavior. The circle can appear during an open bar; the triangle requires its close. Both can be present on a historical crossover bar. Calculate the EMAs and crossover in global scope, then gate the output.

  • History-dependent functions need consistent evaluation across bars. A price-dependent branch that skips entire bars can make their local history differ from the chart history.
  • Skipping intermediate updates solely because a bar is unconfirmed does not, by itself, prove that an EMA buffer is corrupted. Pine normally rolls ordinary series state back between realtime updates and commits the closing result.
  • Global calculations keep this example easy to audit and avoid accidentally skipping bars when you later add conditions.
Chart-bar confirmation only; no higher-timeframe requestspinescript
//@version=6
indicator("Bar-close signal comparison [Pineify]", overlay = true)

fastEma = ta.ema(close, 9)
slowEma = ta.ema(close, 21)
rawCross = ta.crossover(fastEma, slowEma)
confirmedCross = rawCross and barstate.isconfirmed

plot(fastEma, "Fast EMA", color = color.blue)
plot(slowEma, "Slow EMA", color = color.orange)
plotshape(rawCross, title = "Raw crossover", style = shape.circle,
     location = location.abovebar, color = color.orange, size = size.tiny)
plotshape(confirmedCross, title = "Confirmed crossover", style = shape.triangleup,
     location = location.belowbar, color = color.green, size = size.small)

if confirmedCross
    alert("Confirmed crossover at " + str.tostring(close, format.mintick), alert.freq_once_per_bar_close)

Example 2: confirm higher-timeframe data separately

A 5-minute bar can close while its 60-minute candle is still developing. This example compares that developing close with the previous completed 60-minute close. The confirmed request uses [1] inside its expression and lookahead_on together, making the previous value available from the start of each new higher-timeframe period.

  • The orange plot intentionally includes developing data for comparison. The blue plot and triangle use the confirmed reference.
  • The [1] belongs inside request.security(), where it refers to a requested-timeframe bar. Offsetting the returned series outside the call shifts chart bars instead.
  • This pattern trades freshness for confirmation. Do not reuse it as a lower-timeframe recipe; lower-timeframe analysis has different data and intrabar requirements.
HTF request patternConsequence
Current expression + lookahead_offNo historical future leak, but developing realtime HTF values can change after reload.
Current expression + lookahead_onLeaks final HTF values into earlier historical bars.
Previous expression [1] + lookahead_onUses the last completed HTF value with consistent availability timing.
Previous expression [1] + lookahead_offDoes not give the same historical/realtime alignment as the previous-expression + lookahead_on pattern.
Use a standard time-based chart below the selected higher timeframepinescript
//@version=6
indicator("Higher-timeframe confirmation comparison [Pineify]", overlay = true)

higherTimeframe = input.timeframe("60", "Higher timeframe")
if timeframe.in_seconds(higherTimeframe) <= timeframe.in_seconds()
    runtime.error("Choose a timeframe higher than the chart timeframe.")

developingClose = request.security(syminfo.tickerid, higherTimeframe, close,
     gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
confirmedClose = request.security(syminfo.tickerid, higherTimeframe, close[1],
     gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)

plot(developingClose, "Developing HTF close", color = color.orange, linewidth = 1)
plot(confirmedClose, "Previous confirmed HTF close", color = color.blue, linewidth = 2)

rawCross = ta.crossover(close, confirmedClose)
confirmedCross = rawCross and barstate.isconfirmed
plotshape(confirmedCross, title = "Confirmed cross above previous HTF close",
     style = shape.triangleup, location = location.belowbar, color = color.green)

if confirmedCross
    alert("Chart close crossed above the previous HTF close", alert.freq_once_per_bar_close)

Separate alerts from strategy fills

The examples are indicators. Add one to a chart, then create a TradingView alert for its alert() calls. The call must execute on the closing update for alert.freq_once_per_bar_close to trigger; it does not queue a condition that was true earlier but false at the close.

  • After changing the script, its inputs, symbol, or timeframe, recreate the running alert so its saved server copy uses the new context.
  • Strategies calculate at realtime bar close by default. calc_on_every_tick enables intrabar recalculation, which historical OHLC bars cannot fully reproduce.
  • With default settings, a market order created at bar close fills on the next available tick, usually the next bar open. process_orders_on_close can allow a simulated fill on the closing tick. Neither setting guarantees a corresponding broker fill.
  • An alert at chart-bar close still uses developing HTF data if the request is unconfirmed. Alert frequency cannot repair the data request.

A repeatable live-versus-history check

Use these as two separate checks, then test their combination in your own script. This is a validation procedure, not a report of measured live results. Keep the script version, inputs, symbol, session, chart type, and timeframe fixed for the comparison.

  • Use Bar Replay to inspect the order in which bar-based conditions become available. It is not a substitute for recording the original realtime tick sequence.
  • A matching sample supports the tested setup only. Repeat around timeframe boundaries and session changes; keep screenshots or exported observations with the script version.
  • If a closed signal changes, inspect its data dependencies and timing before attributing the difference to the confirmation flag.
CheckRecord liveCompare after reload
Chart-bar confirmationIn Example 1, record raw circles before close and triangles at close, with bar timestamps.Check whether closed-bar triangles remain at the same timestamps. A vanished pre-close circle is expected.
HTF confirmationIn Example 2 on a 5-minute chart with a 60-minute request, record both values across an hourly boundary.Check the blue reference against the preceding completed hourly close and its transition time. The orange history can differ.
Combined signalRecord the triangle at each chart-bar close and any corresponding alert log entry.Compare signal timestamps; historical recalculation does not resend past alerts.
Input guardSelect a requested timeframe equal to or below the chart timeframe.The example should stop with its explicit runtime error.

Repainting risks that remain after bar confirmation

Repainting covers several mechanisms. An indicator that updates during an open candle can be useful when that behavior is disclosed. A historical chart that hides when information became available needs a different review.

  • Pivots and drawings: a pivot requiring right-hand bars is known only after those bars arrive. Plot its decision on the confirmation bar or clearly disclose any backward offset.
  • Intrabar state: varip can preserve live updates that ordinary historical bars do not contain. Bar-close gating does not reconstruct those missing observations.
  • Dataset changes: feed corrections and a different starting history can alter calculations after reload even when signal logic uses confirmed values.
  • Backtest quality: a high win rate alone does not diagnose repainting. Check information availability, fill assumptions, costs, and out-of-sample behavior separately.
Where Pineify fits

Pine Script AI Coding Agent

Bring your source, chart timeframe, requested timeframes, and examples of changed signals. Ask the agent to explain the repainting risk and propose a revision. Review the code and run the live-versus-history checks before using its signals.

Review My Pine Script

Frequently asked questions

Educational programming examples, not investment advice or a profitability claim. Syntax validation does not establish live execution consistency or trading performance.

Sources and verification