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 2018, MetaQuotes Software Corp."

#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事件处理函数程序运行客户端事件