The demo chart was immaculate. Every arrow sat on the perfect candle, every historical signal caught the turn.
Live, your entry arrow printed — then moved one bar left overnight. Nothing malfunctioned. You just met repainting, and it's better to meet it in an audit than in a position.
What does repainting actually mean?
An indicator repaints when its history shows something the live chart never showed you. The signal you'd have acted on in real time and the signal the chart displays afterwards are different — the record got quietly rewritten.
The mechanics are mundane. On the developing bar, scripts recalculate on every tick, so a condition can be true at 14:32 and false again by the bar's close. When the chart reloads, history keeps only each bar's final result. Anything the script "said" mid-bar — the arrow you saw, maybe traded — has no place to live, and vanishes or moves. No villainy required; it's the default physics of the engine meeting a script that decided before the bar finished.
The four mechanical causes
Deciding on the unfinished bar. The script acts on the live bar without waiting for confirmation. Live you see signals flicker in and out; history shows only the survivors. This is the most common cause and the easiest to catch.
Higher-timeframe data requested with lookahead. A script can pull, say, the daily close into an intraday chart. Requested carelessly (Pine's lookahead option), historical bars receive the daily close before that daily bar had closed — knowledge no live trader had. Backtests built on it are fiction.
Structures confirmed after the fact. Pivots, zigzags, and "market structure" points only become known several bars after they happen — then get drawn back at the original bar, offset into the past. The drawing is honest geometry; treating it as a signal you could have traded at that bar is the lie.
Alert-versus-chart mismatch. The chart is redrawn continuously; a fired alert is a timestamped fact. A script can show clean history while its live alerts fire on the flickering version — the gap between the two IS the repaint, and you can measure it.
The 20-minute audit (no code required)
Minutes 0–5 — Freeze the evidence. Put the indicator on a fast chart (1–5 minute bars so you get closes quickly). Screenshot the right edge, signals included, timestamp visible.
Minutes 5–10 — The reload test. Let a few bars close, then reload the chart. Compare against your screenshot. Any arrow that moved, vanished, or appeared where none existed live is a repaint, caught in one refresh. This single test exposes the worst class of offenders.
Minutes 10–15 — Replay it. Open Replay in the top toolbar (availability varies by plan and timeframe), start it before a stretch you screenshotted, and step forward bar by bar. Watch when each signal actually appears versus where static history draws it. A signal that shows up three bars late in replay but sits on the pivot bar in history has confessed.
Minutes 15–20 — Set the alert trap. Create an alert on the signal condition with the frequency set to fire once per bar close. Let it run a session. Fired alerts are receipts the chart can't rewrite — line their timestamps up against tomorrow's history. Gaps between what fired and what's drawn are the repaint, quantified.

Three red flags if you can read the source
Open scripts make this faster — grep for:
lookaheadswitched on in any higher-timeframe request. There are legitimate uses; a signal built on it on historical bars is not one.- No close confirmation on live-bar decisions — logic that never checks the bar is confirmed before committing a signal it also plots into history.
- Signals plotted with negative offset — markers drawn N bars into the past, which is how after-the-fact pivots dress up as foresight.
Closed-source tools can't be grepped, which is its own information: you're left with exactly the behavioral audit above, and a vendor you have to take on faith. We've written before about making non-repainting a purchase criterion rather than a hope.
Where we sit
Priced bias, stated plainly: our SMC toolkit is built to survive precisely this audit — zones commit on the closed bar and don't repaint, and the dashboard prints its own Resolved % with the misses left in, recomputed on your chart. Run the reload test on it before you run it on anything else; if a tool we sell ever fails §"reload", that's a bug report we want. And non-repainting is a floor, not a strategy: an honest signal can still be a mediocre one. It just can't lie about what it showed you.
You now have the reload test, the replay check, and the alert trap. Adding the next candidate script takes two minutes; auditing it takes twenty. Spend the twenty.
History you can't replay is marketing. Screenshot it live, reload, and let the chart confess.


