开发多币种 EA 交易(第 7 部分):根据前向时间段选择组(基础篇)
「用前向测试给多币种组挑样本」
多币种 EA 在回测里很容易过拟合到某一组货币对,但换一组就垮。一个实用办法是把历史切成训练段和前向段:先在训练段上跑优化,再把参数原样丢到没参与优化的前向段去验证,只保留两段都稳的组。 具体落地时,可在 EA 里用 Period() 配合自定义时间窗口标记,区分前向与训练样本。下面这段代码演示了如何根据当前品种是否处于前向窗口返回布尔开关,供后续选组逻辑调用。 [CODE] bool IsForwardPeriod(string symbol, datetime start, datetime end) { datetime cur = iTime(symbol, PERIOD_D1, 0); // 取品种当日起始时间 if(cur >= start && cur <= end) return true; // 落在前向窗口内返回真 return false; // 否则返回假 } [/CODE] 上述函数逐行看:第一行定义符号、起止时间入参;第二行用 iTime 抓日线第 0 根 K 线时间;第三行判断该时间是否在前向区间内;第四行区间外直接否。把它接进组筛选,能在 MT5 策略测试器里复现「训练—前向」两段式验证。 外汇与贵金属杠杆高、滑点跳空频繁,前向段通过不代表实盘必赢,只是把过拟合概率压低一截。开 MT5 把这段塞进你的多币种框架,先跑 2020–2021 训练、2022 前向,看组留存率再决定上不上线。
class="type">bool IsForwardPeriod(class="type">class="kw">string symbol, class="type">class="kw">datetime start, class="type">class="kw">datetime end) { class="type">class="kw">datetime cur = iTime(symbol, PERIOD_D1, class="num">0); class=class="str">"cmt">// 取品种当日起始时间 if(cur >= start && cur <= end) class="kw">return true; class=class="str">"cmt">// 落在前向窗口内返回真 class="kw">return class="kw">false; class=class="str">"cmt">// 否则返回假 }
用前向时段逼出策略真面目
我之前一直拿 2018–2022 这同一段历史磨单个策略实例。这段跨度够长,塞进了不少搅动价格的大事件,但也不算离谱地长——单次优化跑完只要几十秒。特意把窗口留到距当下还有一年多,等于留出一块优化时没碰过的历史,专门看策略脱离拟合环境后怎么走。 MT5 测试器自带前向测试机制:把指定周期切成两段,前段是主要时段,后段是前向时段。主要时段结束会平掉所有单、账户复位到初始资金,然后 EA 在前向段重跑一遍,统计上两段各自独立记账。机器学习里叫 IS(样本内)和 OOS(样本外),这里主要段就是 IS,前向段是 OOS。不过 OOS 概念更宽——哪怕不勾前向、只要测试区间落在优化区间之外,也算跑在样本外。 此前绝大多数回测都没认真走 OOS,现在该较真了:前向段里策略表现能不能接近主要段,才是判断它有没有过拟合的底牌。外汇与贵金属波动受事件驱动明显,这种跨样本衰减是高概率风险点,得用 MT5 自己跑一遍才作数。
◍ 手动与自动选组的前向表现对比
用 2023 全年做前向时间段,相对主要时间段短了约 5 倍,预期前向利润落在主段约五分之一、回撤不高于主段。BaselineExpert.mq5 手动策略组在前向段明显走弱:回撤由主段 10% 升到 12%,恢复耗时超 6 个月,但余额曲线尚未逆转。 OptGroupExpert.mq5 无聚类自动选组在前向段仅微利,回撤放大约 1.5 倍,说明主段最优组的外推性有限。OptGroupClusterExpert.mq5 参数集聚选组结果同样模糊,回撤更宽,群集内仅剩一组、各组合差异不大,已无单独列示必要。 外汇与贵金属 EA 前向衰减属高风险信号,上述三组均未达预期前向基准。下一步应直接在前向段重跑优化,避免手动逐组回测上轮参数。
「前向验证下的参数成色」
把 OptGroupClusterExpert.mq5 的优化结果按主要时间段(IS)和前向时间段(OOS)分别导出成 XML 再转 Excel,用 Pass 列做关键值把两表合并,按主要段归一化利润降序排,并用颜色区分两段数据,能直接看出过拟合迹象。 初步合并后就很扎眼:主要时间段排在最前的那些最优参数,到了前向时间段大多翻负。损失不算灾难级,年化大约吃掉初始余额的 3%–5%,但显然不是我们想要的泛化表现。 两段的 Forward Result 与 Back Result 都来自 EA 的 OnTester() 返回值,定义为归一化利润:Result = Profit * (10% / EquityDD),即把最大相对回撤拉伸到 10% 时测得的估计利润。若前向段也套用主要段的仓位缩放系数 coeff = 10% / EquityDD_IS,就要做修正:ForwardResultCorrected = ForwardResult * (EquityDD_OOS / EquityDD_IS)。 修正后绝对数值变大,逻辑很直接。比如主要段某组回撤 1.52%,仓位可放大 6.58 倍;若前向段回撤 4.03%,原算法只放大 2.48 倍,未修正的 -240 其实是被低回撤低估了,修正后同口径应为 -635。 按修正后的前向列重排,仍有少数组在前向段为正。它们的共同点是主要段标准利润约 15000–18000 美元,两段回撤差不大,前向归一化利润约为主要段的五分之一。外汇与贵金属品种波动跳变频繁,这种 OOS 衰减是高概率风险,上 MT5 跑一遍自己的品种就能复现。 挑参数时别只盯 IS 顶端,把 ForwardResultCorrected 为正且回撤比靠近 1 的组先筛出来,再回看它们的集群编号,才有可能挑出活得过样本外的一组。