从基础到中级:IF ELSE·进阶篇
条件恒真与恒假的三种写法
在 MQL5 脚本里,if 分支的判定条件并不总按直觉走。下面三段 OnStart 演示了三种让代码必然或绝不进入分支的写法,直接丢进 MT5 的脚本文件就能跑出日志。 第一段用 if(false),第 9 行的 Print 永远不会执行,而第 6、11 行的两句照常打印。日志里你只会看到两次 'It will be executed anyway...',验证分支被跳过。 第二段把 false 取反写成 if(~false),按位非让条件变成非零值,分支必然进入,第 9 行 'True condition...' 会出现在两次常规打印之间。 第三段用 if(false | true),按位或只要有一侧为真整体即真,日志会输出 'A very crazy condition always true ...'。外汇与贵金属杠杆高,这类恒真/恒假陷阱在 EA 风控判断里可能让止损逻辑被静默绕过,实盘前务必逐行核对条件表达式。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose" class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart(class="type">void) { Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (false) Print("True condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose" class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart(class="type">void) { Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (~false) Print("True condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose" class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart(class="type">void) { Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (false | true) Print("A very crazy condition always true ..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } class=class="str">"cmt">//+------------------------------------------------------------------+
「ELSE 必须配对,别想单独跑」
不少自学 MQL5 的人会犯一个低级错:把 ELSE 当成能独立存在的语句。实际上 ELSE 只是「否则」分支,必须挂在另一个语句后面。很多人以为它只认 IF,但在 SQL 里 ELSE 是跟 CASE 绑定的——语言设计不同,细节就不同,别拿一门语言的直觉硬套另一门。 在 MQL5 里,只要 ELSE 和 IF 成对,IF 条件为假时才走 ELSE 块。逻辑本身不复杂,但真写起来容易漏掉配对,尤其嵌套多层时。 下面这段代码把 IF-ELSE 和引用传参揉在一起。第 6 行定义 int info = 10;第 10 行 if(info) 为真(非零即真),调用 Procedure 把 info 改成 0 并打印两次;第 12 行 else 此时不执行。第 15 行再次 if(info),但 info 已被改成 0,条件为假,于是第 17 行 else 输出 False condition。第 8 行和第 20 行是无论分支如何都会打印的锚点。 [CODE]
- //+------------------------------------------------------------------+
- #property copyright "Daniel Jose"
- //+------------------------------------------------------------------+
- void OnStart(void)
- {
- int info = 10;
07.
- Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #1 => ", info);
09.
- if (info)
- Procedure(info);
- else
- Print("Variable info is equal to zero...");
14.
- if (info)
- Print("True condition...");
- else
- Print("False condition...");
19.
- Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #2 => ", info);
- }
- //+------------------------------------------------------------------+
- void Procedure(int & arg1)
- {
- Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
- arg1 = 0;
- Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
- }
- //+------------------------------------------------------------------+
[/CODE] 逐行拆解:06 声明变量并赋 10;08 打印首条必执行信息;10 判断 info 非零进入 if;11 调用 Procedure 传引用;12-13 是配对 else,本次跳过;15 二次判断 info 此时已为 0;16 与 17-18 分别对应真假分支,本次走 else;20 打印末条必执行信息;23-28 的 Procedure 接收引用,25 打印传入值,26 改为 0,27 打印改后值。 开 MT5 把第 6 行改成 int info = 0 跑一遍,你会看到第 11 行不执行、第 13 行输出「Variable info is equal to zero...」,而第 15 行依旧走 else。外汇与贵金属杠杆高、风险大,这类逻辑练习请在策略测试器用离线数据验证,别直接挂实盘。
class="num">01. class=class="str">"cmt">//+------------------------------------------------------------------+ class="num">02. class="macro">#class="kw">property copyright "Daniel Jose" class="num">03. class=class="str">"cmt">//+------------------------------------------------------------------+ class="num">04. class="type">void OnStart(class="type">void) class="num">05. { class="num">06. class="type">int info = class="num">10; class="num">07. class="num">08. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #class="num">1 => ", info); class="num">09. class="num">10. if (info) class="num">11. Procedure(info); class="num">12. else class="num">13. Print("Variable info is equal to zero..."); class="num">14. class="num">15. if (info) class="num">16. Print("True condition..."); class="num">17. else class="num">18. Print("False condition..."); class="num">19. class="num">20. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #class="num">2 => ", info); class="num">21. } class="num">22. class=class="str">"cmt">//+------------------------------------------------------------------+ class="num">23. class="type">void Procedure(class="type">int & arg1) class="num">24. { class="num">25. Print(__FUNCTION__, " ", __LINE__, " #class="num">1 => ", arg1); class="num">26. arg1 = class="num">0; class="num">27. Print(__FUNCTION__, " ", __LINE__, " #class="num">1 => ", arg1); class="num">28. } class="num">29. class=class="str">"cmt">//+------------------------------------------------------------------+
◍ ELSE 挂错 IF 是 MQL5 里的隐形坑
纯嵌套 IF 不算麻烦,MQL5 里真正容易翻车的是 IF 和 ELSE 混排时的归属歧义。缩进在 MQL5 中只是给人看的,编译器根本不认,第 18 行的 ELSE 永远贴着最近的那个 IF(第 16 行),而不是你视觉上以为的第 14 行。 下面这段就是典型陷阱:c1=10、c2=0、c3=-6、c4=3,四个 IF 串起来,最后甩一个 ELSE。你以为 ELSE 对应最外层 c1 的判断,实际它只接 c4 那个 IF。跑起来若 c1 为真但 c4 为假,就会掉进 ELSE 子程序,逻辑完全偏掉。 [CODE] //+------------------------------------------------------------------+ #property copyright "Daniel Jose" //+------------------------------------------------------------------+ void OnStart(void) { char c1 = 10, c2 = 0, c3 = -6, c4 = 3; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (c1) if (c2) if (c3) if (c4) Print("True condition..."); else Print("False condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } //+------------------------------------------------------------------+ [/CODE] 逐行拆解:第 06–09 行定义四个 char 变量,非零即真;第 13 行 if(c1) 进内层;第 14–16 行继续嵌套判断;第 17 行才是那个 else,它编译时绑定第 16 行 if(c4),跟 c1/c2/c3 无直接隶属。 最稳的修法是显式加花括号把子块框死,让编译器 unambiguous:把第 14 行 IF 连同里面所有内容包进一个 block,ELSE 自然就挂回外层了。另一种写法靠连续 else if 硬链,结果等价但可读性差,教学里能看懂就行,实盘策略代码别这么绕。 开 MT5 把上面代码贴进脚本跑一遍,故意让 c4=0,看输出是不是进了 else——这一下就能确认你当前环境里 ELSE 的绑定规则,比看文档直观。
class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose" class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart(class="type">void) { class="type">char c1 = class="num">10, c2 = class="num">0, c3 = -class="num">6, c4 = class="num">3; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (c1) if (c2) if (c3) if (c4) Print("True condition..."); else Print("False condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } class=class="str">"cmt">//+------------------------------------------------------------------+
嵌套 if 与逻辑与的等价陷阱
把多个条件用 && 串成一行,和把它们写成层层缩进的 if 嵌套,在 MQL5 里控制流走向并不总是一回事,尤其当某个中间变量为 0 时。上面第一段用 if ((c1) && (c2) && (c3) && (c4)) 判断,c2 赋值为 0,整个布尔表达式短路,不会打印 "True condition...",但函数末尾那行 Print 照常执行。
第二段代码把四个变量拆成四级 if 嵌套:c1=10 为真进入,c2=0 为假,直接命中 else 分支打印 "False condition..."。这里要注意,else 只绑定最内层的 if (c2),而不是后面某个条件,这种缩进若没大括号极易看错归属。
第三段在 c2 为假处补了 {} 把后续 c3、c4 的判断关在里面,于是 c2=0 时整块子树被跳过,不会再向下求值。实盘策略里若用多个指标阈值做过滤,建议显式加 {} 而非依赖缩进,MT5 回测时少踩这类静默逻辑坑——外汇与贵金属波动剧烈,错误条件分支可能导致信号频率异常偏高。
开 MT5 新建脚本粘入下方代码,改 c2 为 1 或 -1,对比三段输出的行号与打印内容,能直观看到短路与嵌套的差异。
class="type">void OnStart(class="type">void) { class="type">char c1 = class="num">10, c2 = class="num">0, c3 = -class="num">6, c4 = class="num">3; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if ((c1) && (c2) && (c3) && (c4)) Print("True condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } class="type">void OnStart(class="type">void) { class="type">char c1 = class="num">10, c2 = class="num">0, c3 = -class="num">6, c4 = class="num">3; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (c1) if (c2) if (c3) if (c4) Print("True condition..."); else Print("False condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } class="type">void OnStart(class="type">void) { class="type">char c1 = class="num">10, c2 = class="num">0, c3 = -class="num">6, c4 = class="num">3; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (c1) if (c2) { if (c3) if (c4) Print("True condition..."); } Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); }
「嵌套 if 里空 else 的坑」
上面这段 MT5 脚本演示了 char 变量在条件判断里的隐式转换。c1=10、c2=0、c3=-6、c4=3,四个变量连续嵌套 if,只有 c1 非零时才会进入第二层;c2 为 0 直接走 else 分支打印 "False condition..."。
注意第 18、19 行的 else; 是空语句。很多人以为不写 else 就完了,但在多层嵌套里留个空 else 能明确语法归属,避免后面维护时把层次看错。
无论条件怎么走,第 11 行和第 23 行的 Print(__FUNCTION__, __LINE__, ...) 都会执行——这是验证代码确实跑过 OnStart 的笨办法。开 MT5 新建脚本粘进去,终端里能看到两次 "It will be executed anyway..." 以及一次 "False condition...",说明 c2=0 把链切断了。
外汇和贵金属行情跳动快,这类控制流逻辑若写错层级,实盘里的订单触发条件可能完全偏离预期,务必在策略测试器里先跑通再上真金白银。
class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose" class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart(class="type">void) { class="type">char c1 = class="num">10, c2 = class="num">0, c3 = -class="num">6, c4 = class="num">3; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); if (c1) if (c2) if (c3) if (c4) Print("True condition..."); else; else; else Print("False condition..."); Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } class=class="str">"cmt">//+------------------------------------------------------------------+
◍ 写出自己的 MQL5 控制流风格
控制流语句刚接触时容易绕晕,但耐心练下去,能为同一问题找出少数人才想得到的写法。已解决的代码不代表最优,同一逻辑常存在更省资源的解法,学会越过第一眼能看到的方案才算入门。 附件 ZIP 仅 2.64 KB,未打包全文代码,但读完你完全能手动补全并改写。除了练手,更重要的是形成自己的编程语气——同样功能,不同人写的嵌套与缩进差异很大。 让代码能被别人读懂,也让你自己改起来快,这一步比抄完示例更有长期价值。外汇与贵金属 EA 编写属高风险活动,实盘前务必在 MT5 策略测试器充分验证。