会自己换策略的 EA:Trademinator 3 遗传算法自优化架构
手动把 EA 参数调到“刚好适合某段历史”是件苦差事,而且市场一变就失效。Trademinator 3 的思路更激进:让 EA 自己在历史数据里选出“最佳策略 + 最佳品种 + 最佳存款占比 + 最佳指标参数”的组合,实盘里一旦回撤超阈值就重新优化。它把遗传算法从“调一个策略的参数”升级成“在所有策略里选最好的那一个”。本文拆解它的架构与关键代码。
一、自优化 EA 要回答的四个问题
作者先定义了自优化 EA 的硬性要求:在历史数据上,它要能(1)从候选策略里选最好的;(2)选最佳交易品种;(3)选带杠杆校正的存款占比;(4)选该策略指标的最佳参数。在实盘上,它还要能(5)开平仓、选仓位大小、(6)判断是否需要新一轮优化。这六个能力把“策略选择”和“参数优化”合并成一个搜索问题——这正是遗传算法擅长的事。
二、设计约束:只在新的 K 线做决定
为了避免过度交易和重绘,作者给 EA 加了明确约束:交易决定只在“选定时间周期出现新柱”时做;平仓只依据指标信号(不用止盈/止损/追踪止损,纯信号驱动);触发新优化的条件是“余额回撤超过初始化时预设的最大值”。适应度函数则要求:在历史中最大化模拟余额,同时约束相对回撤低于某预设水平。这些约束既控制风险,又给优化器划定了清晰的搜索边界。
- 决策频率:仅在新柱出现时评估信号,避免每 tick 抖动
- 平仓逻辑:纯指标信号驱动,不依赖止盈/止损/追踪止损
- 再优化触发:余额回撤 > 预设最大回撤(maxDD)时调用 GA()
- 参数数量上限:每策略待优化指标参数 ≤ 5(受内置指标缓冲区上限约束)
三、OnTick 主循环:策略分派与回撤监控
EA 的核心在 OnTick:先 isNewBars() 判断有无新柱,有则按当前 strat 用 switch 分派到对应的 NeedCloseX 函数(MA/SAR/Stoch…)。NeedCloseX 返回 true 表示应平仓。平仓后检查 GetRelDD()(相对回撤)是否超过 maxDD——超了就调用 GA() 重新遗传优化,再 GetTrainResults() 取回新参数,并把回撤基准从历史最高余额切到当前余额。这样“信号平仓”和“回撤触发再优化”被串成一条自动闭环。
// OnTick 主循环骨架(节选)
void OnTick()
{
if(isNewBars()==true)
{
trig=false;
switch(strat) // 当前选定的策略
{
case 0: trig=NeedCloseMA(); break;
case 1: trig=NeedCloseSAR(); break;
case 2: trig=NeedCloseStoch();break;
default: trig=NeedCloseMA(); break;
}
if(trig==true)
{
if(GetRelDD()>maxDD) // 回撤超限 -> 重新优化
{
GA(); // 调用遗传优化
GetTrainResults(); // 取回最优参数
maxBalance=AccountInfoDouble(ACCOUNT_BALANCE); // 基准切到当前余额
}
}
}
}
四、平仓信号函数:以 SAR 为例
每个策略对应一个布尔型 NeedCloseX 函数,平仓时返回 true,OnTick 才能据此决定是否进入再优化流程。以 SAR 策略为例:读 SAR 缓冲与前一根开盘价,当 SAR[0]>Open[0] 且 SAR[1]<Open[1](或反向)时,若有持仓就 ClosePosition() 并返回 true。函数必须是布尔型且平仓时返回 true,这是整套机制能跑通的契约。
// NeedCloseSAR:SAR 翻转即平仓(节选)
bool NeedCloseSAR()
{
CopyBuffer(SAR,0,0,count,SARBuffer);
CopyOpen(s,tf,0,count,o);
if((SARBuffer[0]>o[0] && SARBuffer[1]<o[1]) ||
(SARBuffer[0]<o[0] && SARBuffer[1]>o[1]))
{
if(PositionsTotal()>0) { ClosePosition(); return(true); }
}
return(false);
}
五、遗传优化与适应度函数
GA() 调用 GAModule.mqh 里的适应度函数 FitnessFunction(int chromos)。染色体(chromos)编码了策略、品种、存款占比和指标参数;适应度函数按这组基因在历史中模拟交易,目标是最大化余额、同时把相对回撤压在预设水平下。GetTrainResults() 再从最优染色体里解出 strat(最佳策略)和 s(最佳品种),切换 EA 的当前配置。这样 EA 不是“一个写死策略”,而是“一个会挑策略的机器”。
六、小结
Trademinator 3 把遗传算法从“调参”升级为“选策略 + 调参 + 选品种”的一揽子搜索:OnTick 按当前策略评估信号、按回撤触发再优化、适应度函数在历史中最大化余额并约束回撤、GetTrainResults 把最优染色体解码回运行配置。它是“自适应 EA”的范本,但代价是需要严谨的样本外验证与回撤护栏——否则自动化反而放大了过拟合。把它当架构参考,而不是“装上去就躺赚”的黑盒。