TradokiTradoki/blog
Subscribe
← back to indexblog / backtesting / tradingview-strategy-tester-unrealistic-results
Backtesting

Why your TradingView strategy tester lies to you

Your equity curve looks perfect because a broker emulator guessed the inside of every candle. The documented assumptions that inflate a backtest.

A
ArthurFounder, Tradoki
publishedAug 12, 2026
read9 min
Why your TradingView strategy tester lies to you

Your strategy tester shows an 87% win rate, an equity curve that only points up, and a drawdown small enough to ignore. Two weeks live, the same rules bleed. The gap is rarely bad luck or a regime change. The TradingView strategy tester is

Your strategy tester shows an 87% win rate, an equity curve that only points up, and a drawdown small enough to ignore.

Two weeks live, the same rules bleed.

The gap is rarely bad luck or a regime change. The TradingView strategy tester is a simulator, and it runs on documented assumptions about what happened inside candles it never saw the inside of. Four of those assumptions quietly work in your favour until real money arrives.

None of this is hidden. TradingView publishes all of it in the Pine Script manual. Almost nobody reads it before sizing up.

A backtest is not a record of what would have happened. It is the output of a broker emulator making specific, published guesses about the inside of every bar.

Repainting is a technical description, not an accusation

The word gets thrown around as an insult, which has made it useless. TradingView's own definition is narrower and more useful: repainting is script behavior causing historical and realtime calculations or plots to behave differently.

That difference exists for a structural reason. On historical bars, only four values survive: open, high, low, close. On a realtime bar, the manual notes that high, low and close are not fixed and can change many times before the bar closes. Only the open stays put.

So a script reading the current close behaves one way in history, where the close is final, and another way live, where the close is whatever price just printed. Same code, two different animals.

The manual sorts this into four buckets, and the distinction is what most traders miss. Some repainting is widespread and often acceptable, such as using higher timeframe data that updates on an unconfirmed bar. Some is potentially misleading, including scripts that relocate past events or run with calc_on_every_tick set to true. Some is flatly unacceptable, and that bucket is where backtests go to become fiction: scripts that leak future information into the past, strategies executing on non-standard charts, and scripts using realtime intrabars to generate alerts or orders.

And some is unavoidable, because data vendors revise feeds and your chart history starts at a different bar tomorrow than it did today.

The emulator fills your orders on a price path it invented

Here is the mechanic that inflates more backtests than anything else, and it has nothing to do with your code.

By default the broker emulator fills orders using only the chart data available to it, which means on historical bars it executes after a bar closes, working from four prices. To decide what happened between them, it assumes a path. If the open sits closer to the high, it assumes the market moved open to high to low to close. If the open sits closer to the low, it assumes open to low to high to close.

Then it makes a second assumption that matters just as much: no gaps exist inside a bar. Any price within the bar's range counts as a valid level for filling a pending order.

Put those together on a daily chart and you have four price points standing in for an entire session, plus a guarantee that every level inside the range was tradeable. If your stop and your target both sat inside one candle, the emulator's invented path decides which one you hit. It is not reading the tape. It is picking an order.

4Price points per historical bar without Bar Magnifier
60 minIntrabar timeframe used for a daily chart with Bar Magnifier
6Chart types where results do not reflect actual market conditions
2M barsDeep Backtesting ceiling

The fix TradingView ships is the Bar Magnifier, enabled with use_bar_magnifier = true or through the strategy settings. It swaps the assumed path for real lower timeframe bars: a daily chart gets filled using 60 minute data, a weekly chart using daily. More ticks, fewer guesses. It is a Premium feature, which is an annoying answer, but knowing the assumption exists is most of the value even if you never enable it.

This is also why a strategy that looks robust in the tester can feel like it is being hunted live. The emulator never sweeps your stop and then reverses inside the same bar unless the bar's range says it must. Real intrabar liquidity runs do exactly that, all day.

Lookahead is the assumption that turns a losing system into a perfect one

The other three problems shave points off your results. This one manufactures them.

When you pull higher timeframe data with request.security(), the manual notes it returns confirmed values on historical bars and unconfirmed values on realtime bars. Configure that request carelessly and your script reads a higher timeframe value on a historical bar before that higher timeframe bar had actually closed. In plain English: on Tuesday's chart it already knows how Friday ended.

That is what produces the entries sitting precisely at swing lows and exits at the exact high. Not a signal. A leak.

The counterintuitive part is the recommended fix. TradingView's manual says to avoid repainting by offsetting the expression by at least one bar with the history-referencing operator and using barmerge.lookahead_on. Lookahead paired with an offset is the safe construction. Lookahead alone is the one that leaks. Traders who learned "lookahead bad, turn it off" have half the rule, and the half they are missing is the half that does the work.

TradingView takes this seriously enough to police it. Using lookahead to produce misleading results is not permitted in published scripts, and the manual states that publications using the technique will be moderated.

