首页 / 交易学院 / 小布知识库 / 编程失误让我痛失1.5万美元
编程失误让我痛失1.5万美元
💻

编程失误让我痛失1.5万美元

ATC 2010选手亲述MQL5 EA错误与教训

MQL5开发 难度 · 进阶 2026-02-04 7 分钟阅读
#MQL5#EA开发#ATC2010#编程错误

访谈背景与主人公交易起点

Andrey Voitenko 是 2010 年自动化交易锦标赛(ATC 2010)的参赛选手,这是他第一次参加此类赛事,但其 Expert Advisor(EA)表现成熟,连续数周位列前十。在参加锦标赛之前,他于 2008 年通过朋友和网络广告接触交易,起初从事体力劳动,后来开户手动交易,经历了爆仓与迷茫。当时 MT4 流行,但他并未重视自动化,直到后来发现人工盯盘容易被干扰、难以严格执行系统,才开始学习 MQL4,并坦诚在 ATC 2010 之前并不完全相信自动化交易能稳定盈利。

他的经历对中文交易者的启示是:从手动转型程序化交易是普遍路径,但真正建立信心需要实盘或接近实盘的验证环境,例如锦标赛这样的公开实时账户。他也通过 MQL5 的 Jobs 服务接单开发 EA,认为该服务能借助第三方仲裁降低自由职业者收款欺诈风险,这对想靠 MQL5 技能变现的开发者具有参考意义。

EA 核心逻辑:水平通道突破策略

Andrey 的 EA 基于水平通道突破原理。具体做法是:先根据某段时间内五分钟 K 线的最高价与最低价计算通道上下轨;当价格深入通道内部时,在上下边界各挂一张挂单(限价或止损单);随后等待其中一张被触发,再通过对冲或平仓锁定利润或接受亏损。该系统在市场从低波动区转入高波动区时表现较好。

选择五分钟周期是他通过测试优化得出的,目的是让 EA 保持较高活跃度。之所以只用挂单而不直接市价成交,是因为挂单的价位清晰体现了通道逻辑,便于锦标赛中审查与追踪,也避免市价单在滑点下的不可控。这种“只做突破、不做回踩”的单纯逻辑,后来成为他人建议改进的基础,例如有人提议在通道较宽时增加边界 pivot 回踩交易。

致命错误:移动止损的条件写错

Andrey 在访谈中反复强调,他最大的失误在于 trailing stop(移动止损)的实现。原本并不是传统意义上的 bug,而是“非标准实现”:代码中的触发条件无效,导致止损被立刻拉近到市价附近,使仓位无法承受正常波动,利润来不及展开就被扫损。他后来修正了该部分,发布了第二版 EA,采用经典移动止损算法。

他估算,如果不是这个草率实验,当时账户余额本可增加 1.5 万美元,排名升至第三并有望获得现金奖励。也就是说,一个看似微小的逻辑错误,直接造成了巨额机会成本。对中文开发者而言,这提醒我们:止损模块必须经过历史回测与样本外验证,不能凭感觉在参赛或实盘前临时修改。

⚠ 常见坑:止损距离动态计算错误
若用 Point 或 bid/ask 差值计算 trailing 距离,未考虑最小止损位数或点值精度,会让 SL 贴太近。务必用 NormalizeDouble 并对齐 SymbolInfoInteger(SYMBOL_TRADE_STOPS_LEVEL)。

资金管理模块的取舍与风险

Andrey 的 EA 其实内置了简单的资金管理:按当前自由保证金的固定百分比计算手数。但在锦标赛中他故意关闭了该模块,从一开始就固定使用 5 手,理由是“慢而稳才能赢”并不适用于追求排名的竞赛。关闭后风险不再随资金浮动,变成固定手数偏激进的模式。

他指出,如果锦标赛启用资金管理并采用允许的最大手数,结果可能完全不同。这反映出竞赛与实盘的目标冲突:竞赛要短期高收益排名,实盘要回撤可控。中文交易者写 EA 时应明确用途,不要将赛用参数直接用于实盘,否则 50% 回撤(他锦标赛初期就遇到)在实盘可能致命。

