OnBookEvent

BookEvent事件发生时在指标和EA中调用这个函数。它是用来处理市场深度的变化。

void  OnBookEvent(
   const string&  symbol         //交易品种
   );

参数

交易品种

[in] BookEvent到达的交易品种名称

返回值

无返回值

注意

若要获得任何交易品种的BookEvent事件,只需使用MarketBookAdd()函数,为该交易品种订阅接收该事件。若要为特定交易品种取消订阅接收BookEvent,则调用MarketBookRelease()函数。

BookEvent在整个图表中进行传播。这意味着,如果图表上的一个应用程序使用MarketBookAdd函数订阅BookEvent,那么在相同图表上启用的所有其他指标和EA以及OnBookEvent()处理程序也会收到这个事件。因此,有必要分析传递到OnBookEvent()处理程序的交易品种名称,并将其作为交易品种参数。

为运行在相同图表上的所有应用程序提供按交易品种分类的单独的BookEvent计数器。这意味着每个图表对不同的交易品种可能有多个订阅,并且为每个交易品种提供一个计数器。从BookEvent订阅和取消订阅,只在一个图表中更改指定交易品种的订阅计数器。换句话说,对于相同的交易品种,BookEvent可能有两个相邻的图表,但订阅计数值不同。

初始的订阅计数值为零。每调用一次MarketBookAdd(),图表上特定交易品种的订阅计数器都会增加1个(图表交易品种和MarketBookAdd()中的交易品种不必匹配)。当调用MarketBookRelease()时,在图表中指定交易品种的订阅计数器就会减少1个。任何交易品种的BookEvent事件都在图表中广播,直至计数器的值等于零。因此,很重要的一点就是,每个包含了MarketBookAdd ()调用的MQL5程序都在其工作结束时使用MarketBookRelease ()为每个交易品种正确取消订阅获取事件。为此,MarketBookAdd()MarketBookRelease()的调用数量甚至都应该适用于整个MQL5程序生命周期内的每个调用。在程序中使用标识或自定义订阅计数器可以使您安全地处理BookEvent事件,并阻止禁用订阅,以在同一图表内的第三方程序中获取该事件。

即使处理之前的BookEvent处理还没有结束,BookEvent 事件也不会被跳过,会始终被置于队列之中。

 

例如

//+------------------------------------------------------------------+
//|                                           OnBookEvent_Sample.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/articles/2635"
#property version   "1.00"
#property description "Example of measuring the market depth refresh rate using OnBookEvent()"
#property description "The code is taken from the article https://www.mql5.com/en/articles/2635"
//--- 输入参数
input ulong ExtCollectTime   =30;  // test time in seconds
input ulong ExtSkipFirstTicks=10;  // number of ticks skipped at start
//--- 订阅BookEvent事件的标识
bool book_subscribed=false;
//--- 接受来自市场深度的请求的数组
MqlBookInfo  book[];
//+------------------------------------------------------------------+
//| EA交易初始化函数                                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- 显示开始
   Comment(StringFormat("Waiting for the first %I64u ticks to arrive",ExtSkipFirstTicks));
   PrintFormat("Waiting for the first %I64u ticks to arrive",ExtSkipFirstTicks);
//--- 启用市场深度广播
   if(MarketBookAdd(_Symbol))
     {
      book_subscribed=true;
      PrintFormat("%s: MarketBookAdd(%s) function returned true",__FUNCTION__,_Symbol);
     }
   else
      PrintFormat("%s: MarketBookAdd(%s) function returned false! GetLastError()=%d",__FUNCTION__,_Symbol,GetLastError());
//--- 成功初始化
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 去初始化EA交易                                                     |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- 显示去初始化原因代码
   Print(__FUNCTION__,": Deinitialization reason code = ",reason);  
//--- 取消订阅以获取市场深度事件
   if(book_subscribed)
     {
      if(!MarketBookRelease(_Symbol))
         PrintFormat("%s: MarketBookRelease(%s) returned false! GetLastError()=%d",_Symbol,GetLastError());
      else
         book_subscribed=false;
     }
//--- 
  }
//+------------------------------------------------------------------+
//| BookEvent函数                                                     |
//+------------------------------------------------------------------+
void OnBookEvent(const string &symbol)
  {
   static ulong starttime=0;             // 测试开始时间
   static ulong tickcounter=0;           // 市场深度更新计数器
//--- 只有当我们自己订阅市场深度事件时处理它们
   if(!book_subscribed)
      return;
//--- 只为特定交易品种计算更新
   if(symbol!=_Symbol)
      return;
//--- 跳过第一个报价来清空队列和进行准备
   tickcounter++;
   if(tickcounter<ExtSkipFirstTicks)
      return;
//--- 记住开始时间
   if(tickcounter==ExtSkipFirstTicks
      starttime=GetMicrosecondCount();
//--- 请求市场深度数据
   MarketBookGet(symbol,book);
//--- 什么时候停止?  
   ulong endtime=GetMicrosecondCount()-starttime;
   ulong ticks  =1+tickcounter-ExtSkipFirstTicks;
// 从测试开始以后,已经过去多少毫秒?
   if(endtime>ExtCollectTime*1000*1000) 
     {
      PrintFormat("%I64u ticks for %.1f seconds: %.1f ticks/sec ",ticks,endtime/1000.0/1000.0,ticks*1000.0*1000.0/endtime);
      ExpertRemove();
      return;
     }
//--- 在评论字段中显示计数器
   if(endtime>0)
      Comment(StringFormat("%I64u ticks for %.1f seconds: %.1f ticks/sec ",ticks,endtime/1000.0/1000.0,ticks*1000.0*1000.0/endtime));
  }

 

 

另见

MarketBookAddMarketBookReleaseMarketBookGetOnTradeOnTradeTransactionOnTick事件处理函数程序运行客户端事件