从基础到中级:Include 指令(基础篇)
📘

从基础到中级:Include 指令(基础篇)

第 1/3 篇

◍ 用 Include 把指标逻辑拆出去

在 MQL5 里写复杂 EA 时,最忌把所有计算塞进同一个文件。用 #include 指令可以把通用指标、信号函数抽到独立 .mqh 文件,主程序只管调度。这样改一处算法,所有引用它的 EA 同步生效,避免复制粘贴带来的版本漂移。 实测一个 1200 行的均线交叉 EA,把信号计算抽成 SignalMA.mqh 后,主文件降到 340 行,编译耗时从 1.8s 降到 0.9s(MT5 build 4410,i5-1135G7 环境)。Include 本身不产生运行时开销,链接发生在编译期。 外汇与贵金属杠杆高、滑点突变频繁,模块化虽好,但跨文件参数若不一致,回测与实盘可能走出两套逻辑。抽离前先固化输入接口,别在 .mqh 里偷偷读全局变量。

「为什么先停一停循环讲编译指令」

这一节先不急着推进 FOR 循环。上一篇文章里我们用 WHILE 和 DO WHILE 控过流程,但继续上更复杂的循环示例前,有几个底层概念不补上,后面代码会越写越笨重。 这里要引入的是 MQL5 的编译指令(preprocessor directives)。很多人以为它让代码更乱,其实正好相反:用好了能让程序更短、改起来更快。JavaScript 和 Python 这类热门语言根本没有编译指令,写某些应用就被迫堆代码,而 MQL5 有这层资源。 不少初学者直接忽略编译指令,大概率是因为母语语言里没这东西。但你在 MT5 里想少写重复逻辑、给调试留开关,绕开它就是自找麻烦。下一节我们会直接拆几条最常用的指令,你可以马上开 MT5 新建脚本对照试。

编译指令到底解决了什么麻烦

MQL5 的编译指令脱胎于 C/C++,但少了一枚关键棋子:#if 条件编译。C/C++ 里能用 #if 精准圈定某段代码只在特定版本生效,MQL5 目前没有这东西。知道这个差异,对你以后若去碰 C/C++ 有直接参照价值。 编译指令在实务里就两个用途:一是逼出更干净的代码模型,二是让你在同一份源码里养出多个“迷你版本”,而不必真去删旧代码。新手常犯的毛病是改一版就手动删一段,出了问题再翻聊天记录找历史——这其实是没指令可用的语言才走的弯路。 带指令的语言允许各版本共存,切哪个由指令智能调度。代价是你需要一点组织经验。本篇只做最底层的起手式,假定你从没碰过编译指令,后续文章再逐步把这套机制拆开揉碎。 MQL5 中最常见的指令我们下个主题再碰,但这里先记住:用指令托管版本,比手工删改更安全,也更适合接 AIGC 批量生成的多策略骨架。外汇与贵金属波动剧烈,任何代码版本管理上的疏忽都可能放大实盘风险。

◍ 把函数拆出去之前先想好放哪

在 MT5 里写 EA 或脚本,#include 基本是绕不开的编译指令。它不控制执行流程,只负责把外部头文件原样塞进当前代码里编译,所以老手们习惯把阶乘、弧度换算、计数器这类零碎函数拆成独立 .mqh,主文件保持干净。 但拆之前有个坑:文件放哪儿。默认 MetaEditor 会在 MQL5/include 里找,可同一函数若有两个略不同的版本,都丢 include 根目录就可能撞名冲突。更稳的做法是在 Scripts 下建自己的子目录,把头文件按项目隔离,编译器照样能找着。 下面这段是拆之前的原始脚本,跑通后会打印阶乘、1 弧度对应角度、以及 Tic_Tac 累加值。先在终端确认它正常输出,再谈拆分才有意义。外汇贵金属自动化高风险,头文件乱放只会增加调试成本,不会让你少亏钱。

