Summary: 面向进阶用户的EA参数优化实战,使用遗传算法替代网格搜索。详解染色体编码、SBX交叉、多项式变异及向前走验证协议,附带MQL5可运行代码,有效防止过拟合。




参数优化是EA过拟合的最常见根源。遗传算法通过智能搜索参数空间,性能远超暴力网格搜索。以下为适用于MQL5的生产级遗传算法优化器。

1. 染色体编码
每个参数集为一个染色体,支持连续与离散参数:
```cpp
struct SChromosome {
double params[10]; // 最多10个参数
double fitness; // 适应度(夏普率、盈利因子等)
int generation;
};
```

2. 种群初始化:Sobol序列
优于纯随机:使用拟随机Sobol序列实现均匀覆盖:
```cpp
void InitPopulation(SChromosome &pop[], int size, double &min[], double &max[]) {
for(int i = 0; i < size; i++) {
for(int p = 0; p < ParamCount(); p++) {
double r = SobolSequence(i + 1, p + 1); // 拟随机
pop[i].params[p] = min[p] + r * (max[p] - min[p]);
}
}
}
```

3. 适应度函数:向前走惩罚项
通过样本外周期测试避免过拟合:
```cpp
double ComputeFitness(SChromosome &ch, int inSampleStart, int outSampleStart) {
double inSamplePF = BacktestEA(ch.params, inSampleStart, outSampleStart);
double outSamplePF = BacktestEA(ch.params, outSampleStart, TimeCurrent());
double ratio = (inSamplePF > 0) ? outSamplePF / inSamplePF : 0;
double fitness = inSamplePF * MathMin(1.0, ratio); // 奖励一致性
return fitness;
}
```

4. 交叉与变异算子
模拟二进制交叉(SBX)用于连续参数:
```cpp
void Crossover(SChromosome &p1, SChromosome &p2, SChromosome &c1, SChromosome &c2, double eta) {
for(int i = 0; i < ParamCount(); i++) {
double u = MathRand() / 32767.0;
double beta = (u <= 0.5) ? pow(2*u, 1/(eta+1)) : pow(1/(2*(1-u)), 1/(eta+1));
c1.params[i] = 0.5 * ((1+beta)*p1.params[i] + (1-beta)*p2.params[i]);
c2.params[i] = 0.5 * ((1-beta)*p1.params[i] + (1+beta)*p2.params[i]);
}
}
// 多项式变异
void Mutate(SChromosome &c, double &min[], double &max[], double eta_m, double prob) {
for(int i = 0; i < ParamCount(); i++) {
if(MathRand()/32767.0 < prob) {
double r = MathRand()/32767.0;
double delta = (r <= 0.5) ? pow(2*r, 1/(eta_m+1)) - 1 : 1 - pow(2*(1-r), 1/(eta_m+1));
c.params[i] += delta * (max[i] - min[i]);
c.params[i] = MathMax(min[i], MathMin(max[i], c.params[i]));
}
}
}
```

5. 完整遗传算法主循环
```cpp
void RunGA(int generations, int popSize) {
SChromosome population[];
InitPopulation(population, popSize, minParams, maxParams);
for(int gen = 0; gen < generations; gen++) {
for(int i = 0; i < popSize; i++)
population[i].fitness = ComputeFitness(population[i], inSampleStart, outSampleStart);
SortByFitness(population);
SChromosome newPop[];
for(int i = 0; i < popSize * 0.9; i++) {
SChromosome parent1 = TournamentSelect(population);
SChromosome parent2 = TournamentSelect(population);
SChromosome child1, child2;
Crossover(parent1, parent2, child1, child2, 15);
Mutate(child1, minParams, maxParams, 20, 0.1);
newPop[i] = child1;
}
ArrayCopy(population, newPop, popSize * 0.1, 0);
}
}
```

6. 向前走验证协议
  • 样本内:70%历史数据

  • 样本外:30%滚动窗口

  • 接受条件:样本外盈利因子 ≥ 0.8 × 样本内盈利因子


  • 参考来源:Aronson, David.《基于证据的技术分析》. Wiley, 2006;MQL5官方文档《遗传算法优化》。