✦ 建议
将 MM 开关设为输入参数 Input,回测时对比固定手数 vs 百分比手数的权益曲线,再决定实盘采用哪种。

回测、优化与曲线平滑的真相

赛前测试效果优于预期,因此他在截止前一个月提交后未改代码。优化 criterion 他选的是“最大余额”而非“最小回撤”,因为目标就是锦标赛排名。其权益曲线看似平滑,主要得益于及时获利了结的算法,而非刻意压低回撤。他的 EA 同时挂 SL 与 TP,但因 trailing stop 修改多次,TP 设得极远几乎不触发,实际靠移动止损出场。

约 50% 回撤发生在锦标赛初期余额较小时,他归因于 12 月 6 日价格懒散来回触碰通道边界、反复被扫损;换成第二版经典 trailing 后曲线明显更平滑。这说明:同一策略逻辑,出场模块差异能彻底改变风险特征。中文开发者优化时不能只看 profit factor,必须观察 equity drawdown 时间点。

社区反馈与后续演进方向

由于 EA 开源发布,网友提出多处改进:通道边界 pivot 回踩交易、参数绑定通道宽度而非固定值、更进阶的资本管理模块、以及最费力的“倾斜通道”替代水平通道。Andrey 表示愿做自然演进,未来版本仍免费放官网。他还看好多货币 EA,认为 Manov 的 EA 曲线优美、按最小回撤优化,若手数更大将难逢敌手。

往届冠军本届表现不佳,他认为除自身编程错误外,新晋者准备更充分、动机更强也是原因。对中文读者的价值是:EA 不是一劳永逸,市场如活物,需持续迭代;参与社区 Jobs 与讨论能暴露盲点。

可借鉴的 MQL5 代码思路(伪代码级)

虽然原文未给完整源码,但依据描述可反推关键片段结构。下面示例展示通道计算与挂单、经典 trailing 的骨架,帮助理解错误所在与正确写法。

// 计算 5分钟通道
int bars = iBars(_Symbol, PERIOD_M5);
double hi = iHigh(_Symbol, PERIOD_M5, iHighest(_Symbol, PERIOD_M5, MODE_HIGH, 20, 0));
double lo = iLow(_Symbol, PERIOD_M5, iLowest(_Symbol, PERIOD_M5, MODE_LOW, 20, 0));
// 错误写法:条件无效导致 SL 立刻贴近
// double sl = price - 1*Point; // bug: 未考虑 stops level
// 正确经典 trailing
if(position_profit > 0){
   double new_sl = SymbolInfoDouble(_Symbol, SYMBOL_BID) - TrailDist*Point;
   if(new_sl > position_sl) trade.PositionModify(ticket, new_sl, TP);
}

给中文 MQL5 开发者的实操清单

总结 Andrey 的教训,我们可落地为开发规范:第一,任何出场逻辑改动必须先走样本外测试;第二,止损距离必须校验 SYMBOL_TRADE_STOPS_LEVEL;第三,锦标赛与实盘参数分离;第四,优化目标依用途定,但都要监控 drawdown;第五,挂单策略需明确边界意义;第六,开源获反馈但需自担误用风险。

✦ 延伸阅读
原文访谈见 https://www.mql5.com/zh/articles/538 ,其中提及 MQL5 Jobs 与官方终端下载,均可在对应站内找到。

常见问题

他的 EA 移动止损条件写错,导致止损被立即拉近市价,仓位被过早扫损;修正为经典 trailing stop 后曲线更平滑,该错误让他少赚约 1.5 万美元排名奖金。
计算新 SL 时需用 SymbolInfoInteger(SYMBOL_TRADE_STOPS_LEVEL) 获取最小止损点数,并用 NormalizeDouble 对齐点位,且新 SL 必须优于原 SL 才修改。
如 Andrey 所言,锦标赛目标为短期排名最大化余额,故关闭百分比 MM、用固定或最大手数更激进;实盘则应开启 MM 控回撤,两者不可混用。
先取 N 根 M5 的 high/low 算上下轨,当价格位于通道内时用 CTrade::BuyStop / SellStop 在边界挂单,触发后按 trailing 或 TP 出场,注意校验挂单距市价合规。