学习为什么、以及如何设计算法交易系统·进阶篇
⚙️

学习为什么、以及如何设计算法交易系统·进阶篇

(2/3)· 从变量到条件语句,逐一拆解一段可跑的 MQL5 代码如何长成交易纪律的载体

案例拆解 第 2/3 篇
很多人把写 EA 想成高不可攀的工程,其实第一道门槛只是搞清楚变量和循环怎么用。若连 IF 判断都靠手写盯盘,情绪干扰迟早把策略拆得七零八落。本篇用均线交叉实例,把基础语法变成你自己的执行骨架。

◍ MT5 里变量怎么分作用域和类型

在 MT5 写 EA 或脚本时,变量就是一块带名字的内存,用来存能改的数据。按作用域分两种:在函数里声明的叫局部变量,只能在那个函数内读写;写在全部函数外面的叫全局变量,整个程序都能用,且只在函数首次执行前用常量初始化一次,表达式不行。 类型上,int 存整数;float 占 4 字节,范围约 1.175494351e-38 到 3.402823466e+38,double 占 8 字节,范围约 2.2250738585072014e-308 到 1.7976931348623158e+308,报价和手数计算多用 double;string 管文字,bool 只取 true / false。 下面这段能直接塞进 MT5 脚本跑,编译后无报错就会弹四个 Alert:整数、小数、字符串、布尔各一个。逐行看:myInteger 是 int 并赋 5;myDouble 是 double 赋 10.56;myString 存一段文字;myBoolean 设 true;后面四个 Alert 依次把这四个值弹窗输出。 另一个常见场景是把 A=10、B=10、C=10+5、var1=2.5、var2=4、result=2.5/4、message1="Hello Mohamed"、message2 拼上 A 的值都记下来,执行后警报会带出 C、result、message1、message2 四块内容。外汇和贵金属波动剧烈,用变量存价格相关数值时务必考虑滑点和重算时机,高风险。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Variables.mq5 |
class=class="str">"cmt">//| Copyright class="num">2022, MetaQuotes Ltd. |
class=class="str">"cmt">//| [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2022, MetaQuotes Ltd."
class="macro">#class="kw">property link "[MQL5官方文档]
class="macro">#class="kw">property version "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
   class="type">int myInteger = class="num">5;
   class="type">class="kw">double myDouble = class="num">10.56;
   class="type">class="kw">string myString = "My name is Mohamed";
   class="type">bool myBoolean = true;
   
   Alert(myInteger);
   Alert(myDouble);
   Alert(myString);
   Alert(myBoolean);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Variables class="num">2.mq5 |
class=class="str">"cmt">//| Copyright class="num">2022, MetaQuotes Ltd. |
class=class="str">"cmt">//| [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2022, MetaQuotes Ltd."
class="macro">#class="kw">property link "[MQL5官方文档]
class="macro">#class="kw">property version "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+

「用 OnStart 跑通基础变量与弹窗」

在 MT5 脚本里,所有执行逻辑都从 OnStart() 入口开始。上面这段直接声明了整型、双精度、字符串三类变量,并在函数体内完成一次除法与字符串拼接,最后用 Alert 把结果推到终端弹窗。 具体看:A=10、B=5 为整数,C 先声明后赋值 C=A+B 得到 15;var1=2.5 除以 var2=4 得到双精度结果 0.625,这类隐式浮点运算在风控计算里很容易因精度被误读。 字符串部分把 "Hello"、空格、"Mohamed" 拼成 message1,又把 "Value of A is: " 接上 string(A) 转出的字符得 message2。四句 Alert 依次弹出问候语、整数 15、0.625、带标签的文本,验证时你开 MT5 新建脚本粘入即可看到四次弹窗。 外汇与贵金属行情受杠杆与跳空影响,这类基础变量练习虽无直接交易风险,但真接实时报价时须警惕浮点误差放大导致的信号偏移。

