管理市场深度事件的订阅

终端在订阅的基础上接收市场深度信息:MQL 程序必须表达其接收市场深度(订单簿)事件的意图,或者相反,通过调用适当的函数 MarketBookAddMarketBookRelease 来终止其订阅。

MarketBookAdd 函数用于订阅接收有关指定金融工具订单簿变更的通知。因此,你可以订阅许多金融工具的丁单薄,而不仅限于当前图表的工作金融工具。

bool MarketBookAdd (const string symbol)

通常,这个函数从 OnInit 或一个长期对象的类构造函数中调用。有关订单簿更改的通知会以 OnBookEvent 事件的形式发送给程序,因此,为了进行处理,程序必须有一个同名的处理程序函数。

如果在调用该函数之前没有在市场报价中选择指定的交易品种,该交易品种将被自动添加到窗口中。

MarketBookRelease 函数用于取消订阅有关指定订单簿变更的通知。

bool MarketBookRelease (const string symbol)

通常,这个函数应从 OnDeinit 或者一个长期对象的类析构函数中调用。

如果调用成功,两个函数均返回值 true,否则返回值 false

对于在同一图表上运行的所有应用程序,单独的订阅计数器通过交易品种进行维护。换言之,图表上的不同交易品种可以有几个订阅,每个订阅都有自己的计数器。

若通过单次调用任何函数而订阅或取消订阅,则仅改变当前运行程序的特定图表上特定交易品种的订阅计数器。这意味着两个图表可以订阅相同交易品种的 OnBookEvent 事件,但订阅计数器的值不同。

订阅计数器的初始值为零。每次调用 MarketBookAdd 时,给定图表上指定交易品种的订阅计数器都会加 1(图表交易品种和 MarketBookAdd 中的交易品种不必匹配)。当调用 MarketBookRelease 时,图表中指定交易品种的订阅计数器减 1。

OnBookEvent 事件(针对图表中的任何交易符号)生成。但前提是该交易品种的订阅计数器大于零。因此必须要确保每个包含 MarketBookAdd 调用的 MQL 程序在完成其工作后,均可使用 MarketBookRelease 正确地取消订阅每个交易品种的接收事件。为此,应确保 MarketBookAdd 调用和 MarketBookRelease 调用的数量相匹配。MQL5 不支持查询计数器的值。

第一个示例是一个简单的无缓冲指标 MarketBookAddRelease.mq5,该指标在启动时可启用对订单簿的订阅,在卸载时禁用订阅。在 WorkSymbol 输入参数中,可以指定要订阅的交易品种。如果留空(默认值),则为当前图表的工作交易品种启动订阅。

input string WorkSymbol = ""// WorkSymbol (empty means current chart symbol)
   
const string _WorkSymbol = StringLen(WorkSymbol) == 0 ? _Symbol : WorkSymbol;
string symbols[];
   
void OnInit()
{
   const int n = StringSplit(_WorkSymbol, ',', symbols);
   for(int i = 0i < n; ++i)
   {
      if(!PRTF(MarketBookAdd(symbols[i])))
         PrintFormat("MarketBookAdd(%s) failed"symbols[i]);
   }
}
   
int OnCalculate(const int rates_totalconst int prev_calculatedconst intconst double &price[])
{
   return rates_total;
}
   
void OnDeinit(const int)
{
   for(int i = 0i < ArraySize(symbols); ++i)
   {
      if(!PRTF(MarketBookRelease(symbols[i])))
         PrintFormat("MarketBookRelease(%s) failed"symbols[i]);
   }
}

作为一项附加功能,允许指定多个金融工具(以逗号分隔)。在这种情况下,可请求订阅所有交易品种。

当指标启动时,日志中会显示订阅成功的标志或错误代码。然后,指标会尝试取消订阅 OnDeinit 处理程序中的事件。

使用默认设置时,在可以使用订单簿的交易品种图表上,日志中将生成以下条目。

MarketBookAdd(symbols[i])=true / ok
MarketBookRelease(symbols[i])=true / ok

如果将指标放在有交易品种而没有订单簿的图表上,会看到错误代码。

MarketBookAdd(symbols[i])=false / BOOKS_CANNOT_ADD(4901)
MarketBookAdd(XPDUSD) failed
MarketBookRelease(symbols[i])=false / BOOKS_CANNOT_DELETE(4902)
MarketBookRelease(XPDUSD) failed

你可以通过在输入参数 WorkSymbol 中指定现有的或缺少的字符来进行体验。在下一节中,我们将考虑订阅几个交易品种订单簿的情况。