Backtest accuracy determines EA reliability. Single-pass optimization on full history produces illusionary equity curves that fail forward. Walk-forward optimization (WFO) separates in-sample (IS) training from out-of-sample (OOS) validation, providing realistic performance expectations.
Walk-Forward Framework
Divide historical data into N overlapping windows. For each window, optimize on IS period, then validate on subsequent OOS period. The OOS results from all windows form the true performance estimate.
Let window size \( W \) and test size \( T \). Rolling WFO:
\[
P_{\text{true}} = \frac{1}{M} \sum_{i=1}^{M} P_{\text{OOS}}^{(i)}, \quad M = \left\lfloor \frac{B_{\text{total}} - W}{T} \right\rfloor
\]
where \( B_{\text{total}} \) is total bars count.
Parameter Stability Matrix
Optimal parameters should remain stable across different market regimes. Compute the coefficient of variation for each optimized parameter:
\[
CV(\theta_j) = \frac{\sigma_{\theta_j}}{\mu_{\theta_j}} \times 100\%
\]
If \( CV > 15\% \), parameter \( \theta_j \) lacks stability and requires redefinition.
MQL4 Walk-Forward Implementation
```cpp
// MQL4 code - Complete Walk-Forward Optimizer
input int InSampleBars = 4000; // Training period
input int OutSampleBars = 1000; // Testing period
input int OptimizationSteps = 5; // Parameter granularity
struct OptimizationResult {
double ProfitFactor;
double SharpeRatio;
double MaxDrawdownPct;
int MAPeriodOptimal;
int RSIThresholdOptimal;
};
OptimizationResult results[];
void RunWalkForwardOptimization() {
int totalBars = Bars;
int windows = (totalBars - InSampleBars) / OutSampleBars;
ArrayResize(results, windows);
for(int w = 0; w < windows; w++) {
int isStart = w * OutSampleBars;
int isEnd = isStart + InSampleBars;
int oosStart = isEnd;
int oosEnd = oosStart + OutSampleBars;
// Grid search on IS period
OptimizationResult best = OptimizeOnRange(isStart, isEnd);
// Validate on OOS period
ValidateOnRange(best, oosStart, oosEnd);
results[w] = best;
}
// Compute aggregate OOS metrics
double avgProfitFactor = 0;
for(int i = 0; i < windows; i++) {
avgProfitFactor += results[i].ProfitFactor;
}
avgProfitFactor /= windows;
Print("Walk-forward Profit Factor: ", avgProfitFactor);
}
```
Detecting Future Function
Future functions peek at unclosed bar data. Common violations in MQL4 include using `iClose(NULL,0,0)` inside `start()` before bar confirmation, or referencing `OrderOpenPrice()` without checking `OrdersTotal()` properly.
Validation Rule: Any price-based decision must use data with index >= 1. The exception is trailing stop modifications which use current price for exit only, never entry.
OOS Acceptance Criteria
Mathematical Overfitting Detection
Compute the F-statistic for parameter sensitivity:
\[
F = \frac{\text{Var}(P(\theta + \delta))}{\text{Var}(P(\theta))}
\]
High F indicates that small parameter changes cause large performance swings, signaling instability.
Reference: MQL5 Documentation - Strategy Tester (https://www.mql5.com/en/docs/tester), "Evidence-Based Technical Analysis" by David Aronson, 2006.