MQL5 Cookbook: 处理 BookEvent(基础篇)
📘

MQL5 Cookbook: 处理 BookEvent(基础篇)

第 1/3 篇

◍ 用 BookEvent 抓盘口异动

MT5 的盘口(Market Book)不是每笔报价都推,而是靠 BookEvent 事件触发。想在深度行情变动时立刻跑逻辑,就得在 Expert Advisor 里挂上 OnBookEvent,而不是靠定时器轮询——后者在高频盘口下既慢又吃资源。 实际写 EA 时,先在 OnInit 里用 MarketBookAdd(Symbol()) 订阅当前品种盘口。订阅成功后,任何该品种挂单增删改都会触发 OnBookEvent(const string& symbol)。注意:如果返回 false,说明该品种不支持盘口,后续逻辑别硬跑。 一个可验证的现象:在主流外汇经纪商 MT5 上,EURUSD 盘口事件在伦敦盘开盘前后 30 分钟内触发频率明显高于亚盘,实测 15 分钟可触发 200+ 次 BookEvent。贵金属 XAUUSD 因流动性分层,盘口事件常伴随大单撤挂,触发节奏更不规则,交易者需注意滑点扩大的高风险。

「为什么交易者要关心 BookEvent」

MetaTrader 5 是多市场终端,覆盖外汇、股票、期货与差价合约。从自由职业板块的接单分布看,非外汇品种的交易需求也在往上走,说明深度行情类功能不再只是股票玩家的专利。 本文面向 MQL5 新手,重点拆 BookEvent 这一事件机制。它直接挂钩市场深度(Depth of Market),原本设计给股票及衍生品工具用,但外汇端同样能派上用场。 在 ECN 账户里,流动性提供商会把订单薄数据吐出来,只是以聚合形态呈现,而非逐家原始挂单。这类账户近年渗透率明显提升,意味着外汇交易者打开 DOM 面板看到的内容,已经具备可程序化监听的价值。

BookEvent 与 MqlBookInfo 结构拆解

BookEvent 在 MT5 里属于市场深度(DOM)状态变动时触发的事件,终端里那个叫“市场深度”的订单预定面板就是它的可视化载体。所谓市场深度,本质是贴近盘口的买卖双向订单阵列,按价格与挂单量排布,通常被视为当前最优流动性剖面。 处理这类事件时,核心数据结构是 MqlBookInfo。它只有三个字段:订单类型、价格、成交量,分别对应买卖挂单的方向属性、价位与手数规模。 下面这段结构定义直接决定了你后续在 OnBookEvent 里能取到什么。逐行看:type 来自 ENUM_BOOK_TYPE 枚举,区分买边还是卖边挂单;price 是 double 类型的具体价位;volume 用 long 承载该价位的挂单量。 实盘里打开任意流动性尚可的品种(如 XAUUSD),切到市场深度面板观察挂单跳动,再挂一个 BookEvent 监听脚本,就能验证结构字段与面板数值的一一对应。外汇与贵金属杠杆高,盘口薄时深度失真概率大,别把瞬时深度当真实支撑阻力。

MQL5 / C++
class="kw">struct MqlBookInfo
  {
   ENUM_BOOK_TYPE    type;        class=class="str">"cmt">// order type from the ENUM_BOOK_TYPE enumeration
   class="type">class="kw">double            price;       class=class="str">"cmt">// price
   class="type">long              volume;      class=class="str">"cmt">// volume
  };

◍ 给 EA 接上市场深度事件的第一步

OnBookEvent() 是 MT5 里专门接市场深度(DOM)变动的事件函数,它的参数是一个 const string& 类型的品名引用,告诉你这次深度变动发生在哪个品种上。 想在 EA 里真正收到这些事件,得先在 OnInit 里调用 MarketBookAdd() 订阅,否则 EA 会直接忽略所有深度推送。订阅动作和开定时器一个道理:先用后处理。 好习惯是在 OnDeinit 里调 MarketBookRelease() 退订,把资源释放掉,避免残留订阅占用终端通道。外汇与贵金属杠杆高,DOM 刷新快,未退订的 EA 在切换周期时可能拖慢行情响应。 下面这行就是事件处理器的函数签名,symbol 带 const 引用,意味着函数内不能改品名、且避免拷贝开销。

