自训练 EA:用遗传算法让 EA 自己决定何时再优化、换策略
EA 上线后最尴尬的事,是市场一变参数就失效,而你还在手动跑优化。本文的核心思路:把“是否再优化、换成哪个策略、参数取什么”变成 EA 自己的运行逻辑,用遗传算法在变化的市场里持续搜索更好的配置,尽量不中断交易。
一、自训练 EA 要解决什么问题
传统流程是:跑回测→选参数→上线→行情变了→停 EA→再优化→再上线。这个循环靠人盯,反应慢、还打断交易。自训练 EA 把“再优化决策”和“再优化执行”本身变成 EA 的一部分:它一边交易,一边在后台判断是否需要重算参数,需要时调用 GA 找新解。
二、EA 的三大职责:交易 / 决策 / 再优化
一个自训练 EA 要明确做三件事:用选定策略正常交易;决定“现在该不该再优化”;用遗传算法执行再优化。最简单的再优化是单一策略换参数;进阶的是让 GA 在变化后的市场里直接挑选另一套策略(比如从均线交叉切到神经网络)。
- 交易:在已完成 K 线上交易,不加点位、不部分平仓,简化资金管理
- 决策:监控相对回撤,达到阈值就触发再优化
- 再优化:调用 GA,搜索更优的参数/策略/交易品种组合
- 初始化:建指标缓存、设神经网络拓扑、调 GA、记录最大余额作为再优化起点
三、适应度函数怎么写
每一个交易策略有自己专属的适应度函数(FF),每次再优化都会重新创建。对均线策略的 FF 和神经网络策略的 FF 完全不同。文章示例里,FF 的结果是“最大余额”,前提是相对回撤没超过外部变量设的临界值(示例 0.5);如果某次 GA 跑出余额 100000 但相对回撤 -0.6,FF 直接判 0。
// 检测新 K 线开盘(节选)
bool isNewBars() {
CopyTime(s,tf,0,1,curBT);
TimeToStruct(curBT[0],curT);
if(tf==PERIOD_M1||...||PERIOD_M30)
if(curT.min!=prevT.min){ prevBT[0]=curBT[0]; ...; return(true);}
// H1/D1/MN1 类似按 hour/day/mon 判断
return(false);
}
// 根据可用保证金算手数
double GetPossibleLots() {
request.volume=1.0;
OrderCheck(request,check);
return(NormalizeDouble(AccountInfoDouble(ACCOUNT_FREEMARGIN)/check.margin,2));
}
四、遗传算法做再优化
GA 每次运行会产出一组“性能结果”:对均线策略是均线周期,对神经网络是突触权重,共同的部分是“下次再优化前交易哪个品种”和“用多少保证金比例 optF”。你还可以往 FF 里加更多优化维度,比如时间框架。EA 初始化时先跑一次 GA 拿到初解,之后在触发条件下反复重跑。
// OnInit 里调用遗传优化并取结果
int OnInit() {
tf = Period();
depth = 10000; count = 2; // 历史深度与每次复制根数
ArrayResize(LongBuffer,count); ArrayResize(ShortBuffer,count);
GA(); // 遗传优化
GetTrainResults(); // 取优化后的参数
InitRelDD(); // 记录最大余额(再优化起点)
return(0);
}
五、再优化触发条件:相对回撤
什么时候该再优化?文章用“相对回撤(RelDD)”作触发器:一旦相对余额回撤达到外部变量设的临界值(示例 0.2),就跑 GA 再优化。为避免在临界值上每根 K 线都触发,触发后把“最大余额”更新为当前值,作为新一轮起点。你的 EA 完全可以用别的标准(比如收益曲线斜率、波动率突变)。
// 记录最大余额 / 计算相对回撤
void InitRelDD() {
curBalance = AccountInfoDouble(ACCOUNT_BALANCE);
maxBalance = curBalance;
HistorySelect(D'2000.01.01',TimeCurrent());
for(int i=HistoryDealsTotal();i>0;i--){
DealTicket=HistoryDealGetTicket(i);
curBalance+=HistoryDealGetDouble(DealTicket,DEAL_PROFIT);
if(curBalance>maxBalance) maxBalance=curBalance;
}
}
double GetRelDD() {
if(AccountInfoDouble(ACCOUNT_BALANCE)>maxBalance) maxBalance=AccountInfoDouble(ACCOUNT_BALANCE);
return((maxBalance-AccountInfoDouble(ACCOUNT_BALANCE))/maxBalance);
}
六、两种策略示例:均线交叉 vs 神经网络
文章给了两套可运行的策略源码。其一是双均线交叉(金叉买入、死叉卖出),其二是简单神经网络,输入是最近五个交易时段的价格变动(归一化到 [0,1])。两者都通过同一个 GA 框架驱动:GA 负责选品种、选 optF、选各自参数;交易逻辑在 OnTick 里根据新 K 线触发。
七、实战注意与风险
自训练 EA 很诱人,但坑也不少。第一,再优化用的是历史,历史不代表未来,GA 仍可能过拟合某段行情;第二,回测模式要和实盘一致,只用“仅开盘价”会低估止损止盈的影响,关键策略请用“每一价格变动”;第三,GA 跑在 OnInit/触发时,别让它阻塞 OnTick 的主交易逻辑。把这些想清楚,自训练才是加分项而不是定时炸弹。
八、小结
自训练 EA 把“参数维护”从人工循环变成 EA 的内置能力:用相对回撤触发、用遗传算法搜索、用专属适应度函数评估。它适合“行情多变、需要 EA 自己微调”的场景,但本质仍是历史外推,过拟合和回测一致性是两条必须守住的底线。把它当“会自我微调的助手”,而不是“印钞永动机”。