- Создание и удаление пользовательских символов
- Свойства пользовательских символов
- Установка маржинальных коэффициентов
- Настройка котировочных и торговых сессий
- Добавление, замена и удаление котировок
- Добавление, замена и удаление тиков
- Трансляция изменений стакана заявок
- Особенности торговли с пользовательскими символами
Трансляция изменений стакана заявок
При необходимости, MQL-программа может генерировать для пользовательского символа стакан заявок с помощью функции CustomBookAdd. Это, в частности, может быть полезно для инструментов с внешних бирж, таких как криптовалютные.
int CustomBookAdd(const string symbol, const MqlBookInfo &books[], uint count = WHOLE_ARRAY)
Функция транслирует подписавшимся MQL-программам состояние стакана цен для пользовательского инструмента symbol, используя данные из массива books. Массив описывает полное состояние стакана, то есть все заявки на покупку и продажу. Переданное состояние полностью заменяет предыдущее и становится доступно через функцию MarketBookGet.
Параметр count позволяет задать количество элементов массива books, которое должно быть передано в функцию. По умолчанию используется весь массив.
Функция возвращает признак успеха (true) или ошибки (false).
Чтобы получить генерируемые функцией CustomBookAdd стаканы, заинтересованная в них MQL-программа должна, как обычно, подписаться на них с помощью MarketBookAdd.
При вбросе стакана цены Bid и Ask инструмента не обновляются: для этой цели следует отдельно вбрасывать тики при помощи CustomTicksAdd.
Передаваемые данные проверяются на корректность: цены и объемы должны быть больше нуля, для каждого элемента должны быть указаны тип, цена и объем (поля volume и/или volume_real). Если хотя бы один элемент стакана описан неверно, функция вернет ошибку.
Также проверяется параметр "Глубина стакана" (SYMBOL_TICKS_BOOKDEPTH) пользовательского инструмента. Если количество уровней на продажу или покупку в передаваемом стакане превышает это значение, лишние уровни отбрасываются.
Объем с повышенной точностью volume_real имеет больший приоритет по сравнению с обычным volume. Если для элемента стакана указаны оба значения, будет использовано volume_real.
Внимание! В текущей реализации CustomBookAdd автоматически блокирует пользовательский символ, как будто на него имеется подписка, выполненная с помощью MarketBookAdd, но события OnBookEvent при этом не поступают (в принципе, генерирующая стаканы программа может на них подписаться, вызвав MarketBookAdd явным образом и контролировать то, что будут получать другие программы). Удалить эту блокировку можно с помощью вызова MarketBookRelease.
Это может потребоваться в связи с тем, что символы, для которых имеются подписки на стакан, нельзя скрыть из Обзора рынка никакими средствами (пока все явные или неявные подписки не будут отменены из программ, а также не будет закрыто окно стакана). И как следствие, такие символы нельзя удалить.
В качестве примера создадим неторгующий эксперт PseudoMarketBook.mq5, который будет генерировать из ближайшей истории тиков псевдо-состояния стакана. Это может быть полезно для символов, для которых стакан не транслируется, в частности, для Forex. При желании можно использовать такие пользовательские символы для формальной отладки собственных торговых алгоритмов, использующих стакан.
Среди входных параметров укажем максимальную глубину стакана.
input uint CustomBookDepth = 20; |
Название кастом-символа будем формировать за счет добавления суффикса ".Pseudo" к названию текущего символа графика.
string CustomSymbol = _Symbol + ".Pseudo"; |
В обработчике OnInit создадим пользовательский символ и установим для него формулу, равную названию исходного символа. Таким образом, мы получим автоматически обновляемую терминалом копию исходного символа, и нам не потребуется утруждать себя копированием котировок или тиков.
int OnInit()
|
Если пользовательский символ уже существует, эксперт может предложить пользователю удалить его, и на этом завершить работу (предварительно пользователю следует закрыть все графики с этим символом).
else
|
Особенностью данного символа является установка свойства SYMBOL_TICKS_BOOKDEPTH, а также чтение размера контракта SYMBOL_TRADE_CONTRACT_SIZE — он потребуется при генерации объемов.
if(SymbolInfoInteger(_Symbol, SYMBOL_TICKS_BOOKDEPTH) != CustomBookDepth
|
Запуск алгоритма производится в обработчике OnTick. Здесь мы вызываем некую функцию GenerateMarketBook, которую еще предстоит написать. Она заполнит передаваемый по ссылке массив структур MqlBookInfo, и мы отправим его на пользовательский символ с помощью CustomBookAdd.
void OnTick()
|
Функция GenerateMarketBook анализирует последние count тиков и на их основе эмулирует возможное состояние стакана, руководствуясь гипотезами:
- то, что было куплено, скорее всего, будет продано;
- то, что было продано, скорее всего, будет куплено.
Разделение тиков на те, что соответствуют покупкам и продажам, в общем случае (при отсутствии биржевых флагов) можно оценить по движению самой цены:
- движение цены Ask вверх трактуется, как покупка;
- движение цены Bid вниз трактуется, как продажа.
В результате получим следующий алгоритм.
bool GenerateMarketBook(const int count, MqlBookInfo &book[])
|
Вспомогательная функция Place заполняет массивы buys и sells, аккумулируя в них объемы по ценовым уровням. Мы покажем её ниже. Индексы в массивах определяются как расстояние в пунктах от текущих лучших цен (Bid или Ask). Размер объема обратно пропорционален возрасту тика, то есть более отдаленные в прошлое тики оказывают меньшее влияние.
После того как массивы заполнены, на их основе формируется массив структур MqlBookInfo.
for(int i = 0, k = 0; i < ArraySize(sells) && k < depth; ++i) // верхняя половина стакана
|
Функция Place довольно проста.
void Place(double &array[], const int index, const double value = 1)
|
На следующем скриншоте показан график EURUSD с работающим на нем экспертом PseudoMarketBook.mq5 и получившийся вариант стакана.
Синтетический стакан заявок пользовательского символа на основе EURUSD