Guide

Repainting Explained: The Five Kinds and How to Prevent Each

Repainting is not one bug. It is five distinct problems that get lumped under one scary word. Tell them apart and each one has a clear, specific fix.

13 min read

Repainting is the most feared word in Pine Script, and also the most misunderstood. People use it to mean "my indicator lied to me," but that covers at least five different mechanisms with different causes and different fixes. Lumping them together is why so much online advice is vague and contradictory. This guide separates them.

At its core, repainting means the script shows one thing in the moment and a different thing after the fact, so what you backtested is not what you could have traded. Every kind traces back to the gap between the forming bar and confirmed history, which is the heart of the execution model. Here are the five kinds.

KindCausePrevention
Higher-timeframe leakHTF bar not yet closedUse confirmed HTF values
Realtime fluctuationValue changes as bar formsGate on barstate.isconfirmed
Future leaklookahead_on reads aheadUse default lookahead_off
Security misuseWrong request patternRequest once, reference closed bars
Drawing repaintObjects redrawn on the last barDraw on confirmed bars only

Kind one: higher-timeframe leak

This is the most common. You request a higher timeframe and use its value while the higher-timeframe bar is still forming. On history the bar is already closed, so the value looks stable and perfect. Live, it keeps changing until the higher bar closes, so your signal shifts. The fix is to use a confirmed higher-timeframe value, typically by referencing the last closed bar, exactly as laid out in multi-timeframe analysis without repainting.

Kind two: realtime fluctuation

Any value computed on the current forming bar can change with every tick, because the bar's high, low, and close are not final. An indicator that draws a signal mid-bar may un-draw it when price moves. On historical bars this never happens, since those bars are frozen, so the indicator looks perfectly reliable in backtest and flickers live.

pine
//@version=6
indicator("Confirmed-bar signal", overlay = true)

rawSignal = ta.crossover(close, ta.sma(close, 20))

// Repaints: fires mid-bar and can vanish
// plotshape(rawSignal, ...)

// Stable: only commit on a closed bar
confirmed = rawSignal and barstate.isconfirmed
plotshape(confirmed, style = shape.triangleup, location = location.belowbar)

The fix is barstate.isconfirmed. Only treat a signal as real once the bar closes. You trade a little immediacy for a signal that does not lie, which is the right trade for anything you act on.

Kind three: future leak via lookahead

Using barmerge.lookahead_on carelessly lets a request return data before it would have been known, effectively reading the future on historical bars. This produces gorgeous backtests and impossible live results. The fix is simple: use the default lookahead_off unless you fully understand the narrow, advanced cases where lookahead is combined with confirmed history. We show the trap and the safe pattern in the multi-timeframe guide.

PineScripter defaults to confirmed-bar, non-repainting patterns

Kind four: security misuse

Beyond lookahead, there are subtler ways to misuse request.security: requesting a series that itself depends on the forming bar, mixing timeframes inconsistently, or acting on a requested value without accounting for when it becomes known. The prevention is discipline: request once, be explicit about which bar's value you are using, and reference closed bars for anything you act on. This overlaps with the performance advice in why your Pine Script is slow, because clean requests are both faster and safer.

Kind five: drawing repaint

The last kind is visual. If your script draws lines, labels, or zones based on the current bar and redraws them as new bars arrive, the historical picture changes every time the chart reloads. A support zone that "was always there" was actually redrawn after the fact. This is not a data leak, but it is still misleading. Draw on confirmed bars, and be honest about which drawings are provisional. The drawing-object mechanics, including the caps, are in arrays, matrices, and maps.

How to test whether your script repaints

There is a simple test. Note where a signal appears live, then reload the chart and see whether it is still in the same place. If the past changed, you have repainting. Another approach is to run the script on the bar-replay feature and watch whether signals stay put as bars form. For strategies specifically, compare the Strategy Tester results against forward performance; a large gap often means a repainting signal, which ties into how the tester can mislead, covered in how TradingView backtesting actually works.

Repainting is not always bad

One honest nuance: some repainting is acceptable and even desirable. A live indicator that updates the current forming bar is doing its job; you just must not treat the forming value as final. The problem is only when you backtest or trade on values that were never actually available in real time. Knowing the difference is what separates a trader who understands their tools from one who gets blindsided.

Because there are five distinct kinds, avoiding repainting by hand means keeping five separate things straight, and generic AI routinely gets several of them wrong, often defaulting to lookahead patterns that flatter the backtest. PineScripter generates confirmed-bar, non-repainting code by default across all five categories, so the behavior you see on history is the behavior you get live. If you suspect an indicator is repainting, you can rebuild it cleanly 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.