理解并有效地使用 MQL5 策略测试器(基础篇)
「先把 MT5 策略测试器跑通」
MQL5 自带的策略测试器(Strategy Tester)是验证任何 EA 或指标逻辑的第一现场,不是可选配件。打开 MT5 终端按 Ctrl+R,默认进入的是本地单线程回测,左上方选好品种、时间帧、测试周期与模型(每 tick / 控制点 / 开盘价)后才能点开始。 很多新手卡在「没数据」:MT5 需要先下载对应品种的历史数据。在「符号」窗口右键刷新或调工具—下载历史,否则回测长度会被截断到几根 K 线。一个可验证现象是,同一 EA 在 2020—2023 的 XAUUSD H1 上用每 tick 模型跑,若历史只覆盖 3 个月,夏普和回撤会严重失真,和全量数据结果偏差可能超过 40%。 测试器右侧的「输入参数」面板直接映射 EA 的 extern 变量,改手数、止损点数、均线周期不用重编译。外汇与贵金属杠杆高、滑点跳空频繁,回测盈利只代表历史概率,实盘可能显著偏离,务必用小资金先验证。
◍ 开测前必须啃下的三块硬骨头
在 MT5 里跑策略测试器之前,有几个前置项不理顺,回测结果基本不可信。很多开发者栽在自以为懂了,实际连编译期的报错都没处理干净,这种状态下跑出的权益曲线没有任何参考价值。 排第一的是错误处理。MQL5 程序里任何未捕获的异常都会让测试中断或给出假信号,所以要在关键调用处把错误码(如 GetLastError 返回的非零值)全部兜住。开发阶段犯糊涂太正常,但正式测试前必须清零这类低级坑。 排第二的是调试。MT5 的调试器支持断点逐行执行,能让你在 tick 级观察变量变化,比单纯看日志高效得多。排第三才是策略测试器本身——它比 MT4 的测试引擎多了真实毫秒级成交模拟和 Agent 分布式计算,功能深得多。 需要点明:本文预设读者已掌握 MQL5 语法并能独立写程序。若你还不会写 EA,直接读测试器相关内容收益极低,应先补语言基础。外汇与贵金属品种波动剧烈、杠杆风险高,任何回测优异都不代表实盘概率稳赢。
先认准错误出在哪一阶段
写 MQL5 程序最耗时的不是改 bug,而是不知道报错到底指什么、发生在哪一步。编译器能准确抛出信息,但人若看不懂,排错时间会成倍拉长。 按工作流切分,错误只落在三个节点:敲代码时的编译错误与警告、点运行后的运行时错误、以及程序发交易指令时由服务器回写的交易错误。先把这三类的边界记牢,再谈定位。 在 MT5 的 MQL5 IDE 里,所有报错集中显示在底部“工具箱”窗口。默认没看到的话,走三条路任一即可调出:菜单“查看”→“工具箱”、快捷键 Ctrl+T、或主工具栏的“工具箱”按钮。窗口一开,后续三类错误都有处可查。
「MT5编译器报错的七种高频形态」
写 MQL5 时编译器报错极其正常,但在「错误」选项卡清零前程序绝不会生成 ex5。下面这七类占了新手绝大多数编译失败:分号缺失、意外令牌、未声明标识符、括号不平衡、程序意外结束、全局范围表达式、参数计数错误。
分号预期最简单——行尾漏写 ; 或左括号缺失都会触发。原错误代码 int a=(2+1) 编译即失败,补成分号结尾 int a=(2+1); 后通过。
未声明标识符常出现在直接用变量再赋值:上面片段里 a=5; 之前没声明,编译器会精确指出变量 a 未声明;改成 int a=5; 即消错。
左括号不平衡与程序意外结束本质都是括号配对失败。例如 if (a=5 漏右括号,会同时报「左括号不平衡」和「意外的程序结束」,补 ) 后干净编译。
表达式不允许出现在全局范围,是因为在函数外写了语句。片段中 void OnStart(){ bool a=7; if(a=5) a=5; 缺收尾 } 导致后续代码掉到全局,补 } 归位即可。
错误的参数计数发生在函数实参个数和定义不符。自定义 myVal(int a,int b) 返回两数之和,调用只传 myVal(10) 必报错;传 myVal(10,20) 才匹配。
某些操作符预期则是运算符漏写,如 int a= 7 10; 中间无 +,编译报「某些运算符预期」,改为 int a= 7+10; 解决。
警告不等于错误:片段末行 int a; 声明未使用,仅出「未使用变量 a」警告,不影响出 ex5。双击错误行可跳转到对应代码行,从最上方错误修起往往连带消掉下游报错。
<span class="keyword">class="type">int</span> a=(<span class="number">class="num">2</span>+<span class="number">class="num">1</span>) <span class="keyword">class="type">int</span> a=(<span class="number">class="num">2</span>+<span class="number">class="num">1</span>); <span class="keyword">class="type">int</span> a=(<span class="number">class="num">2</span>+<span class="number">class="num">1</span>; <span class="keyword">class="type">int</span> a=(<span class="number">class="num">2</span>+<span class="number">class="num">1</span>); a=<span class="number">class="num">5</span>; <span class="keyword">class="type">int</span> a=<span class="number">class="num">5</span>; <span class="keyword">class="type">bool</span> a=<span class="number">class="num">7</span>; <span class="keyword">if</span> (a=<span class="number">class="num">5</span> a=<span class="number">class="num">5</span>; <span class="keyword">class="type">bool</span> a=<span class="number">class="num">7</span>; <span class="keyword">if</span> (a=<span class="number">class="num">5</span>) a=<span class="number">class="num">5</span>; <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="keyword">class="type">bool</span> a=<span class="number">class="num">7</span>; <span class="keyword">if</span> (a=<span class="number">class="num">5</span>) a=<span class="number">class="num">5</span>; <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="keyword">class="type">bool</span> a=<span class="number">class="num">7</span>; <span class="keyword">if</span> (a=<span class="number">class="num">5</span>) a=<span class="number">class="num">5</span>; } <span class="keyword">class="type">int</span> a=(<span class="number">class="num">7</span>+<span class="number">class="num">5</span>); <span class="keyword">if</span> (a<<span class="number">class="num">7</span>) a=<span class="number">class="num">7</span>; } <span class="keyword">class="type">int</span> a=(<span class="number">class="num">7</span>+<span class="number">class="num">5</span>); <span class="keyword">if</span> (a<<span class="number">class="num">7</span>) { a=<span class="number">class="num">7</span>; } <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="keyword">class="type">int</span> example=myVal(<span class="number">class="num">10</span>); } <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class="type">int</span> myVal(<span class="keyword">class="type">int</span> a, <span class="keyword">class="type">int</span> b) { <span class="keyword">class="kw">return</span> a+b; } <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>() { <span class="keyword">class="type">int</span> example=myVal(<span class="number">class="num">10</span>,<span class="number">class="num">20</span>); } <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class="type">int</span> myVal(<span class="keyword">class="type">int</span> a, <span class="keyword">class="type">int</span> b) { <span class="keyword">class="kw">return</span> a+b; } <span class="keyword">class="type">int</span> a= <span class="number">class="num">7</span> <span class="number">class="num">10</span>; <span class="keyword">class="type">int</span> a= <span class="number">class="num">7</span>+<span class="number">class="num">10</span>; <span class="keyword">class="type">int</span> a;