MQL5 / C++
class="type">void OnStart()
  {
   class="type">int A = class="num">10;
   class="type">int B = class="num">5;
   class="type">int C;
   class="type">class="kw">double var1 = class="num">2.5;
   class="type">class="kw">double var2 = class="num">4;
   class="type">class="kw">double result = var1 / var2;

   class="type">class="kw">string greeting = "Hello";
   class="type">class="kw">string space = " ";
   class="type">class="kw">string name = "Mohamed";
   class="type">class="kw">string message1;
   class="type">class="kw">string message2;

   C = A + B;
   message1 = greeting + space + name;   
   message2 = "Value of A is: " + class="type">class="kw">string(A);

   Alert(message1);
   Alert(C);
   Alert(result);
   Alert(message2);
  }

MT5里的真假判断怎么写

布尔类型只干一件事:做逻辑比较,结果不是 true 就是 false。MQL5 里常用的关系符号有 ==(等于)、!=(不等于)、<(小于)、<=(小于等于)、>(大于)、>=(大于等于),它们直接决定条件分支走哪边。 拿最直观的例子看,表达式 4<5 在数学上成立,所以在脚本里赋值给 bool 变量后,Alert 弹出的内容会是 true。这类判断是 EA 过滤信号、开关仓位的前提,写错一个符号整个逻辑就反了。 下面这段演示代码可以在 MT5 新建脚本直接跑,验证布尔赋值和弹窗行为: //+------------------------------------------------------------------+

//Boolean Operations.mq5
//Copyright 2022, MetaQuotes Ltd.
//[MQL5官方文档]

//+------------------------------------------------------------------+ #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "[MQL5官方文档] #property version "1.00" //+------------------------------------------------------------------+

//Script program start function

//+------------------------------------------------------------------+ void OnStart() { bool result = 4 < 5; Alert (result); //true } //+------------------------------------------------------------------+ 逐行拆一下:#property 三行是脚本元数据,不影响逻辑;OnStart() 是脚本入口;bool result = 4 < 5; 把比较结果存进 result;Alert(result); 把 true 打到终端警报窗。外汇与贵金属交易杠杆高、风险大,用布尔条件触发下单前务必在策略测试器跑历史数据确认逻辑。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                     Boolean Operations.mq5 |
class=class="str">"cmt">//|                                   Copyright class="num">2022, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                         [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2022, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
   class="type">bool result = class="num">4 < class="num">5;
   Alert(result);      class=class="str">"cmt">//true
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 用 while 把重复动作交给计数器

while 循环由一个判断表达式和一段执行体构成:只要表达式为真,执行体就反复运行,直到表达式转为假才退出。它适合把『条件满足前一直做某件事』这类逻辑写得很干净,不用手动堆叠代码。 下面这段脚本把计数器从 1 起步,只要 counter < 3 就弹出当前值并加 1。跑完循环再弹一次收尾提示,最终警报顺序会是:脚本开始、1、2、循环已完成——共 4 条消息,循环体只进了 2 次。 在 MT5 里新建脚本粘入代码,拖到图表运行就能看到弹窗。若把判断里的 3 改成 10,警报会多输出到 9,这种改一个数就拉长行为的特性,正是循环比复制粘贴更有用的地方。外汇与贵金属波动剧烈,任何自动逻辑上线前都应在模拟盘验证。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                    While Loop.mq5 |
class=class="str">"cmt">//|                                   Copyright class="num">2022, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                             [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2022, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
   class=class="str">"cmt">//While(Loop)
   Alert("Start of script");
   
   class="type">int counter = class="num">1;
   
   while(counter < class="num">3) class=class="str">"cmt">//true?
     {
      Alert(counter);
      counter = counter + class="num">1;
     }
     
     Alert("Loop has finished");
  }

「for 循环的三段式与一次实跑」

