In 2024 I backtested a mean-reversion EA on ten years of EURUSD data. The results were gorgeous: 68% win rate, 2.4 profit factor, max drawdown 8%. I put $15,000 behind it. Within four months the live account was down -$4,200 and the EA had taken trades the backtest never showed. The post-mortem took a weekend and made me sick: my "ten years of data" had a six-week gap in 2019 where the broker's feed dropped ticks, three separate price spikes of 200+ pips that never happened in reality, and weekend bars stitched together wrong. The backtest was a fantasy novel. This is the guide to historical data quality for backtesting that I needed before I trusted a single number.
Every backtest is only as honest as its data. Bad data does not just add noise — it systematically lies in the strategy's favor, because gaps, spikes, and stale quotes create phantom fills that flatter every EA ever built. Below: what bad data looks like before it ruins you, the gaps and spikes that poisoned my backtest, how to clean tick data properly, a $100k EA evaluated on clean versus dirty data, the same EA run on three different feeds, the math of modeling quality and slippage, and how to backtest like your capital depends on it — because it does. I verify my risk numbers with the DarkWolf MT5 Signal Calculator before any backtest-informed sizing goes live.
What bad data looks like before it ruins you
Bad tick data has a recognizable fingerprint. Once you know the signs, you can spot a poisoned dataset in ten minutes — before it costs you money. Here is my pre-backtest inspection checklist, the exact one I run on every new dataset:
| Defect | What you see | Why it flatters the backtest |
|---|---|---|
| Time gaps | Hours or days with zero ticks during market hours | The EA "holds through" volatility that would have stopped it out |
| Phantom spikes | Single ticks 100+ pips from surrounding prices | Fake wicks trigger entries/exits at prices that never existed |
| Flatlined quotes | Identical bid/ask repeated for minutes in active sessions | Frozen prices let scalpers "trade" with zero spread cost |
| Weekend stitching | Friday close connected directly to Sunday open, no gap | Hides gap risk — weekend gaps are where stops die |
| Wrong timezone | Session times shifted; "London open" signals fire at wrong hours | Session-based EAs test the wrong market behavior entirely |
The inspection itself is simple: load the data in MT5's strategy tester in visual mode and watch the first month at high speed. Gaps show as price teleporting. Spikes show as vertical lines to nowhere. Flatlines show as a dead chart during what should be London. Ten minutes of watching saves ten months of false confidence. The backtesting best-practices guide covers the tester settings; this article covers whether the data deserves the tester at all.
The gaps and spikes that poisoned my 10-year backtest
Let me show you exactly what was wrong with my dataset, because the specifics are instructive. The data came from my broker's history center — the default source most MT5 traders use without question.
Defect one: a six-week gap in March–April 2019. The broker had migrated feed providers and simply never backfilled. Six weeks of 2019 — including a volatile Brexit headlines period — were missing. My mean-reversion EA's best quarter in the entire backtest was Q2 2019, a quarter in which it traded nothing real. The "68% win rate" was computed over a dataset with a hole punched through one of the choppiest periods in the sample. Removing the gap period alone dropped the win rate to 61%.
Defect two: three phantom spikes — single ticks printing 200–300 pips away from market, one in 2017, two in 2021. Each spike wicked through my EA's take-profit on open positions, banking phantom wins of $400–$700 that never happened. Worse, one spike wicked through a stop-loss the other way, but the tester filled the stop at the spike price instead of the real price — a phantom loss that at least erred honestly. Net effect of the spikes: +$1,900 of imaginary profit baked into the results.
Defect three, the subtle one: spread data. The history center stored only bid prices, so the tester reconstructed asks using a fixed 2-pip spread assumption. My EA traded the Asian session, where real spreads run 3–6 pips. Every Asian trade in the backtest was priced with fantasy costs — roughly $0.80 per trade too cheap across 4,000 trades, or $3,200 of hidden subsidy. This was the biggest lie in the dataset, and it was invisible unless you knew to look for the spread column.
The quirk that still bothers me: the broker's data was not malicious. It was just neglected — a feed migration here, a missing backfill there, nobody's job to check. Default broker data is guilty until proven innocent. I now treat every new dataset as guilty until proven innocent, and the inspection checklist above is the trial.
Cleaning your tick data the right way
Here is my actual data pipeline, refined over two years. It takes about an hour per instrument for a ten-year history, and it is the highest-ROI hour in my trading workflow:
| Input Field | What it means | Sample value |
|---|---|---|
| Data source | Where the ticks come from — quality varies enormously | Dukascopy free tick data (bid+ask) |
| Date range | Must include at least one crisis, one trend year, one chop year | 2015–2025 (11 years) |
| Spike filter | Remove ticks beyond N× ATR from neighbors | 5× M1 ATR, both directions |
| Spread handling | Use real ask/bid; never a fixed-spread assumption | Variable, from tick data |
| Timezone | Align to your broker's server time before testing | GMT+2/+3 (broker server) |
Yes — I am using the manual-table format for a data pipeline, because each row is genuinely an input you configure. The source matters most: Dukascopy's free historical data includes real bid and ask ticks going back decades, which solves the spread problem that poisoned my backtest. It is not perfect — no free data is — but bid+ask ticks from a real feed beat bid-only broker data every time.
The spike filter deserves emphasis: removing ticks beyond 5× ATR sounds aggressive, but real market moves print many ticks in sequence — a genuine spike leaves a trail. Phantom spikes are solitary: one impossible tick surrounded by normal ones. The filter removes the solitary freaks and keeps the real violence. After filtering, I re-run the visual inspection. If the chart still teleports anywhere, the dataset goes in the bin. MetaQuotes' own documentation explains how MT5's tester consumes tick data — worth reading once so you understand what "every tick based on real ticks" actually promises.
A $100k EA evaluated on clean vs dirty data
The definitive experiment. I took the same mean-reversion EA, the same settings, the same 2015–2025 period — and ran it on two datasets: my broker's default history (dirty) and the cleaned Dukascopy tick data (clean). $100,000 simulated account, 1% risk per trade, real variable spreads on the clean run:
| Metric | Dirty data (broker default) | Clean data (filtered ticks) |
|---|---|---|
| Total net profit | +$86,400 | +$21,700 |
| Profit factor | 2.4 | 1.35 |
| Win rate | 68% | 54% |
| Max drawdown | 8% | 23% |
| Trades | 4,120 | 4,388 (gap periods now have real trades) |
Read that table slowly. The dirty data said: deposit $100k, make $86k, risk 8%. The clean data said: make $21k, risk 23% drawdown. Same EA. The $64,700 difference was entirely phantom — gap-skipped volatility, spike-triggered fantasy fills, and subsidized spreads. The clean result (1.35 profit factor, 23% drawdown) is a tradeable but unexciting EA; the dirty result was a wealth fantasy. I lost $4,200 live learning which one was real. Monte Carlo simulation on the clean results widened the drawdown estimate further to 28% — which is the number I actually size against now.
I ran the same EA on three data feeds
One more experiment, because a single clean dataset can still have its own biases. I ran the identical EA on three independent tick sources for 2020–2025, all spike-filtered, all with real spreads:
| Data feed | Net profit (2020–2025) | Profit factor | Max drawdown |
|---|---|---|---|
| Feed A (Dukascopy ticks) | +$11,200 | 1.32 | 21% |
| Feed B (broker raw ticks) | +$9,800 | 1.28 | 24% |
| Feed C (third-party vendor) | +$12,600 | 1.38 | 19% |
The three feeds agree with each other within a believable band: profit factors 1.28–1.38, drawdowns 19–24%. That convergence is what a real edge looks like — it survives changing the data. When a backtest result collapses under a different feed, the "edge" was data-shaped, not market-shaped. My rule now: any EA must show a profit factor above 1.25 on at least two independent feeds before it touches a demo account, and it must survive forward testing before it touches real money. Backtest, multi-feed confirm, forward test, then — and only then — live.
Modeling quality and slippage, mathematically
MT5 reports a "modeling quality" percentage for every backtest. Most traders glance at it. Here is what it actually means and how to adjust for what it cannot measure:
| Variable | Meaning | Example value |
|---|---|---|
| Backtest Expectancy | Average profit per trade in the tester | +$8.50 |
| Modeling Quality | MT5's tick-data quality score (want 99%+) | 99.9% |
| Slippage per Trade | Measured live slippage, averaged over 100+ live trades | $1.20 |
| Spread Drift | Live spreads minus backtest spreads, per trade | $0.90 |
| True Expectancy | 8.50 × 0.999 − 1.20 − 0.90 = +$6.39 | +$6.39 per trade |
The modeling-quality multiplier is deliberately crude — it is a reminder, not a science. The real work is in the last two rows: slippage and spread drift must be measured live, because no backtest can know your broker's fill behavior. I keep a running log of requested-vs-fill prices on every live account; after 100 trades I have my slippage number, and I subtract it from every backtest expectancy before sizing. An EA with +$8.50 backtest expectancy and $6.39 true expectancy is still tradeable. An EA with +$2.10 backtest expectancy and the same costs is not — and the backtest alone would never tell you.
Backtesting like your capital depends on it
The full routine, in the order I run it for every EA before live deployment:
One: source clean tick data with real bid and ask, minimum ten years, covering a crisis (2008, 2020, or 2022 all work), a trend year, and a chop year. Two: run the defect inspection — visual scan for gaps, spikes, flatlines, weekend stitching. Three: spike-filter at 5× ATR and verify the filter did not remove real volatility (compare a known news day before and after). Four: backtest in "every tick based on real ticks" mode, confirm modeling quality reads 99% or higher, and record every metric — not just profit factor, but drawdown, trade count, and profit by year.
Five: the year-by-year check. If the EA made 80% of its profit in one miraculous year, it is not a strategy — it is a lottery ticket that happened to fit 2020's volatility. I want profits spread across at least 70% of the tested years. Six: multi-feed confirmation on a second independent dataset. Seven: walk-forward or out-of-sample validation — optimize on 2015–2020, validate on 2021–2025, and demand the validation profit factor stays above 1.2. Eight: forward-test on demo for a minimum of 100 trades, logging slippage the whole time.
Nine, the one people skip: size from the worst number, not the average. I take the largest drawdown across all feeds and simulations, add 30%, and size so that drawdown equals no more than 15% of the account. The DarkWolf MT5 Signal Calculator does the position math; the drawdown math I do by hand, because it forces me to look at the scary number. BabyPips' backtesting school is a solid primer if you are new to the tester itself — but the data pipeline above is what separates backtests you can trust from backtests that cost $4,200 to disprove.
The mindset shift that took longest: a backtest is not evidence that a strategy works. It is evidence that a strategy worked on that data. Everything after — the cleaning, the multi-feed checks, the forward test — is the process of asking whether "that data" resembles the future closely enough to bet on. Usually the honest answer is "partially," and you size accordingly. Humility, expressed in position size, is the whole edge.
Backtest data questions
Where can I get free quality tick data for MT5 backtesting?
Dukascopy offers free historical tick data with real bid and ask going back decades — it is the best free source I have found. Your broker's history center is convenient but often bid-only with gaps, so use it for quick tests only. Whatever the source, run the defect inspection (gaps, spikes, flatlines, weekend stitching) before trusting a single result.
What modeling quality percentage should I aim for?
99% or higher, using "every tick based on real ticks" mode with imported tick data. Anything under 90% means the tester is interpolating price movement rather than replaying it, and interpolated fills are fantasy fills. If your data cannot reach 99%, fix the data before you optimize the EA — no setting in the tester compensates for missing ticks.
How many years of data do I need for a reliable backtest?
Ten years minimum, and the years must include different regimes: a crisis, a strong trend year, and a choppy year. Five years of one long trend will make any trend-follower look brilliant and any mean-reversion system look broken. Regime diversity matters more than raw year count — ten years of the same market teach you one lesson ten times.
Why do my live results differ from my backtest?
The usual suspects in order: spread differences (backtest used fixed or optimistic spreads), slippage (zero in the tester, real on live), data defects (phantom fills in the backtest), and over-optimization (the EA fit the noise). Log requested-vs-fill prices live for 100 trades, compare against the backtest's assumptions, and the gap will explain itself. Then subtract the measured costs from the backtest expectancy before sizing.
Should I backtest on M1 data or is H1 enough?
It depends on the EA's holding time. If your EA holds trades for hours, M1 or tick data is mandatory — H1 bars hide the intrabar price action where your stops and entries actually fill. For daily-hold swing EAs, H1 data is usually sufficient. The rule: your data granularity must be finer than your EA's decision granularity, or the tester is guessing at fills inside bars you cannot see.