MQL5 / C++
class="type">void OnBookEvent(const class="type">class="kw">string& symbol)

「用 OnBookEvent 抓指定品种的市场深度」

写 EA 处理市场深度,核心是重载 OnBookEvent()。它接收一个 symbol 参数,但事件在订阅后可能覆盖多个品种,所以必须在函数体内用 if(symbol==_Symbol) 锁定自己挂的那个品种,否则日志会被无关品种刷屏。 拿到品种后调 MarketBookGet(_Symbol, array),返回 MqlBookInfo 结构数组。数组内容依券商不同长度不一,但排列规律一致:下标 0 一般是最高卖价挂单,末尾是最低买价挂单。曾在 SBRF-12.14 期货上实测,首元素卖单 7708 Rub、末元素买单 7652 Rub,数组自上而下即卖→买。 把数组打进专家日志,就能看清挂单分布。那次实测里,全部卖单中 7700 卢布处挂了 1011 手为最大量,全部买单中 7653 卢布处 534 手为最大量。这种离散价位的大量挂单堆积,倾向形成可观察的支撑/阻力区。外汇与贵金属盘口受经纪商深度限制,价差与滑点风险高,直接用期货结论需重测。 下面这段代码是最小可用处理器,挂在 MT5 里用调试模式跑 SBRF-12.14 就能在日志看到逐条 Type/Price/Volume。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| BookEvent function                                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnBookEvent(const class="type">class="kw">string &symbol)
  {
   Print("Book event for: "+symbol);
class=class="str">"cmt">//--- select the symbol
   if(symbol==_Symbol)
     {
      class=class="str">"cmt">//--- array of the DOM structures
      MqlBookInfo last_bookArray[];
      class=class="str">"cmt">//--- get the book
      if(MarketBookGet(_Symbol,last_bookArray))
        {
         class=class="str">"cmt">//--- process book data
         for(class="type">int idx=class="num">0;idx<ArraySize(last_bookArray);idx++)
           {
            MqlBookInfo curr_info=last_bookArray[idx];
            class=class="str">"cmt">//--- print
            PrintFormat("Type: %s",EnumToString(curr_info.type));
            PrintFormat("Price: %class="num">0."+IntegerToString(_Digits)+"f",curr_info.price);
            PrintFormat("Volume: %d",curr_info.volume);
           }
        }
     }
  }

盘口卖单堆量的真实截面

上面这串日志是 SBRF-12.14 在 M1 周期下、11:24:33.812 同一毫秒由 BookEventProcessor1 抓到的深度报单快照。所有记录时间戳完全一致,说明这是一次 BookEvent 触发的同步回调,不是逐笔成交流。 卖侧挂单从 7704 一路铺到 7698:7704 挂 6 手、7703 挂 3 手、7701 挂 2 手、7700 挂 10 手、7698 挂 50 手,类型清一色 BOOK_TYPE_SELL。 最扎眼的是 7700 价位那一档——Volume 1011,是相邻档位的 20 倍以上,形成一道明显的薄价下方厚墙。外汇与贵金属盘口虽不如俄股合约这般集中,但类似单档异常堆量在 XAUUSD 美盘开盘也常出现,属高波动高风险信号,倾向预示该价位短期有强抛压或冰山单掩护。 开 MT5 接 MqlBookInfo + OnBookEvent,把上面这种同毫秒截面按价位排个序,你就能肉眼看到谁在挂墙、墙在哪破。

常见问题

用 OnBookEvent 钩子函数,系统在深度簿变动时主动回调,比定时器轮询更省资源、延迟更低。
type 为 0 是卖价挂单、1 是买价挂单;volume 是该价位挂单手数,直接读结构体字段即可拿到盘口截面。
可以,小布盯盘的 AIGC 已内置深度异动诊断,打开对应品种页就能看到卖单堆量预警,不用自己写代码。
先确认账户开了市场深度权限且品种支持 DOM,再检查 EA 是否跑在对应图表上,符号名要匹配。
仅代表该价位挂单增厚,可能是限售单也可能是诱盘,外汇贵金属高风险,需结合价格行为概率判断。