Why Most "No-Repaint" BOS/CHoCH Indicators Still Repaint (And How to Actually Fix It)
If you've traded ICT concepts on MT5 for more than a week, you've hit this: an indicator marks a Break of Structure, you take the trade, and ten minutes later the arrow has silently moved to a different candle. The indicator's marketing page said "no repaint." It repainted anyway.
This isn't a rare bug. It's the default outcome of how most people write structure-detection code — and it's fixable with one habit most tutorials skip.
Where the repaint actually comes from
Almost every BOS/CHoCH indicator works by tracking swing highs/lows and checking when price breaks them. The repaint bug hides in exactly one place: how the swing point itself gets confirmed.
A naive swing detector looks at bar i and asks "is this higher than the N bars on each side?" The problem: on the currently forming bar, or on a bar that was very recently the highest point, that answer can flip. Today's swing high might not survive the next candle. If your structure break logic reacts to a swing the moment it looks confirmed — instead of waiting until it's actually confirmed — every break built on it can silently move later.
The fix: confirm on close, not on touch
A swing point is only "real" once enough bars have closed without invalidating it. Here is the difference between the naive check and the confirmed one:
// WRONG: reacts to the extreme the instant it forms if(high[i] > high[i-1] && high[i] > high[i+1]) swingHigh = i; // i+1 hasn't fully closed relative to future bars yet // RIGHT: only accept a swing once N bars have CLOSED past it, and none of them exceeded it bool IsConfirmedSwingHigh(int i, int confirmBars) { for(int k = 1; k <= confirmBars; k++) if(high[i+k] >= high[i]) return false; // still not safe return (i + confirmBars) <= iBars(_Symbol, _Period) - 1; // enough closed bars exist }
The difference is small in code and enormous in behavior: a swing point is only drawn once it has survived enough closed bars. Indicators that repaint almost always skip this wait because it makes the chart feel less "live." Indicators that don't repaint pay for that honesty with a small lag, and that lag is the price of the signal actually meaning something.
The second trap: multi-timeframe structure
If your BOS logic pulls a higher-timeframe bias (H1 direction feeding an M15 entry, for example), the same rule applies one level up: don't read the higher timeframe's current forming bar — only its last closed bar. Reading the forming H1 candle for bias is the most common reason an M15 signal that looked valid at 14:03 is gone by 14:04.
Why this matters more than people think
A structure-break signal that moves after the fact isn't just annoying — it silently inflates backtest results (the indicator "knew" things at bar-close time it couldn't have known live) and erodes trust the first time a trader watches it happen live. If you're building or buying a BOS/CHoCH tool, the single most useful question to ask isn't "does it repaint" — sellers will say no either way — it's "show me the confirmation-bar count," because a tool with zero lag on structure confirmation is mathematically not possible without looking into the future.
I applied this exact confirmed-swing logic building ATS Dominance Shift (CHoCH + order block detection) for MT5 — happy to go deeper on the multi-timeframe case in the comments.


