- Управление подпиской на события о стакане цен
- Получение событий об изменении стакана цен
- Чтение данных текущего стакана цен
- Использование данных стакана в прикладных алгоритмах
Использование данных стакана в прикладных алгоритмах
Стакан цен считается весьма полезной технологией для разработки продвинутых торговых систем. В частности, анализ распределения объемов стакана на уровнях, близких к рынку, позволяет заранее узнать среднюю цену исполнения ордера конкретного объема: достаточно просуммировать объемы уровней (противоположного направления), которые обеспечат его заливку. На тонком рынке, при недостаточности объемов, алгоритм может воздержаться от открытия сделки, чтобы избежать существенного проскальзывания цены.
На основе данных стакана можно конструировать и другие стратегии. Например, бывает важно знать ценовые уровни, на которых расположены крупные объемы.
MarketBookVolumeAlert.mq5
В следующем тестовом индикаторе MarketBookVolumeAlert.mq5 реализуем простой алгоритм для отслеживания объемов или их изменений, превышающих заданную величину.
#property indicator_chart_window
|
В индикаторе нет диаграмм. Контролируемый символ вводится в параметре WorkSymbol (если оставить его пустым, подразумевается рабочий символ графика). Минимальный порог отслеживаемых объектов, то есть чувствительность алгоритма, указывается в параметре VolumeLimit. В зависимости от другого параметра CountVolumeInLots, объемы анализируются и выводятся пользователю в нотации лотов (true) или единиц (false) — это также влияет на то, как должно вводиться значение VolumeLimit. Перевод из единиц в доли лотов обеспечивает макрос VOL: используемый в нем размер контракта contract инициализируем в OnInit (см. ниже).
#define VOL(V) (CountVolumeInLots ? V / contract : V) |
При обнаружении крупных объемов выше порога программа выведет сообщение о соответствующем уровне в комментарий. Для сохранения ближайшей истории предупреждений используем уже известный нам класс многострочных комментариев (Comments.mqh).
#define N_LINES 25 // количество строк в буфере комментариев
|
В обработчике OnInit подготовим необходимые настройки и подпишемся на стакан.
double contract;
|
Свойства SYMBOL_SESSION_BUY_ORDERS_VOLUME и SYMBOL_SESSION_SELL_ORDERS_VOLUME, если они заполнены вашим брокером для выбранного символа, позволят сориентироваться с тем, какой порог имеет смысл выбирать. По умолчанию VolumeLimit равен 0, из-за чего абсолютно все изменения стакана будут генерировать предупреждения. Чтобы отсеять малозначительные флуктуации, рекомендуется установить VolumeLimit в значение, которое превышает средний размер объемов на всех уровнях (посмотрите заранее во встроенном стакане или в индикаторе MarketBookDisplay.mq5).
Привычным образом реализуем финализацию.
void OnDeinit(const int)
|
Основную работу выполняет обработчик OnBookEvent. В нем описан статический массив MqlBookInfo mbp для хранения предыдущего варианта стакана (с прошлого вызова функции).
void OnBookEvent(const string &symbol)
|
При наличии старого и нового стакана производим сравнение объемов на их уровнях друг с другом во вложенных циклах по i и j. Напомним, что увеличение индекса означает уменьшение цены.
int j = 0;
|
Здесь акцент делается не на типе уровня, а только на величине объема, но при желании легко добавить в уведомления обозначение покупок или продаж, в зависимости от поля type того уровня, где произошло важное изменение.
В завершение сохраняем новую копию mbi в статическом массиве mbp для сравнения относительно него на следующем вызове функции.
if(ArrayCopy(mbp, mbi) <= 0)
|
ArrayCopy не ужимает динамический приемный массив автоматически, если он оказался больше, чем массив-источник, поэтому мы явным образом устанавливаем его точный размер с помощью ArrayResize.
Вспомогательная функция NotifyVolumeChange просто добавляет информацию о найденном изменении в комментарий.
void NotifyVolumeChange(const string action, const double price,
|
На следующем изображении показан результат работы индикатора для настроек CountVolumeInLots=false, VolumeLimit=20.
Уведомления об изменениях объема в стакане
MarketBookQuasiTicks.mq5
В качестве второго примера возможного применения стакана обратимся к проблеме получения мультивалютных тиков. Мы уже касались её в разделе Генерация пользовательских событий, где было предоставлено одно из возможных решений и индикатор EventTickSpy.mq5. Теперь, после знакомства с API стакана цен, мы может реализовать альтернативный вариант.
Создадим индикатор MarketBookQuasiTicks.mq5, который будет подписываться на стаканы заданного списка инструментов и находить в них цены лучшего предложения и спроса, то есть пары цен вокруг спреда, а это — ни что иное как цены Ask и Bid.
Разумеется, данная информация не является полным эквивалентом стандартных тиков (напомним, что потоки сделок/тиков и стакана могут поступать от совершенно разных поставщиков), но обеспечивает адекватное и оперативное представление о рынке.
Новые значения цен по символам будем выводить в многострочный комментарий.
Перечень рабочих символов задается во входном параметре SymbolList, как список, через запятую. Включение и отключение подписки на стаканы производится в обработчиках OnInit и OnDeinit.
#define N_LINES 25 // количество строк в буфере комментариев
|
Анализ каждого нового стакана осуществляется в OnBookEvent.
void OnBookEvent(const string &symbol)
|
Найденные рыночные цены Ask/Bid передаются во вспомогательную функцию OnSymbolTick для вывода в комментарий.
void OnSymbolTick(const string &symbol, const double price)
|
При желании вы можете убедиться, что наши синтезированные тики мало отличаются от стандартных тиков.
Вот как информация о поступающих квази-тиках выглядит на графике.
Мультисимвольные квази-тики, полученные на основе событий стаканов
Вместе с тем, следует еще раз отметить, что события стакана доступны на платформе только онлайн, но не в тестере. Если торговая система будет построена исключительно на квази-тиках из стакана, для её тестирования потребуется применение сторонних решений, обеспечивающих сбор и воспроизведение стаканов в тестере.