An equity curve with no losing streaks is not evidence of a great system. It is evidence that something in the chain already knew the answer.

Internal note on strategy validation, Tradoki desk

If an LLM wrote the higher timeframe request for you, this is the specific line to audit before anything else. Generated Pine Script reproduces the patterns it saw most often, and forum code is full of the leaky version. The same trap swallows multi-timeframe analysis done by hand, where the higher timeframe bias you apply to Tuesday quietly comes from Friday's completed candle.

Heikin Ashi and Renko results are simulations of prices nobody traded

This one is short, absolute, and routinely ignored.

TradingView states that performance results from a strategy applied to non-standard charts do not reflect actual market conditions by default. Six chart types carry the warning: Heikin Ashi, Renko, line break, Kagi, point and figure, and range. Trades get simulated against the chart's synthetic prices, which are not real market prices, and the documentation says the outcome is typically unrealistic.

Think about what a Heikin Ashi close is. It is an average of four values. No order ever filled there, because it is not a price, it is arithmetic. Backtesting against it is like grading a driving test against the average speed of the trip.

Costless backtests are a setting you forgot to change

Commission and slippage are fields in the strategy properties, and a field nobody filled in is a market with no friction in it.

Run a scalping system that averages a fraction of a point per trade through a costless simulation and it will look like an annuity. Add a realistic spread and commission and the same trade list can invert. The strategies most sensitive to this are exactly the high frequency, small edge ones that produce the most flattering win rates, which is a pattern worth internalising: the smoother the equity curve, the more likely costs are doing the heavy lifting against you.

Sample size compounds the problem, because a standard backtest only uses the data loaded on your chart. Deep Backtesting runs against all available history for the symbol, up to two million bars and one million trades, and it requires a Premium plan or higher. Without it, a "long backtest" can quietly be a few hundred bars, and a few hundred bars is not a sample.

Four checks that separate a measurement from a screenshot

None of this makes the strategy tester useless. It makes an unaudited tester result useless, which is a different claim.

Move it to a candle chart. If the results only exist on Heikin Ashi or Renko, they only exist in the smoothing. This costs one click and kills more bad strategies than any other single check.

Read every higher timeframe request out loud. Every request.security() call, checked for the offset. If the script reads a higher timeframe value that had not closed yet at that point in history, nothing downstream of it is evidence.

Turn on the Bar Magnifier, or assume your fills are optimistic. If enabling it materially changes the results, the original numbers were a product of the assumed price path rather than the strategy.

Put costs in before you get attached. Set commission and slippage to something defensible for your broker and instrument before you look at the equity curve, not after. Numbers you see first are the ones you argue for later.

Then forward test anyway. As a rule of thumb from what we see in cohorts rather than a measured statistic, the strategies that survive a clean backtest and then 30 days of forward testing on a demo account are the ones where the tester was measuring the rules rather than the simulator's generosity.

A backtest is a hypothesis with a spreadsheet attached. Treat the machine producing it as an interested party.

● FAQ

Why does my TradingView backtest look perfect but fail live?
Usually because the broker emulator filled your orders on an assumed price path rather than a real one. On historical bars it works from four prices per bar and treats every level inside the bar's range as fillable, with no gaps. That is generous to any strategy whose stop and target both sit inside the same candle.
What does repainting actually mean in Pine Script?
TradingView defines it as script behavior causing historical and realtime calculations or plots to behave differently. Not all of it is dishonest. The manual separates behavior that is widespread and often acceptable from behavior it calls unacceptable, such as leaking future information into the past.
Does barmerge.lookahead_on cause lookahead bias?
On its own it can. The Pine Script manual's recommended way to avoid repainting in higher timeframe requests is to combine barmerge.lookahead_on with an expression offset by at least one bar using the history-referencing operator. The offset is what makes it safe. Lookahead without that offset is the version that leaks future data.
Are Heikin Ashi and Renko backtests reliable?
Not by default. TradingView states plainly that performance results from a strategy applied to non-standard charts do not reflect actual market conditions, because trades are simulated against synthetic prices rather than traded ones. A Heikin Ashi close is an averaged value, not a price anyone transacted at.
What is the Bar Magnifier and do I need it?
It replaces the emulator's guess about intrabar movement with real lower timeframe data, so a daily chart is filled using 60 minute bars instead of four daily prices. It is a Premium feature. It does not make a weak strategy work, but it removes one large source of fill optimism from the result.
— share
— keep reading

Three more from the log.

Why 'Once Per Bar Close' Alerts Still Fire Late
003 · Pine Script

Why 'Once Per Bar Close' Alerts Still Fire Late

TradingView's own support docs explain the confirmation logic behind alert delay, and why the webhook relay is rarely where the real bottleneck hides.

Sep 05, 2026 · 7 min