Summary: This guide focuses on eliminating future functions and data snooping bias in MT4 backtests. Provides safe OrderSend implementation, bar shifting rules, and minimum sample size formulas.
The difference between a profitable backtest and a live disaster often comes down to one thing: future function leakage. MT4's strategy tester cannot detect logical errors where your EA uses price data that would not have been available at decision time.
The Bar Shifting Rule
The most common future function is accessing `Close[0]` or `High[0]` before the bar closes. In real-time trading, `Close[0]` changes constantly. In backtest with "Every tick" mode, `Close[0]` at bar open equals `Open[0]`, but at bar close it equals `Close[0]` - creating look-ahead bias.
Safe Implementation: Shift by 1
```cpp
// MQL4 - Safe entry condition using only closed bar data
input double LotSize = 0.1;
input int FastMA = 5;
input int SlowMA = 20;
bool ShouldBuy() {
// Use indexes 1 and 2 - NEVER 0 for decision
double FastMA_prev = iMA(NULL, 0, FastMA, 0, MODE_SMA, PRICE_CLOSE, 1);
double FastMA_current = iMA(NULL, 0, FastMA, 0, MODE_SMA, PRICE_CLOSE, 2);
double SlowMA_prev = iMA(NULL, 0, SlowMA, 0, MODE_SMA, PRICE_CLOSE, 1);
// Crossover detection using fully closed bars
if(FastMA_prev > SlowMA_prev && FastMA_current <= SlowMA_current) {
return true;
}
return false;
}
// Safe OrderSend with error handling
int OpenBuyOrder() {
if(!ShouldBuy()) return -1;
double sl = Bid - 50 * Point;
double tp = Bid + 100 * Point;
int ticket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp, "EA Entry", 0, 0, Green);
if(ticket < 0) {
Print("OrderSend failed: ", GetLastError());
return -1;
}
return ticket;
}
```
Data Snooping Bias Formula
The probability of finding at least one profitable strategy by chance increases with the number of tests:
\[
P(\text{at least one false positive}) = 1 - (1 - \alpha)^n
\]
Where \( \alpha \) is significance level (typically 0.05) and \( n \) is number of strategies/parameters tested. With 100 tests, probability of a false positive reaches 99.4%.
Minimum Out-of-Sample Bars Required
For statistically valid backtest results, the minimum number of trades \( N \) required:
\[
N = \left( \frac{Z_{\alpha/2} \cdot \sigma}{\delta} \right)^2
\]
Where \( \sigma \) is standard deviation of returns, \( \delta \) is expected drawdown tolerance, \( Z_{\alpha/2} = 1.96 \) for 95% confidence. For daily strategies, this typically requires 3-5 years of data.
Three Validation Steps After Every Backtest
1. Monte Carlo simulation: Randomly shuffle trade sequence 1000 times. If 10th percentile Sharpe ratio < 0, your strategy lacks edge.
2. Parameter stability test: Vary each parameter ±20%. If performance drops more than 30%, the strategy is over-optimized.
3. Walk-forward analysis: Divide data into 70% in-sample, 30% out-of-sample. Optimize on in-sample, validate on out-of-sample without re-optimizing.
Tick Simulation Limitations
MT4's "Control points" and "Open prices only" modes are insufficient for stop-loss and trailing stop validation. Always use "Every tick" mode when testing strategies with pending orders, stops, or take-profits. The difference in maximum adverse excursion (MAE) can exceed 30% between tick modes.
Reference: MQL4 Community - Backtesting Best Practices (https://www.mql5.com/en/articles/1519), "Evidence-Based Technical Analysis" by David Aronson, 2006.