Тезисно про межбиржевой арбитраж и MT5. Не судите строго, но кодов не будет. Кто умеет тот и сам напишет, кто типично подворовывает обломается, кому интересно обратятся. Далее только постановка вопроса, анализ проблем и намёки про решения. В этой статье про самое-самое начало, сбор данных
Что и почему собираем
Внезапно для почти всех MT-шников: события OnTick и соответствующие CopyTicks нельзя непосредственно использовать в анализе и при торговле. MT-Тик это о далёком прошлом и вообще «вещь в себе». Не существует публичных критериев генерации тика.
Нас не интересуют «тики» которые прошли. Нас интересует минимальная цена лимиток в стакане предлагаемая к продажам (Ask - то есть потенциальная цена нашей покупки) и максимальная цена лимиток к покупкам (Bid - потенциальная цена наших продаж). При торговле мы будем либо открываться по рынку в этих ценах либо ставить лимитку в этот спред.
В других биржах нет такого как понятия как «тик». Есть тикер - периодическая трансляция, есть поток сделок, есть поток изменений стакана. Последние два имеют перекрёстные ссылки. В MetaTrader этого нет, поэтому в нём работа только со стаканом (как бы двусмысленно это не звучало).
До начала торговли и даже раньше создания торгового алгоритма, данные надо собрать, сохранить чтобы оанализировать и сравнивать с другими.
Какие данные точно надо собирать :
- серверное время события (изменения bid или ask) с максимально возможной точностью, в микросекундах. И приведённое к общему отсчёту, GMT+0 или UTC.
- пинг до сервера в момент события.
- прошедшее время от предыдущего события. Опционально, его можно и после считать, но в момент записи это делать сильно проще
- конечно-же цены bid,ask и объёмы стакана при них.
- если в книге более 1 уровня, то невредно сохранить следующий уровень bid2,ask2 и объемы. Можно и всю книгу хранить, это на вкус и цвет.
Проблемы времени
У сервера и терминала разные часовые пояса. У них разные настройки времени, где-то NTP работает где-то нет. Между ними есть задержки в передаче данных (пинг) и обработке данных. При этом системное время ещё и «плывёт» и там и там. Доступные в Mt5 якоря TimeLocal(), TimeCurrent() и относительные GetTickCount64(), GetMicrosecondCount() тоже «плывут». Первые плывут от эффекта работы NTP на обеих сторонах, вторые неизвестно от каких таймеров взяты да и те в виртуализации плавают.
Периодически и довольно часто (не реже раз в день) придётся синхронизоваться - считать разницу TimeLocal, TimeCurrent и набегающую ошибку в счётчиках. Для точности лучше чаще, но практика говорит раз в день доcтаточно и лучше это делать в неторговое время, иначе возникают другие проблемы. При перемене дат почти идеально, и точность соблюдаем и не мешаем торговле (в окрест 24:00 никто не торгует) и ничего не сбиваем
Траблы с котировками
Лучше на примерах: то что в MT4/5 USDJPY, в прочих местах обычно JPYUSD. И с соответствующими множителями (ту-же йену надо делить на 100 - котировка в MT это на самом деле USD/100JPY, доллар за сотню йен). Надо конвертировать и сохранять в каком-то общем виде. Для себя решите что при этом делать с _Point и _Digits;
Куда и как сохранять
Очень важный момент. Штатно, то есть без DLL, MetaTrader умеет сохранять данные 1) в файлы 2) в базу SQLite 3) через WebRequest 3.5) посредством TcpSocket; То есть не разбежишься
При этом данных много и они следуют часто и существенных задержек процедура записи не должна давать; Если не используете DLL то единственный путь, это писать в файл на Ram-диск. Или база SQLite в памяти. Вроде несложно, но проблем не оберёшься. Данных много, память не бесконечна, придётся что-то удалять и контролировать переполнения. Писать дополнительный код «это переносим в долговременный архив», «это удаляем».
Не забываем что будет ещё вторая половина (арбитраж он парный), которую тоже надо надо куда-то складывать. Совсем не факт что вторая половина в этом-же сборщике и вообще в MT5. Должны быть сущность/база/иерархия_файлов куда могут писать обе части.
И ко всему - придётся это всё дело ещё и анализировать. Желательно отдельно от «собирания данных», точно не в том-же терминале где идёт сбор. Чтобы ни в коем случае не дать лишней нагрузки и не сбить тайминги. Идеально когда сбор данных это отдельный сервер, аналитика отдельный и друг-другу не они мешают. Но это фантастика, реальнее хотя-бы разные процессы
Поэтому только внешняя специализированный база, и без DLL тут сложно обойтись. Причём перечень внешних баз которые умеют работать с большими и частыми дополнениями не так велик. Это всякие «TimeSeries DataBase», оптимизированные под постоянные потоковые дополнения.
Пока что использую InfluxDB. У него есть своя гора минусов, и немного плюсов. Почему именно он, там мои соображения, мои личные тараканы так проголосовали. Главное - база независимая от сборщика данных
Подсказка про моменты
MetaTrader событийно ориентирован. Когда произошло какое-то событие, оно ставится(буферизуется) в очередь и когда дошёл черёд то вызывается обработчик. Приоритеты событий/обработчиков не документированы и могут меняться от релизов/версий. Ровно как и правила буферизации/пропуска
Всего обработчиков событий (за деталями и для точности - в справочник):
- OnInit() - при инициализации экземпляра советника
- OnDeinit() - при деинициализации
- OnTick() - есть тик в текущем инструменте
- OnTimer() - истёк промежуток таймера
- OnChartEvent() - есть событие от интерфейса чарта
- OnBook() - изменения стакана одного из подписных инструментов
- OnTrade() - сработка или изменение отложки
- OnTradeTransaction() - оповещения о результате торгового приказа
Ещё есть тестерные, но они нас не волнуют
Просто намёк - так как приоритеты неизвестны, то проверку «наступило нужное событие» надо делать во всех доступных колбеках кроме, конструкторов/деструкторов. А чтобы жизнь мёдом не казалась - то и проверку на дубликат событий