Глубина стакана цен

MetaTrader 5 позволяет получать о биржевых инструментах не только информацию о ценах и объемах сделок, упакованную в тики, но и "стакан цен" (или "глубину рынка"), то есть распределение объемов в выставленных заявках на покупку и продажу на нескольких ближайших уровнях вокруг текущей цены. Одно из целочисленных свойств символа SYMBOL_TICKS_BOOKDEPTH содержит максимальное количество уровней, показываемых в стакане. Это количество разрешено для каждой из сторон, то есть общий размер стакана может быть в два раза больше (причем здесь не учитываются ценовые уровни с нулевыми объемами, которые не транслируются).

В зависимости от обстановки на рынке, актуальный размер транслируемого стакана может стать и меньше, чем указано в данном свойстве. Для небиржевых инструментов данное свойство, как правило, равно 0, хотя некоторые брокеры могут транслировать стакан и для Forex-символов, ограниченный лишь заявками своих клиентов.

Сам стакан и уведомления о его обновлении должны быть запрошены заинтересованной MQL-программой с помощью специального API, которое мы рассмотрим в следующей главе.

Следует отметить, что в силу архитектурных особенностей платформы данное свойство не связано напрямую с трансляцией стакана, то есть это всего лишь поле спецификации, заполняемой брокером. Иными словами, ненулевое значение свойства не означает, что стакан обязательно будет поступать в терминал при открытом рынке. Это зависит от прочих настроек сервера и наличия на нем активного подключения к поставщику данных.

Попробуем получить статистику по глубине стаканов по всем или избранным символам с помощью скрипта SymbolFilterBookDepth.mq5.

input bool UseMarketWatch = false;
input int ShowSymbolsWithDepth = -1;

Параметр ShowSymbolsWithDepth, равный по умолчанию -1, предписывает собрать статистику по разным настройкам стакана среди всех символов. Если установить параметр в иное значение, программа попытается найти все символы с указанной глубиной стакана.

void OnStart()
{
   SymbolFilter f;                // объект фильтра
   string symbols[];              // массив для имен символов
   long depths[];                 // массив значений свойств
   MapArray<long,intstats;      // счетчики встречаемости каждой глубины
   
   if(ShowSymbolsWithDepth > -1)
   {
      f.let(SYMBOL_TICKS_BOOKDEPTHShowSymbolsWithDepth);
   }
   
   // применяем фильтр и заполняем массивы
   f.select(UseMarketWatchSYMBOL_TICKS_BOOKDEPTHsymbolsdepthstrue);
   const int n = ArraySize(symbols);
   
   PrintFormat("===== Book depths for %s symbols %s=====",
      (UseMarketWatch ? "Market Watch" : "all available"),
      (ShowSymbolsWithDepth > -1 ? "(filtered by depth="
      + (string)ShowSymbolsWithDepth + ") " : ""));
   PrintFormat("Total symbols: %d"n);
   ...

Если задана конкретная глубина, просто выводим массив символов (они все удовлетворяют условию фильтра), и завершаем работу.

   if(ShowSymbolsWithDepth > -1)
   {
      ArrayPrint(symbols);
      return;
   }
   ...

В противном случае ведем подсчет статистики и выводим её.

   for(int i = 0i < n; ++i)
   {
      stats.inc(depths[i]);
   }
   
   Print("Stats per depth:");
   stats.print();
   Print("Legend: key=depth, value=count");
}

При настройках по умолчанию можем получить следующую картину.

===== Book depths for all available symbols =====
Total symbols: 52357
Stats per depth:
    [key] [value]
[0]     0   52244
[1]     5       3
[2]    10      67
[3]    16       5
[4]    20      13
[5]    32      25
Legend: key=depth, value=count

Если установить ShowSymbolsWithDepth в одно из обнаруженных значений, например, 32, получим перечень символов с такой глубиной стакана.

===== Book depths for all available symbols (filtered by depth=32) =====
Total symbols: 25
[ 0] "USDCNH" "USDZAR" "USDHUF" "USDPLN" "EURHUF" "EURNOK" "EURPLN" "EURSEK" "EURZAR" "GBPNOK" "GBPPLN" "GBPSEK" "GBPZAR"
[13] "NZDCAD" "NZDCHF" "USDMXN" "EURMXN" "GBPMXN" "CADMXN" "CHFMXN" "MXNJPY" "NZDMXN" "USDCOP" "USDARS" "USDCLP"