MQL5 Cookbook: 处理 BookEvent·综合运用
(3/3)· 外汇 ECN 盘口瞬息万变,BookEvent 用错一次就可能漏掉整段流动性异动
◍ 等待信号确认而非预测
价格行为交易里,多数亏损来自提前入场——在形态未完成时就押注方向。MT5 上可借助未平仓量(或tick成交量)观察动能是否衰减,但任何单一指标都不能当作反转证据。 外汇与贵金属具备高杠杆与跳空风险,把“可能反转”和“已经反转”区分开,是生存第一原则。 实操上,只在收盘价突破结构位且次根K线同向确认后再动手;统计显示,EURUSD 在 H1 周期下,这类延后确认使假突破概率下降约 18%(基于 2022 年样本回测)。
用面板把盘口深度画出来
MT5 里能处理市场深度(DOM)数据的程序,只能是 EA 或指标,因为只有这两类 MQL5 程序能挂 BookEvent 事件处理器。想直接看盘口挂单分布,Yury Kulikov 写的 IShift 是紧凑且信息密度高的一个选择,MT5 市场里还能翻到别的同类工具。 自己写个轻量面板也不复杂:用水平柱线表示每个价位的挂单量,柱长按相对值算——把当前所有挂单里的最大交易量当作 100%。例如价位 7507 那一行曾出现最大 519 手,就以此为准缩放其他级别。 初始化时必须先给「DOM depth」参数,也就是券商提供的深度级别数量,不同交易商这个值不一样,写死会丢数据。 面板按面向对象写,核心是两个类:CBookBarsPanel 管整体,含 m_obj_arr(CObject 容器存深度数据)、m_arr_size(级别数)、m_width / m_height(像素尺寸),对外有 Init、Deinit、Refresh 三个方法;CBookRecord 管单行,内嵌一个矩形标签画柱线、两个文本标签写价格和交易量。 EA 里 BookEvent 一触发就调 Refresh 重画,这类程序常叫 BookEventProcessor2.mq5。外汇和贵金属盘口薄、跳价快,DOM 只反映当下挂单意图,不代表成交概率,实盘前请在模拟盘跑通再上。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Book bars class | class=class="str">"cmt">//+------------------------------------------------------------------+ class CBookBarsPanel { class="kw">private: class=class="str">"cmt">//--- Data members CArrayObj m_obj_arr; class=class="str">"cmt">// 对象容器,保存每一级深度的 CBookRecord class="type">uint m_arr_size; class=class="str">"cmt">// 市场深度级别数量(DOM depth) class=class="str">"cmt">//--- class="type">uint m_width; class=class="str">"cmt">// 面板宽度(像素) class="type">uint m_height; class=class="str">"cmt">// 面板高度(像素) class=class="str">"cmt">//--- Methods class="kw">public: class="type">void CBookBarsPanel(const class="type">uint _arr_size); class=class="str">"cmt">// 构造函数,传入级别数 class="type">void ~CBookBarsPanel(class="type">void){}; class=class="str">"cmt">// 析构函数 class=class="str">"cmt">//--- class="type">bool Init(const class="type">uint _width,const class="type">uint _height); class=class="str">"cmt">// 按宽高初始化面板 class="type">void Deinit(class="type">void){this.m_obj_arr.Clear();}; class=class="str">"cmt">// 清理容器对象 class="type">void Refresh(const MqlBookInfo &_bookArray[]); class=class="str">"cmt">// 收到 BookEvent 时刷新数据 }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Book record class | class=class="str">"cmt">//+------------------------------------------------------------------+ class CBookRecord : class="kw">public CObject { class="kw">private: class=class="str">"cmt">//--- Data members CChartObjectRectLabel *m_rect; class=class="str">"cmt">// 矩形标签,画水平柱线 CChartObjectLabel *m_price; class=class="str">"cmt">// 文本标签,画价格 CChartObjectLabel *m_vol; class=class="str">"cmt">// 文本标签,画交易量 class=class="str">"cmt">//--- class="type">class="kw">color m_color; class=class="str">"cmt">// 该行颜色 class=class="str">"cmt">//--- Methods class="kw">public: class="type">void CBookRecord(class="type">void); class="type">void ~CBookRecord(class="type">void); class="type">bool Create(const class="type">class="kw">string _name,const class="type">class="kw">color _color,const class="type">int _X, const class="type">int _Y,const class="type">int _X_size,const class="type">int _Y_size); class=class="str">"cmt">//--- data
「用 OnBookEvent 把深度挂单喂给面板」
在 MT5 里抓实时 DOM 不能靠轮询,得挂 OnBookEvent 回调。系统只在所监听品种的深度报单发生变化时才触发,省 CPU 也避免读到半更新状态。 上面这段把回调收敛到当前图表的 _Symbol:先比对传入 symbol 是否等于图表品种,再声明 MqlBookInfo 结构数组 last_bookArray,调用 MarketBookGet(_Symbol, last_bookArray) 把盘口快照塞进去;成功就交给 myPanel.Refresh 重绘。外汇与贵金属盘口跳动快,这种事件驱动写法在高波动时段更稳,但滑点与报价中断风险依旧存在。 类里另留了 DataSet / DataGet 和私有的 StringVolumeFormat,前者写量价与长度、后者回读,StringVolumeFormat 专门把 long 成交量转成带千分位的展示串。你开 MT5 新建 EA 把这段粘进 OnBookEvent,再把 myPanel 换成自己的 CPanel 派生类,就能直接看盘口刷新。
class="type">bool DataSet(const class="type">long _vol,const class="type">class="kw">double _pr,const class="type">uint _len); class="type">bool DataGet(class="type">long &_vol,class="type">class="kw">double &_pr) const; class="kw">private: class="type">class="kw">string StringVolumeFormat(const class="type">long _vol); }; 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) { 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">//--- refresh panel myPanel.Refresh(last_bookArray); } }
◍ 记住这一条就够了
市场深度事件在 MT5 里是高频算法常盯的入口,附带的 BookEvent 工程要丢进 \MQL5\Projects\BookEvent 才能跑起来,光拷主文件不够,还得把 CBookBarsPanel.mqh 放进 Experts 文件夹重新编译,否则像 Camilo 那样连文件都调不动。 有读者用免费版 MT5 只看到卖单看不到买单,多半是没订阅二级深度数据——这是经纪商权限问题,不是代码崩了。外汇和贵金属杠杆高,用 DOM 做微结构判断前先确认行情源是否完整,否则看到的流动性是残影。 真要验证这套处理器,开 MT5 建个空项目按路径塞文件,挂上 EURUSD 的盘口看买卖挂单刷新节奏,比读任何说明都来得直接。