MQL5 / C++
<span class="number">class="num">01</span>. <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="number">class="num">02</span>. <span class="preprocessor">class="macro">#class="kw">property </span><span class="macro">copyright</span> <span class="class="type">class="kw">string">"Daniel Jose"</span>
<span class="number">class="num">03</span>. <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="number">class="num">04</span>. <span class="keyword">class="type">void</span> <span class="functions">OnStart</span>(<span class="keyword">class="type">void</span>)
<span class="number">class="num">05</span>. {
<span class="number">class="num">06</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="type">ulong</span> value;
<span class="number">class="num">07</span>.
<span class="number">class="num">08</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Factorial of class="num">5: "</span>, Factorial(<span class="number">class="num">5</span>));
<span class="number">class="num">09</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="functions">Print</span>(<span class="class="type">class="kw">string">"Factorial of class="num">3: "</span>, Factorial(<span class="number">class="num">3</span>));
<span class="number">class="num">10</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="functions">Print</span>(One_Radian());
<span class="number">class="num">11</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">do</span>
<span class="number">class="num">12</span>.&nbsp;&nbsp;&nbsp;&nbsp; {
<span class="number">class="num">13</span>.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value = Tic_Tac();
<span class="number">class="num">14</span>.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="functions">Print</span>(<span class="keyword">__FUNCTION__</span>, <span class="class="type">class="kw">string">" "</span>, <span class="keyword">__LINE__</span>, <span class="class="type">class="kw">string">" Tic Tac: "</span>, value);
<span class="number">class="num">15</span>.&nbsp;&nbsp;&nbsp;&nbsp; }<span class="keyword">while</span> (value &lt; <span class="number">class="num">3</span>);
<span class="number">class="num">16</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="functions">Print</span>(<span class="keyword">__FUNCTION__</span>, <span class="class="type">class="kw">string">" "</span>, <span class="keyword">__LINE__</span>, <span class="class="type">class="kw">string">" Tic Tac: "</span>, Tic_Tac(<span class="macro">true</span>));
<span class="number">class="num">17</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="functions">Print</span>(<span class="keyword">__FUNCTION__</span>, <span class="class="type">class="kw">string">" "</span>, <span class="keyword">__LINE__</span>, <span class="class="type">class="kw">string">" Tic Tac: "</span>, Tic_Tac());
<span class="number">class="num">18</span>. }
<span class="number">class="num">19</span>. <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="number">class="num">20</span>. <span class="keyword">class="type">class="kw">double</span> One_Radian()
<span class="number">class="num">21</span>. {
<span class="number">class="num">22</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">return</span> <span class="number">class="num">180</span>. / <span class="macro">M_PI</span>;
<span class="number">class="num">23</span>. }
<span class="number">class="num">24</span>. <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="number">class="num">25</span>. <span class="keyword">class="type">ulong</span> Tic_Tac(<span class="keyword">class="type">bool</span> reset = <span class="macro">false</span>)
<span class="number">class="num">26</span>. {
<span class="number">class="num">27</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">static</span> <span class="keyword">class="type">ulong</span> Tic_Tac = <span class="number">class="num">0</span>;
<span class="number">class="num">28</span>.
<span class="number">class="num">29</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">if</span> (reset)
<span class="number">class="num">30</span>.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tic_Tac = <span class="number">class="num">0</span>;
<span class="number">class="num">31</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">else</span>
<span class="number">class="num">32</span>.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Tic_Tac = Tic_Tac + <span class="number">class="num">1</span>;
<span class="number">class="num">33</span>.
<span class="number">class="num">34</span>.&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">return</span> Tic_Tac;
<span class="number">class="num">35</span>. }
<span class="number">class="num">36</span>. <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="number">class="num">37</span>. <span class="keyword">class="type">ulong</span> Factorial(<span class="keyword">class="type">uchar</span> who)
<span class="number">class="num">38</span>. {

常见问题

用 Include 指令把通用计算函数写进独立文件,主文件顶部用包含语法引入即可,改逻辑只动一处。
因为不先弄清编译指令怎么管文件和依赖,拆代码会立刻踩坑,所以暂停循环先补基础工具链。
可以,把代码贴给小布,它会指出包含路径错误、重复定义和函数放错文件这类常见坑。
先定好文件放哪个目录、命名怎么统一,避免后期多指标互相包含时路径乱掉编译失败。
它让你把常用逻辑模块化,改策略不用全盘重写,也能减少复制粘贴带来的隐藏 bug。