「MQL5 操作符的入门落点」
「MQL5 操作符的入门落点」
MQL5 里操作符是写 EA 和指标的骨架,从赋值、算术到关系与逻辑判断,都靠它们把行情数据转成可执行的交易动作。官方示例文档在 2025 年 4 月 23 日更新了一版基础到中级的操作符讲解,站内阅读量到了 607,说明这块仍是多数刚碰 MT5 编程的人卡顿的地方。 想在 MT5 里验证操作符行为,最直接的是开 MetaEditor 写几行打印到日志。比如用三元操作符做多空条件切换,比写一堆 if-else 更短平快,回测时也更不容易漏分支。 外汇和贵金属杠杆高、滑点随机,用操作符拼出的信号逻辑只是工具,实盘里信号触发概率和止损被扫的概率都要自己跑历史数据看,别默认它永远有效。
◍ 为什么操作符是数据类型的先修课
这套材料只用于搞懂概念本身,别把它当成能直接上线的交易工具。外汇和贵金属市场高杠杆、高波动,拿教学代码真去跑实盘,爆仓概率极高。 上一讲我们聊了预定义变量和一种把函数当解释对象看的思路,但所有内容都绕不开一个新手的共性卡点:MQL5 里数据类型太多,不先理清它们怎么被操作,后面全乱。 很多人觉得操作符太基础不值得单讲,但统计社区里的报错帖,相当比例的根源就是对赋值、算术这类符号的误用。先吃透操作符,才能正确解释 int、double、string 之间的差异。
整数相除为何丢掉小数
在 MT5 里写 Print(5 / 2),终端打印出来的是 2 而不是 2.5。这不是电脑算错,而是 MQL5 作为强类型语言,两个整数字面量相除时,编译器强制结果也为整数类型,小数部分直接截断。
很多从 Python 这类动态语言切过来的交易者会本能觉得 5/2 就该是 2.5。但 MQL5 和 C++ 一样,数据类型决定了运算结果的形态。下面这段代码就是上面现象的最小复现:
[CODE]
- //+------------------------------------------------------------------+
- #property copyright "Daniel Jose"
- //+------------------------------------------------------------------+
- void OnStart(void)
- {
- Print(5 / 2);
- }
- //+------------------------------------------------------------------+
[/CODE]
逐行拆解:第 4 行定义脚本入口 OnStart;第 6 行是两个 int 常量 5 和 2 做除法,因操作数皆为整数,MQL5 执行整数除法得 2,再交由 Print 输出;终端显示 2。
要拿到 2.5,必须做类型转换(typecasting)。把第 6 行改成 Print((double)(5 / 2)) 仍不对——因为括号里先做了整数除法已经丢掉小数。正确写法是让操作数之一先成浮点,例如 Print((double)5 / 2)。文档中的隐式转换规则倾向复杂类型(如 double),但显式转换更可控。
[CODE]
- //+------------------------------------------------------------------+
- #property copyright "Daniel Jose"
- //+------------------------------------------------------------------+
- void OnStart(void)
- {
- Print((double)(5 / 2));
- }
- //+------------------------------------------------------------------+
[/CODE] 逐行拆解:第 6 行先算 5/2 得整数 2,再转成 double 输出 2.0——这暴露了转换时机的重要性。外汇与贵金属 EA 开发中,这类整数截断可能导致点差、手数计算偏差,属高风险细节,开 MT5 跑一下两段代码就能确认差异。
class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose" class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnStart(class="type">void) { Print(class="num">5 / class="num">2); } 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((class="type">class="kw">double)(class="num">5 / class="num">2)); } class=class="str">"cmt">//+------------------------------------------------------------------+
「整数溢出藏在 MSB 里」
整数类型在内存里就是一串位。8 位的 char 若按无符号解读,范围是 0~255;若按有符号解读,最高位(MSB)当符号位,正数只能到 127,零占了 MSB 为 0 且其余位全 0 的位置,于是负数下限被推到 -128,实际范围是 -128~127。 许多交易者写 EA 时顺手用 char 存计数或价差刻度,却忘了它只有 8 位。下面这段代码把 100 和 40 相加,日常数学里是 140,但 char 装不下,MSB 被进位点亮,Print 出来是 -116。 [CODE]
- //+------------------------------------------------------------------+
- #property copyright "Daniel Jose"
- //+------------------------------------------------------------------+
- void OnStart(void)
- {
- char value1 = 100,
- value2 = 40,
- Result;
09.
- Result = value1 + value2;
- Print(value1, " + ", value2, " = ", Result);
- }
- //+------------------------------------------------------------------+
[/CODE] 逐行拆解:06~08 行声明三个 char 变量并赋初值;10 行做加法,结果写回 char 类型的 Result;11 行向 MT5 终端打印。100 的二进制是 01100100,40 是 00101000,相加得 10001100,MSB 为 1 被解读成负数,对应十进制正是 -116。 外汇与贵金属杠杆高、跳空频繁,这类静默溢出若出现在仓位计算循环里,可能让条件判断反向,概率上引发异常下单。开 MT5 把上面代码贴进脚本跑一遍,亲眼看看终端输出的 -116,比看任何说明都直接。 更大的类型如 32 位 int 只是把 MSB 推到 bit 31,上限变成约 21 亿,但到了边界照样翻折。字符串编码从 8 位 ASCII 扩到 16 位也只是把范围拉到 65536,本质还是 MSB 移位。理解位宽与符号位,才能在调参时选对类型,而不是等爆仓才回头查。
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 value1 = class="num">100, value2 = class="num">40, Result; Result = value1 + value2; Print(value1, " + ", value2, " = ", Result); } class=class="str">"cmt">//+------------------------------------------------------------------+
◍ 逻辑操作符
逻辑操作符在位级别进行操作。虽然它们有时可以应用于字节或整个位集,但它们主要是为在位级别上运行而设计的。起初,这可能看起来有点令人困惑,但随着时间的推移,你会发现这是有道理的。与用于执行计算的算术操作符不同,逻辑操作符用于评估条件。通常,逻辑运算测试值是否满足特定条件。由于这些操作符在与控制结构一起使用时最有效,因此我们在这里只提供一个简要的概述,以便您为即将到来的主题做好准备。 尽管逻辑操作符在与条件语句一起使用时更有意义,但它们也可以用于执行小规模操作。事实上,每个 CPU 操作实际上都比算术更合乎逻辑。尽管算术逻辑单元(ALU)以算术和逻辑命名,但逻辑运算是 CPU 功能的基础。 就逻辑运算符而言,我们主要有 AND(与)、OR(或)、NOT(非),在某些(但不是全部)编程语言中还有 XOR(异或)。除此之外,我们还有右移和左移操作。这些简单的操作是所有计算逻辑的基础。事实上,任何事物都可以从这些基本操作中构建出来。这正是 ALU(CPU 的“大脑”)运行的原理。 此时,您可能正在查看 MQL5 文档(或其他编程语言的参考资料)并想知道:“但还有更多的逻辑运算符,例如大于(>)、小于(<)等。为什么它们没有包括在这里?”好问题,亲爱的读者。为了方便起见,一些语言提供了额外的逻辑运算符或比较函数。然而,在硬件层面上,这些操作比编程语言中呈现的方式简单得多。需要明确的是,这并不是对这些实现的批评。事实上,它们使编程变得更加容易。例如,比较两个值的最简单方法是减法。然而,另一种方法涉及应用逐位 XOR 运算。如果所有位都匹配,则结果为零。如果任何位不同,则值不相等。执行减法时,我们可以分析 MSB 以确定结果是零(等于)、负(小于)还是正(大于)。这使我们能够在没有显式比较运算符的情况下建立数值关系。 为了明确这个概念,让我们来看一个简单的例子,它确定一个值是大于、小于还是等于另一个值。为此,我们将使用以下代码片段: 代码 04 这里我们有一个简单而典型的数值分析系统。执行此代码时,您将在终端中看到以下结果: 图 06 现在,请注意前面提到的关于确定一个值是否大于、小于或等于另一个值的内容。为了让事情变得更有趣,我们使用一个 16 位有符号值,它允许我们表示 65536 个不同的值。但是,由于它是一个有符号值,意味着它既可以保存负数也可以保存正数,所以范围将从 -32768 到 32767 变化。如果我们坚持分析 8 位范围内的值,我们就不会遇到确定一个值是否大于、小于或等于另一个值的问题。但是使用 16 位值,我们可以表示更广的范围,从 -255 到 255,这非常好。话虽如此,还是有方法可以使其变得更好。但我们暂时不会深入探讨这个问题,因为有一些概念需要首先解释。不过,代码 04 还是相当迷人和有趣的。 那么,让我们来分解一下这里发生的事情。由于 value1 明显小于 value2,因此用一个值减去另一个值将得到一个负值,从而证实第一个值确实较小。这发生在代码 04 的第 9 行。另一方面,当我们从 value2 中减去 value1 时,如第 10 行所示,结果为正,表示 value2 大于 value1。最后,在第 11 行,我们进行比较以检查值是否相等。由于结果为非零,我们可以明确地得出结论,这些值并不相同。 这个概念非常有趣,当你意识到 ALU 中没有减法运算时,它变得更加有趣。事实上,ALU 中执行的任何操作本质上都只是一个和,结合了一些逻辑运算。即使是加法操作,其核心也可以简化为逻辑操作。 然而,为了正确地演示这一点,我们需要使
记住这一条就够了
强类型语言里那些不起眼的细节,往往决定一段 MQL5 脚本会不会在实盘里静默出错。本文随附的 Anexo.zip(0.98 KB)里放了文中四个示例里的三个,剩下那个留给你自己照着文档补完。 把布尔逻辑啃透比追新函数更划算——它能在处理正负值分支时少写一半嵌套。MT5 里打开附件挨个改一行参数跑一遍,比只读不写记得牢。 外汇和贵金属杠杆高、滑点凶,任何代码逻辑都先在策略测试器用历史数据验证逻辑,再谈真金白银。