Управление подпиской на события о стакане цен

Получение информации о содержимом стакана цен производится в терминале по принципу подписки: MQL-программа должна сообщить о своем желании получать события о стакане или, наоборот, прекратить свою подписку с помощью вызова соответствующих функций MarketBookAdd и MarketBookRelease.

Функция MarketBookAdd производит подписку на получение извещений об изменении стакана цен по указанному инструменту. Таким образом, можно подписаться на стаканы множества инструментов, а не только рабочего инструмента текущего графика.

bool MarketBookAdd(const string symbol)

Обычно, эта функция вызывается из OnInit или в конструкторе класса долгоживущего объекта. Уведомления об изменении стакана поступают в программу в виде событий OnBookEvent, поэтому для их обработки в программе должна присутствовать одноименная функция-обработчик.

Если указанный символ не был выбран в Обзоре рынка перед вызовом функции, он будет добавлен в окно автоматически.

Функция MarketBookRelease отменяет подписку на извещения об изменении указанного стакана.

bool MarketBookRelease(const string symbol)

Обычно эта функция должна вызываться из OnDeinit или деструктора класса долгоживущего объекта.

Обе функции возвращают значение true в случае успеха, а иначе — false.

Для всех приложений, запущенных на одном графике, ведутся отдельные счетчики подписок в разрезе символов. Иными словами, на графике может быть несколько подписок на разные символы, и для каждого из них поддерживается свой собственный счетчик.

Подписка или отписка одиночным вызовом любой из функций изменяет счетчик подписок только для конкретного символа, на конкретном графике, где работает программа. Это означает, что на двух соседних графиках могут быть подписки на события OnBookEvent на один и тот же символ, но с разными значениями счетчиков подписок.

Начальное значение счетчика подписок равно нулю. При каждом вызове MarketBookAdd счетчик подписок для указанного символа на данном графике увеличивается на 1 (символ графика и символ в MarketBookAdd не обязаны совпадать). При вызове MarketBookRelease счетчик подписок на указанный символ в пределах графика уменьшается на 1.

Трансляция событий OnBookEvent по любому символу в пределах графика продолжается до тех пор, пока счетчик подписок по данному символу больше нуля. Поэтому важно, чтобы каждая MQL-программа, которая содержит вызовы MarketBookAdd, при завершении своей работы правильно отписывалась от получения событий по каждому использованному символу с помощью 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 существующие или отсутствующие символы. Случай с подпиской на стаканы нескольких символов мы рассмотрим в следующем разделе.