Table of Contents
MQL5 Expert Advisor 开发第 1 部分:构建并测试安全骨架
第 1 部分有意把目标定得很小:创建一个真正的 MQL5 Expert Advisor,完成编译,然后在完全不下单的情况下通过 MetaTrader 5 Strategy Tester 运行。把资金或交易逻辑带进来之前,先确认工具链正常,并理解OnInit()、OnTick()和OnDeinit()。
本文 2019 年的旧版本在 MQL5 标题下混用了 MetaTrader 4 下载链接、MQL4 Wizard 和 MT4 截图。这次不再使用那些图片。它们是历史 MT4 界面,并不能准确说明当前 MQL5 工作流;而且 MetaTrader 5 的界面布局也可能随版本有所变化。
这是一篇软件开发教程,不是在声称 Expert Advisor 可以盈利。本练习中请保持自动交易关闭,只使用 Strategy Tester 和模拟账户。在策略、风险上限、故障行为和运行流程得到独立验证之前,后续实验也不要移到真实账户。
MetaTrader 5、MQL5 与文件类型
本系列始终使用 MetaTrader 5 工具链:
- MetaTrader 5是交易终端,其中包含 Strategy Tester。
- MetaEditor是终端自带的编辑器和编译器。
- MQL5是本文 Expert Advisor 使用的语言。
- 可编辑的源码文件以
.mq5结尾;编译成功后,会在同一个程序文件夹生成.ex5可执行文件。
MetaTrader 4 使用 MQL4 和.mq4/.ex4文件。某些概念看起来相似,但 MT4 代码和截图不能直接当作 MQL5 教程使用。
请从MetaQuotes 官方下载页获取 MetaTrader 5,或使用你已经信任的机构提供的安装包。本文不需要券商推广、合作伙伴链接、真实账户、入金或付费服务。
创建 Expert Advisor 模板
在 MetaTrader 5 中按F4打开 MetaEditor。也可以在终端 Navigator 的Expert Advisors区域选择Create in MetaEditor。
在 MetaEditor 中:
- 选择File > New。
- 选择Expert Advisor (template),不要选择Expert Advisor (generate)。
- 命名为
Part1ObserverEA,并保存在MQL5/Experts下。 - Author 和 Link 是可选项;不要填写账户信息或凭据。
- 标准 EA 模板已经包含
OnInit、OnDeinit和OnTick。第 1 部分不需要额外事件处理器。
官方MQL5 Wizard 文档说明,模板会放在MQL5/Experts下,并包含三个主要事件处理器骨架。如果 MetaEditor 打开的是MQL4/Experts路径,或生成.mq4文件,请立刻停下:当前打开了错误的平台/编辑器实例。
把模板替换为不下单的观察 EA
使用下面的完整骨架:
#property copyright "Lachlan Chen"
#property version "1.00"
#property description "Part 1 observer: logs lifecycle events and never trades."
input bool InpLogFirstTicks = true;
input uint InpTicksToLog = 3;
ulong g_ticks_seen = 0;
int OnInit()
{
PrintFormat("Part1ObserverEA initialized: symbol=%s period=%s",
_Symbol,
EnumToString(_Period));
return(INIT_SUCCEEDED);
}
void OnTick()
{
g_ticks_seen++;
if(InpLogFirstTicks && g_ticks_seen <= InpTicksToLog)
{
PrintFormat("tick=%I64u symbol=%s server_time=%s",
g_ticks_seen,
_Symbol,
TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS));
}
}
void OnDeinit(const int reason)
{
PrintFormat("Part1ObserverEA stopped: reason=%d ticks_seen=%I64u",
reason,
g_ticks_seen);
}
这个程序只做三件事:
OnInit()记录测试品种和周期,并返回INIT_SUCCEEDED。OnTick()统计收到的 tick 事件,并按需记录最初几次。OnDeinit()记录停止原因和处理过的 tick 事件数量。
代码中没有CTrade对象、OrderSend()、持仓操作或交易请求。修改InpTicksToLog只会改变 Journal 消息数量,不可能启用交易。
MetaQuotes 推荐使用返回整数的`OnInit()`,因为这种形式可以报告初始化失败。`OnTick()`会在图表/测试品种收到新 tick 时调用。关闭自动交易会阻止 EA 发送交易请求,但不会让 EA 停止接收 tick 事件,这一点很适合本文这种无害观察程序。
编译并阅读结果
保存文件并按F7,或点击Compile。MetaEditor 应在.mq5源码旁生成Part1ObserverEA.ex5。不要因为点击了工具栏就假设成功,请检查Errors标签。
无错误编译只能说明该 MetaEditor 版本接受了语言语法和引用函数,不能证明以后加入的交易规则正确、安全或有利可图。每次修改源码后都要重新编译,否则终端可能继续运行旧的.ex5文件。
在 Strategy Tester 中运行骨架
回到 MetaTrader 5,打开View > Strategy Tester。当前 Tester 有多种任务布局,不同版本的文字和面板位置可能略有差异。
第一次运行时:
- 选择单次 Expert Advisor 测试,并指定
Part1ObserverEA。 - 选择具备历史数据的品种、周期和一段较短的过去日期范围。
- 关闭 Optimization。
- 使用本地测试代理。远程/云端代理可能不记录
Print()输出,不适合本次日志观察练习。 - 启动测试,然后查看Journal。
按照默认输入,Journal 应显示一条初始化消息、最多三条 tick 消息和一条结束消息。由于这份源码完全没有交易请求,测试结果中不应出现成交。
这里的余额线保持水平,只代表“没有交易”,不代表策略结果、基准收益或低风险。如果 Tester 出现成交,请确认选中的 EA 确实是Part1ObserverEA,并确认已编译的.ex5对应上面的源码。
官方 Strategy Tester 指南介绍了品种、周期、日期、tick 生成、执行延迟、可视化模式和 Journal 设置。以后比较测试结果时,请记录这些设置。
添加订单之前,先设计验证路径
第 2 部分也许会加入信号或订单路径,但能够编译的代码离真实交易还非常远。请按阶段推进:
- 确定性的单元检查: 用少量已知输入验证计算。
- 历史回测: 选择适合的 tick 模式,确认订单严格遵守书面规则。
- 未见过的前向区间: 不让较晚的数据参与参数选择,单独比较结果。
- 成本和执行压力: 纳入点差、手续费、适用时的隔夜费,以及非零执行延迟或滑点假设。
- 模拟前向测试: 不使用真实资金,在当前市场条件下观察 EA。
- 故障测试: 模拟数据断开、订单拒绝和终端重启,确认状态不明确时不会产生新交易。
- 独立复核: 检查仓位大小、最大风险暴露、止损行为、日志和手动停止开关。
MetaTrader 5 在优化时支持独立的前向区间,目的就是减少参数对单一历史区间的过拟合;它还提供执行延迟模拟和高级手续费设置。请实际使用这些功能。理想化的零成本测试不能作为可部署的结果估计。
回测仍然会受到券商品种规格与历史数据、Bid/Ask 行为、tick 模型、账户类型、点差、手续费、隔夜费、延迟假设和所选日期的影响。一条平滑的余额曲线可能来自过拟合,并不能承诺未来表现。
如果以后加入机器学习
机器学习会带来另一种意外偷看未来的路径。拟合预处理、特征选择或模型参数之前,应先按时间拆分数据。如果根据未来测试区间选择缩放器、阈值、特征列表或超参数,即使最终模型没有收到一个名为“future price”的字段,也已经发生信息泄漏。
训练、验证和最终前向区间必须保持时间顺序。转换步骤只能在训练区间上拟合,保留一段真正从未使用的最终区间,并考虑每项特征在真实环境中究竟何时可用。scikit-learn 官方文档提供了防止数据泄漏和时间顺序交叉验证的简明说明。
机器学习分数不是交易结果。把预测转换为订单后,还会引入换手、点差、手续费、滑点、仓位大小和执行失败。考虑任何真实使用之前,必须在 Strategy Tester 和模拟账户中评估从决策到执行的完整路径。
第 1 部分完成了什么
现在你已经拥有真正的 MQL5 .mq5源码、MetaEditor 生成的.ex5,以及一次不交易但完整经过 EA 生命周期的 Strategy Tester 运行。这才是正确基础:先证明自己理解环境和事件流程,再逐个增加小而可测试的行为。
一手资料
核对日期:2026 年 9 月 1 日。
