接收市场深度变化的事件

当订单簿状态变化时,终端会生成 OnBookEvent 事件。该事件由源代码中定义的 OnBookEvent 函数处理。为了让终端开始向 MQL 程序发送特定交易品种的 OnBookEvent 通知,必须首先使用 MarketBookAdd 函数订阅接收通知。

若要取消订阅某个交易品种的 OnBookEvent 事件,可调用 MarketBookRelease 函数。

OnBookEvent 事件是播报的,这意味着图表上有一个 MQL 程序订阅 OnBookEvent 事件就足够了,同一图表上的所有其他程序也将开始接收事件,前提是其他程序的代码中有 OnBookEvent 处理程序。因此,有必要分析交易品种的名称,其作为参数传递给处理程序。

OnBookEvent 处理程序的原型如下。

void OnBookEvent(const string &symbol)

OnBookEvent 事件始终会加入队列,即使前一个 OnBookEvent 事件的处理尚未完成。

重要的是,OnBookEvent 事件仅为通知,并不会提供订单簿的状态。要获得市场深度数据,必须调用 MarketBookGet 函数。

但应注意的是,MarketBookGet 调用即使是直接从 OnBookEvent 处理程序进行,也会在调用 MarketBookGet 时接收订单簿的当前状态,该状态不一定与触发 OnBookEvent 事件发送的订单簿状态相匹配。若一连串订单簿变更以极快速度到达终端时,可能会发生这种情况。

在这方面,为了获得市场深度变化的完整时间线,需要编写 OnBookEvent 的实现,并根据执行速度来确定优化顺序。

同时,在 MQL5 中,无法保证可获得所有唯一的市场深度状态。

如果程序已经开始成功接收通知,但随后当市场开放时通知消失不见(并且分时报价继续出现),可能表明订阅存在问题。特别是,另一个设计不当的 MQL 程序可能会执行超出必要次数的取消订阅操作。在这种情况下,建议在预定义的超时(例如,几十秒或一分钟)后,使用新的 MarketBookAdd 调用重新订阅。

一个无缓冲指标 MarketBookEvent.mq5 的示例允许你跟踪 OnBookEvent 事件的到达,并在注释中打印交易品种名称和当前时间(毫秒系统计数器)。为了清楚起见,我们使用 Comments.mqh 文件中的多行注释函数,该文件选自 在图表窗口中显示消息一节。

有趣的是,如果你将输入参数 WorkSymbol 留空(默认值),该指标本身将不会启动订单簿的订阅,但能够拦截同一图表上其他 MQL 程序请求的消息。我们来检验一下。

#include <MQL5Book/Comments.mqh>
   
input string WorkSymbol = ""// WorkSymbol (if empty, intercept events initiated by others)
   
void OnInit()
{
   if(StringLen(WorkSymbol))
   {
      PRTF(MarketBookAdd(WorkSymbol));
   }
   else
   {
      Print("Start listening to OnBookEvent initiated by other programs");
   }
}
   
void OnBookEvent(const string &symbol)
{
   ChronoComment(symbol + " " + (string)GetTickCount());
}
 
void OnDeinit(const int)
{
   Comment("");
   if(StringLen(WorkSymbol))
   {
      PRTF(MarketBookRelease(WorkSymbol));
   }
}

让我们使用默认设置(没有自己的订阅)运行 MarketBookEvent,然后添加上一节中的 MarketBookAddRelease 指标,并为其指定一个包含可用订单簿的若干交易品种列表(在以下示例中,为 "XAUUSD,BTCUSD,USDCNH")。在哪个图表上运行指标并不重要:可以是一个完全不同的交易品种,比如欧元兑美元 (EURUSD)。

在启动 MarketBookEvent 之后,该图表将立即变为空白(没有注释),因为还没有订阅。一旦 MarketBookAddRelease 启动(日志中应出现三行,成功订阅的状态等于 true),交易品种名称将随着其订单簿更新开始交替出现在注释中(我们还没有学习如何读取订单簿;这方面的内容将在下一节讨论)。

在屏幕上的显示效果如下。

关于“外部”交易品种订单簿变更的通知
关于“第三方”交易品种订单簿变更的通知

如果我们现在移除 MarketBookAddRelease 指标,即可取消订阅,注释将停止更新。随后移除 MarketBookEvent 将会清除该注释。

请注意,从请求退订到市场深度事件实际停止更新注释之间会间隔一段时间(一两秒钟)。

你可以在图表上单独运行 MarketBookEvent 指标,在其 WorkSymbol 参数中指定一些交易品种,以确保通知在同一个应用程序中运行。 MarketBookAddRelease 以前仅用于演示通知的播报特性。换言之,在一个程序中启用订单簿变更订阅会影响另一个程序中通知的接收。