ATC冠军选手访谈:MQL5多币EA实战
从策略构建到避坑的自动化交易经验谈
选手背景与编程基础
Francisco García García(社区ID:chuliweb)来自西班牙格拉纳达附近的小镇Huéscar,拥有格拉纳达大学计算机科学学位,职业是中学教师。他并非金融科班出身,但具备扎实的编程功底,熟悉C、C++、Java、PHP、Perl、ASP、LISP等多种语言。在他看来,只要理解通用编程原理,切换到某一具体语言的特性并不困难,关键是选对工具。他注册MQL5社区并参加2012自动交易锦标赛(ATC 2012),初衷是检验自己的算法交易能力。
在锦标赛进行约一周时,他的EA曾冲到排行榜第8位,但因一个编程逻辑错误被踢出第一页。这类错误在参赛者中并不罕见。统计显示,许多淘汰源于对交易请求发送机制或止损逻辑的处理不当,而非策略本身无效。这也说明,对于非职业程序员,严格测试与规则对齐和策略研发同样重要。
为何选择MQL5而非MQL4
Francisco明确表示自己更倾向于MQL5。他认为MQL5相比MQL4有显著改进,核心在于引入了面向对象编程(OOP)与事件驱动机制。面向对象让代码模块化和复用更自然;事件处理(如OnTrade、OnTick)使EA能精确响应成交、报价等动作,而不必在主循环里轮询。对于需要动态管理多货币挂单体积的他来说,MQL5的事件模型是不可或缺的工作基础。
从情绪化亏损到纯算法交易
Francisco约有5年外汇自学经历,试过多个平台后固定在MetaTrader。他坦诚自己即使在模拟账户也无法控制情绪:扛亏损单或没落袋就关终端都让他难以执行策略。理性上他不愿拿本金冒险,因此决定只做策略编程,让机器消除人为情绪对账户的破坏。这也是很多中文兼职交易者的真实痛点——不是不懂策略,而是执行变形。
他认为编码反而是自己擅长的部分,真正的难点永远在前面:找到能稳定盈利的策略,以及挑出合适的参数。许多策略对特定货币对有效,但参数优化极易过拟合。若在历史数据上把利润最大化,实盘必崩。他的解法是前向测试(Forward Testing):先用一段历史回测,再拿另一段未参与优化的样本验证。
参赛EA的策略逻辑与周期选择
他的EA只在GBPUSD、USDCHF、EURJPY三个货币对上交易,刻意排除了包括EURUSD在内的其他品种,原因是那些要么不赚钱,要么只在极短时段盈利。EA在D1周期上运行,每两天对每个货币对评估一次。它不使用任何指标,而是比较当前价与前几日OHLC价格,挂出买卖挂单,让市场选择触发哪边。
他不用 trailing stop,偶尔手动把止损移到盈利位。由于锦标赛不到三个月,他认为D1在噪声与攻击性间取得平衡:小周期假信号多,大周期来不及跑。资金管理考虑每日波幅与多单敞口;EA是多货币的,他用OnTrade事件动态调节挂单体积,避免保证金不足,并用其他挂单抵消亏损,类似组合止损。
回测、前向测试与云网络
Francisco用策略测试器跑了两年历史回测,再做前向测试。他没用MQL5云网络(Cloud Network)的算力,而是用自己机器以另一种方式验证,但也高度推荐该服务给所有EA开发者。云网络能调动社区空闲算力,大幅缩短优化时间,尤其适合参数空间大的多货币策略。
他强调,优化系统到‘无需调整’几乎不可能。正确流程应是:隔离样本内/样本外数据,样本内粗调,样本外确认;若样本外衰减严重,说明策略被噪声捕获。前向测试本质是滚动窗口模拟,比单纯看回测曲线诚实。
调试经历与官方文档救场
测试阶段他的EA出现过违规手数与错误止损位。他特别感谢两篇官方文章:《How to Fix Errors in Trading Robots》和《Trading Rules of the ATC 2012》。最大麻烦在发送交易请求的算法有误——后来得知不少参赛者栽在同一处。ATC对最小手数、止损距离、挂单位置有硬规则,EA必须主动校验,否则单子被拒或被判违规。
在MQL5中,下单需用CTrade或OrderSend,并检查返回码与ResultRetcode。例如,挂单价格必须离市价足够远(点差+止损级别),止损必须高于/低于对应价位一定点数。他建议在每次交易动作后打印trade.ResultRetcodeDescription(),快速定位违规原因。
// 示例:安全发送挂单的简化检查
#include <Trade/Trade.mqh>
CTrade trade;
void PlacePending(double price, double sl, double tp, double lot)
{
if(price <= 0 || sl <= 0 || lot <= 0) return;
MqlTick tick; SymbolInfoTick(_Symbol, tick);
double min_dist = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
if(MathAbs(price - tick.ask) < min_dist) return; // 距离不足
trade.BuyLimit(lot, price, _Symbol, sl, tp);
if(trade.ResultRetcode() != TRADE_RETCODE_DONE)
Print("Err: ", trade.ResultRetcodeDescription());
}
对社区资源与信号服务的看法
Francisco把MQL5社区视为学习语言的第一信息源:读文章、看代码库(Code Base)、查官方文档。他认为新推出的信号(Signals)服务很有前景,可让普通用户跟单,而不必自己写EA。这对中文用户同样适用——若暂无力自研,可先评估信号提供者的历史与回撤。
给算法交易新人的建议很朴素:EA不是印钞机,需持续迭代;从文档起步,先写个基于均线交叉的简单EA。这能让人理解OnTick、订单、止损闭环,再去碰多货币与事件模型,才不会在基础语法上耗费锦标赛时间。
访谈带来的实操启示
总结这位选手的路径:明确自身优势在编程而非执行;用MQL5事件模型解决多货币动态手数;放弃指标,用价格结构+挂单;D1周期适配短赛程;前向测试抗过拟合;严格对照交易规则写单。对中文交易者,不必照搬策略,但‘用机器隔离情绪’‘用事件管资金’‘用文档查坑’三条可直接迁移到自己的EA开发流程中。
- 用OnTrade动态调控多货币挂单体积,防保证金不足
- 回测后必做前向测试,隔离样本外数据验证
- 发送订单后检查Retcode,对照SYMBOL_TRADE_STOPS_LEVEL等规则
- 从简单均线EA入门,再演进到多货币与复杂逻辑