MQL5 里的 for 循环由三个表达式加一个循环体构成:第一段做初始化,第二段每次判断终止条件,为真就继续跑循环体,为假就把控制权交出去;第三段在每轮迭代末尾做增量或计算。 拿上面这段代码来说,初始化把 i 置 0,条件卡在 i<5,每轮结束 i 自加 1。循环体只干一件事:弹一条 Alert("Hello")。 按这个逻辑,i 会依次取 0、1、2、3、4,共触发 5 次 Hello 弹窗;等到 i 累加到 5,条件 i<5 不成立,循环停下。你在 MT5 里新建脚本粘进去跑,终端会确切地报 5 次提醒,不会多也不会少。 外层 OnStart 是脚本入口,for 写在它里面就能直接验证。想改次数就把 i<5 里的 5 换成别的整数,比如 20 就会弹 20 条,外汇或贵金属 EA 里拿它扫 K 线序号时也是同一套机制,注意这类自动循环在实盘高频调用时存在执行延迟与滑点风险。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 For Loop.mq5 |
class=class="str">"cmt">//|                                         Copyright class="num">2022, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                                 [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2022, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
   for(class="type">int i=class="num">0; i<class="num">5 ; i++)
     {
      Alert("Hello");
     }
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

用 if-else 给报价分叉报警

条件分支在 EA 或脚本里就是做二选一。语法骨架是 if (条件) 操作1 else 操作2:条件为真只跑操作1,为假只跑操作2,两者不会同时执行。 下面这段脚本把阈值钉在 1.146600,先弹出现价,再判断 Bid 与阈值的上下关系给出方向提示。外汇与贵金属波动剧烈,这类报警只作参考,实际下单需结合风控,杠杆品种高风险。 代码逐行拆: // 版权与版本元信息,仅标识脚本属性 #property copyright "Copyright 2022, MetaQuotes Ltd." #property link "[MQL5官方文档] #property version "1.00" // 脚本入口函数 void OnStart() // 设定判断阈值 1.146600 double level = 1.146600; // 取当前品种买价并按规定小数位规范化 double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits); // 弹出当前买价报警 Alert("Bid Price = " + string(Bid)); // 若买价大于阈值 if(Bid > level) // 弹窗提示价格高于阈值倾向 BUY { Alert ("The price is above " + string(level) + " -> BUY"); } // 否则(买价不高于阈值) else // 弹窗提示价格低于阈值倾向 SELL { Alert ("The price is below " + string(level) + " -> SELL"); } } 把 level 改成你盯的黄金或欧美关键位,挂到 MT5 脚本里跑一次,就能在终端看到分叉报警的实际效果。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                If-else statement.mq5 |
class=class="str">"cmt">//|                                             Copyright class="num">2022, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                                     [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2022, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
   class="type">class="kw">double level = class="num">1.146600;
   class="type">class="kw">double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   Alert("Bid Price = " + class="type">class="kw">string(Bid));
   if(Bid > level)
   {
   Alert("The price is above " + class="type">class="kw">string(level) + " -> BUY");
   }
class=class="str">"cmt">// What if the condition is false and we need to take an action also here we can use else function instead of writing another if code
   else
    {
    Alert("The price is below " + class="type">class="kw">string(level) + " -> SELL");
    } 
   
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
把重复劳动交给小布
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到均线交叉与纪律执行的可视化,你专注决策而非守屏。

常见问题

类型不匹配通常在编译期就报错,比如把 double 赋给 int 会截断或提示转换,写前先定清类型能省掉大量调试时间。
While 多用于不确定次数的状态等待,For 更适合遍历 K 线数组计算指标,选错会让逻辑绕弯且吃 CPU。
用 && 与 || 组合快线慢线位置关系,能把多行 IF 压成一句条件,避免嵌套过深看花眼。
目前小布展示的是策略信号与纪律执行层,源码级回测需你本地编译,但信号异常它会在品种页标出供你比对。
注释在编译后被忽略,不影响执行效率,但过度注释会拖慢你后期维护时的阅读节奏,保持一行一意即可。