Parameter optimization is where most EAs fail in live trading due to overfitting. Genetic algorithm (GA) in MQL5 Strategy Tester provides a robust search, but without proper validation, you curve-fit to historical noise.
1. GA Core Mechanics in MQL5
MQL5's built-in GA uses selection, crossover (uniform or single-point), and mutation. The default fitness is profit-based, which is dangerous. Custom fitness should include stability metrics.
Fitness formula with overfitting penalty:
```
F = (NetProfit * RiskAdjustment) - (MaxDrawdown * 0.5) - (TradesCount < 100 ? 1000 : 0)
```
To implement custom fitness, you cannot directly modify MQL5 optimizer but can post-process using `OnTester()` return value:
```cpp
double OnTester() {
double profit = TesterStatistics(STAT_PROFIT);
double dd = TesterStatistics(STAT_MAX_DRAWDOWN);
int trades = TesterStatistics(STAT_TRADES);
double fitness = profit - dd * 0.5;
if(trades < 100) fitness -= 1000;
return(fitness);
}
```
Return value drives GA selection. Higher fitness = higher reproduction probability.
2. Population Diversity Preservation
Premature convergence happens when diversity drops below threshold. Diversity formula:
```
D = 1 - (1/N) * Σ|Pi - Pmean| / range
```
where Pi is parameter value. MQL5 GA uses default crossover rate 0.9 and mutation rate 0.01. For 100 population size, optimal mutation rate = 1/L (L=parameter bits). Adjust via `OptimizationSetMutationProbability()` in custom tester.
3. Walk-Forward Validation Protocol
Single optimization is never enough. Implement IS/OOS split:
If IS fitness > OOS fitness by 30%+, overfitting exists. Use forward walk: optimize every 6 months, test next 3 months, slide window.
MQL5 code for walk-forward via custom frames:
```cpp
input datetime forwardStart = D'2024.01.01';
input datetime forwardEnd = D'2024.04.01';
double OnTester() {
datetime testStart = forwardStart, testEnd = forwardEnd;
// Calculate fitness only on OOS period
double oosProfit = TesterStatistics(STAT_PROFIT);
return(oosProfit);
}
```
Run optimization with IS date range, then test with `forwardStart` without re-optimization.
4. Overfitting Detection Metrics
Use Sharpe ratio instead of raw profit:
```
Sharpe = (MeanReturn - RiskFree) / StdDev(Return)
```
Sharpe > 2 is acceptable. Monte Carlo permutation test: shuffle trade sequence 100 times, if original fitness > 95% of shuffled results → overfitted.
Implement via:
```cpp
double SharpeRatio() {
double returns[];
// fill returns from equity array
double avg = returns.Mean();
double std = returns.StdDev();
return(avg / std);
}
```
5. Practical GA Settings for Forex EAs
Reference