Summary: This guide covers walk-forward optimization for MT4 backtests, including parameter stability matrices, out-of-sample validation code, and detection of future function leakage for reliable EA performance.




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
  • Profit Factor on OOS > 1.2 (for trend strategies)

  • Maximum drawdown <= 120% of IS maximum drawdown

  • Number of trades >= 30 per OOS window

  • Correlation between IS and OOS equity curves < 0.7 (indicates non-overfitting)


  • 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.