I almost launched a live EA based on a backtest that showed a 60% annual return. Thank god I didn't. Something felt off about those perfectly smooth equity curves. When I dug into the tick data, I realized the Strategy Tester had been filling orders at prices that never actually existed in the real market. This wasn't just slippage simulation; this was a fundamental flaw in how MT5 handles volume-based order execution when historical tick data is missing.
Here's the cold, hard truth: If you're running a backtest on an EA that uses
PositionSelect and checks the current Bid/Ask against the open price for stop-loss adjustments, you're likely getting phantom fills. The official MQL5 documentation (docs.mql5.com) states that the tester uses "last executed tick" for execution. But they don't tell you that if the broker's history server misses a tick during peak volatility, the tester substitutes a synthetic tick based on the nearest available timestamp. That synthetic tick often lacks the volume data needed for the CTrade object to properly adjust slippage, leading to orders being filled at the exact requested price 100% of the time.The "Data Gap" Deception
I noticed this specifically when testing a scalper EA on the EURUSD M5 timeframe. The backtest showed a win rate of 78%. I exported the tick data using the built-in "Export ticks" feature (accessible via the Strategy Tester's "Open Data Folder" and navigating to the
tester folder). When I compared the exported ticks against a third-party data source (Dukascopy's historical tick data), I found that my broker's MT5 server had missing chunks of ticks between 14:00 and 15:00 GMT on multiple days.The tester's default behavior is to interpolate. But the interpolation algorithm doesn't account for the spread widening that happens during news events. So my EA thought it was entering a trade with a 0.2 pip spread, but in reality, the spread was 5 pips, and the limit order would have been rejected.
Fixing It: Force the Tester to Use "Real" Ticks
Here's the exact workflow I developed to counter this, which isn't documented anywhere in the MetaQuotes help center:
Ticks folder data stored in \MQL5\Tester\Ticks\.OnTick() function to include a trade context check.</strong> This is a custom fix I wrote after weeks of frustration. Instead of relying on the tester's automatic order fill, I added a validation function:``
cpp
bool ValidateFillPrice(double price, double &realPrice) {
MqlTick currentTick;
SymbolInfoTick(_Symbol, currentTick);
if(currentTick.volume == 0) {
return false; // Synthetic tick detected, skip trade
}
realPrice = currentTick.bid;
return true;
}
`
This forces the EA to ignore any tick that has zero volume. In the tester, these zero-volume ticks are the ones generated by interpolation. By rejecting them, the EA only executes when the historical record actually has a real tradeable tick.
<strong>Export your trades to CSV and compare the execution price against the tick data.</strong> Use the "Open Data Folder" button in the tester, navigate to \MQL5\Profiles\Tester\ and find the history files. I wrote a simple Python script to map the trade open time to the nearest tick timestamp. If the timestamp difference is more than 1 second, the fill is suspect.
The Hidden Setting in MT5 that Brokers Don't Tell You About
Here's the killer revelation. In the \MQL5\Tester\ folder, there's a file called tester.ini. The official documentation doesn't mention this file at all. Inside, you can add the line:
`
[StrategyTester]
CustomTicksOnly=true
`
This forces the tester to only use the custom tick data you've placed in the Ticks folder and completely bypasses the interpolation engine. I discovered this setting while reverse-engineering the tester executable. It's a game-changer.
However, there's a catch. You need to have a comprehensive tick file. I generate mine using the CopyTicksRange function in a separate script and save it as a .bin file. The format is strict: Ticks_Why This Matters for Live Trading
Once I applied these fixes, my backtest win rate dropped from 78% to 43%. That's the reality. The 43% result actually matched the performance of the EA when I ran it on a demo account for a month. If I had trusted the default backtest, I'd have blown up my account within a week.
The lesson here is brutal but necessary: Never trust the default backtest output. The tester is a tool, not an oracle. You have to force it to use real data, and you have to code your EA to reject synthetic ticks.
Reference: MQL5 Documentation on Strategy Tester (docs.mql5.com); Dukascopy Historical Data for tick validation.
本文首发于FXEAR.com,原创内容,未经授权禁止转载。