MQL5 EA 编码入门:从零搭建你自己的订单类(基础篇)
🛠️

MQL5 EA 编码入门:从零搭建你自己的订单类(基础篇)

(1/3)· 很多新手直接套用标准库,却看不懂订单背后发生了什么,本文带你拆开黑匣子

含代码示例偏理论 第 1/3 篇
想写自动 EA,却只会拖系统函数、不懂订单怎么发出去?从标准库切换到自己写的类,才算真正摸进 MQL5 的门。本篇是系列开篇,先带你把最底层的订单系统从空白文件建起来。

从零搭一个会自己跑的 EA 骨架

在 MT5 里写 EA,第一步不是急着下单,而是把程序生命周期的三个钩子函数先立住:OnInit 初始化、OnTick 每笔报价触发、OnDeinit 退出清理。这三个函数是 MT5 终端调度 EA 的硬性入口,缺一个都可能让策略在实盘里行为异常。 MQL5 的 EA 模板默认就带这三个空函数,但很多人直接往 OnTick 里堆逻辑,忽略了 OnInit 里做句柄缓存——结果每跳都重新申请 iMA 句柄,CPU 占用和延迟都会悄悄恶化。 下面这段是最小可编译骨架,保留了核心结构、未加任何交易动作,你直接贴进 MetaEditor 就能编译通过并加载到图表观察日志输出。外汇与贵金属品种波动剧烈,实盘前务必先在策略测试器用历史数据跑通逻辑,高风险品种切勿直接挂真仓。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                      Expert.mq5 |
class=class="str">"cmt">//|                        Copyright class="num">2023, MetaQuotes Software Corp. |
class=class="str">"cmt">//|                                             [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property strict

class="type">int OnInit()
  {
   Print("EA initialized");
   class="kw">return(INIT_SUCCEEDED);
  }

class="type">void OnDeinit(class="kw">const class="type">int reason)
  {
   Print("EA deinitialized, reason=",reason);
  }

class="type">void OnTick()
  {
   class="kw">static class="type">int ticks=class="num">0;
   ticks++;
   if(ticks%class="num">1000==class="num">0) Print("Processed ticks: ",ticks);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

「从结构走向订单系统代码」

前一篇讲了自动 EA 的概念与骨架,但没碰一行代码。那一篇的定位是给零基础读者补环境认知:先搞清楚 MT5 里 EA 跑在什么上下文里,再谈写逻辑。 本篇直接进代码层。起点不是指标也不是风控,而是订单系统——任何 EA 在 MT5 里下单、撤单、查持仓,全得先把这个底层打通。外汇与贵金属保证金交易杠杆高,实盘前务必在策略测试器用历史数据验证逻辑。 下面这段是订单系统的最小骨架,后面所有交易动作都挂在它上面。

◍ 自己造一个发单函数库

MT5 标准库把订单系统封装得很顺手,但这次不打算让你继续当黑盒用户。我们要从零写一个自己的发单库,只保留搭建稳健订单系统真正需要的那部分功能,不堆砌标准库里那些花哨资源。 对刚碰 MQL5 的人先说在前头:后面会用到特定结构体,得自己啃才能跟住逻辑。我会把思路和概念拆到最直白,但如果你不花力气,最后只能看看我们造出来的东西,没法自己改写复用。 这个自建库的目标很具体——能在 MT5 里编译后直接发单、挂单、维护持仓,而不是调 CJA 那种现成接口。外汇和贵金属杠杆高,任何自建发单逻辑上线前都先用策略测试器跑历史tick验证。

从零搭一个订单管理类骨架

在 MT5 的 MetaEditor 里,右键 Include 文件夹选新建文件,就能得到一个空的 .mqh 头文件。很多人会直接用向导里的“新建类”模板,但那样生成的类自带预定义格式,不利于理解底层结构;手动从头写更能看清访问控制是怎么运作的。 类本质上是一种自定义数据类型,比 int、double、bool 这些基元类型能封装更多行为。程序调用方不需要知道类内部怎么实现,只要会用公开接口就行,这正是隔离风险、提升健壮性的关键。 类里用 private 和 public 保留字切分作用域:private 段里的变量和函数只能在类内部访问,外部改不了;public 段则全局可读写。如果完全不写这两个保留字,所有成员默认公开,等于废掉了类的封装保护。 建好 C_Orders 这个空类后,EA 主文件用 #include <Generic Auto Trader\C_Orders.mqh> 把它挂进来,编译器在预处理阶段就会把头文件内容合并进工程一起编译。下面这段代码就是刚建好的最小骨架和挂载方式,灰色注释行都可删。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class="macro">#class="kw">property link      ""
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| defines                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">// class="macro">#define MacrosHello   "Hello, world!"
class=class="str">"cmt">// class="macro">#define MacrosYear    class="num">2010
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| DLL imports                                                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">// class="macro">#class="kw">import "user32.dll"
class=class="str">"cmt">//   class="type">int      SendMessageA(class="type">int hWnd,class="type">int Msg,class="type">int wParam,class="type">int lParam);
class=class="str">"cmt">// class="macro">#class="kw">import "my_expert.dll"
class=class="str">"cmt">//   class="type">int      ExpertRecalculate(class="type">int wParam,class="type">int lParam);
class=class="str">"cmt">// class="macro">#class="kw">import
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EX5 imports                                                         |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">// class="macro">#class="kw">import "stdlib.ex5"
class=class="str">"cmt">//   class="type">class="kw">string ErrorDescription(class="type">int error_code);
class=class="str">"cmt">// class="macro">#class="kw">import
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class C_Orders
{
      class="kw">private :
      class="kw">public  :
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property link      "[MQL5官方文档]
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Generic Auto Trader\C_Orders.mqh>
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
{
      class="kw">return INIT_SUCCEEDED;
}

「空壳回调里藏着初始化顺序的坑」

上面这段 MQL5 骨架里,OnDeinit 和 OnTick 都是空实现,但 EA 加载到 MT5 图表时,这两段并非摆设。OnDeinit(const int reason) 在指标或 EA 被移除、图表周期切换、或终端重载时触发,reason 会带回退出的整数码,比如 REASON_REMOVE=1、REASON_RECOMPILE=2,不接参数就丢了现场上下文。 OnTick() 是每来一个报价就跑一次,空函数意味着你还没挂任何逻辑,但 MT5 仍会按 tick 频率调用它,在高频品种上会吃掉极少量 CPU。想验证就新建一个 EA,把这俩函数原样贴进去编译,用 Experts 日志看加载和卸载时的调用时机。 外汇与贵金属杠杆高、滑点跳空频繁,空壳 EA 虽不交易,但若后续往 OnTick 里塞重计算,可能因 tick 密度暴增拖垮终端,建议先在策略测试器用 2023 年 XAUUSD 的 M1 数据跑压力观察。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(class="kw">const class="type">int reason)
{
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
{
}
class=class="str">"cmt">//+------------------------------------------------------------------+
把重复劳动交给小布
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到 EA 信号与订单流异常提示,你专注把类写稳。

常见问题

标准库封装了细节,适合快速上手;但自己写类能看清挂单、成交、持仓维护的真实流程,后续改逻辑不会被黑匣子卡住。
可以,小布盯盘内置的 AIGC 会标注品种页里的信号与订单流异常,辅助你对照自写类的执行表现,但外汇贵金属高风险,最终决策仍在你。
直接建类会带预定义格式,本系列要求从头写,所以走 Include 新建空文件再填代码,避免被模板带着走。
能,篇里放缓了节奏,先讲结构和注释含义;跟不住就先读前一篇概念篇,再回来敲代码。