После существенного улучшения аналитического инструмента провел анализ результатов его применения в разных условиях. После чего возникли гипотезы, для проверки которых создал соответствующие ситуации. Ниже пойдет их разбор.
Торговый сервер.
Нужно было открыть Hedge-демо-счет у технически компетентного брокера. Важным условием еще было отсутствие ограничения на количество живых позиций и ордеров. Выбрал этот вариант.
Скрипт.
На этом демо-счете запустил такой торговый скрипт, предварительно разрешив алготорговлю в Терминале.
#property script_show_inputs #include <MT4Orders.mqh> // https://www.mql5.com/ru/blogs/post/745131 input double inLot = 0.1; input int inAmountOrders = 500; input int inTP = 10; // Асинхронно открывает множество позиций с одинаковым TakeProfit. void OnStart() { const double Lot = MathMax(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN), inLot); const double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); for (int i = 0; i < inAmountOrders; i++) OrderSendAsync(_Symbol, OP_BUY, Lot, Ask, 0, 0, Ask + inTP * _Point); const double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); for (int i = 0; i < inAmountOrders; i++) OrderSendAsync(_Symbol, OP_SELL, Lot, Bid, 0, 0, Bid - inTP * _Point); }
CustomReport.
Скрипт открыл множество позиций с одинаковыми TakeProfit. Дождался их срабатывания и запустил CustomReport с такими настройками.
Сформировался HTML-отчет (прикреплен). На удивление показавший много особенностей исполнения ордеров в MT5. Их и разберем. Забегая вперед скажу, что все они будут плохими.
Маркет-ордера.
Обратил внимание на рост времени исполнения маркет-ордеров, отправленных асинхронно.
На сервере очередь присвоения тикетов, а затем исполнения затянулась на десятки миллисекунд. Выше тикет - дольше ждем результат.
Другой взгляд на эту ситуацию доказывает сказанное.
Рост времени рождения ордера на сервере ~5 тикетов в миллисекунду. Рост времени исполнения ~1-2 тикета в миллисекунду.
Это медленно!
Рождение TakeProfit.
Наблюдается такой рост времени рождения TakeProfit.
Удалось добиться сразу 63 миллисекунд всего лишь на рождение TakeProfit-ордера! Скорость роста TP-рождения ~7 тикетов в миллисекунду. Очень медленно.
И ведь это еще и тормозит исполнение лимитных ордеров.
Исполнение TakeProfit.
Наблюдался также рост времени исполнения TakeProfit.
Более широко это можно увидеть на следующей картинке.
По времени исполнения TakeProfit невозможно сказать, связано ли это с MT5 или же с софтом брокера.
Частичное исполнение TakeProfit.
Выбранный демо-сервер несколько уникален тем, что может демонстрировать реджекты и частичные исполнения. Давайте посмотрим, как выглядит частичное исполнение TakeProfit.
Была открыта позиция на 0.1 лота, а закрыта двумя TP по 0.05 лота, т.к. первый TP смог исполниться только наполовину. HTML-отчет это четко показал, заодно проинформировав (красным цветом), сколько сделок было использовано для формирования позиции до закрытия.
Хорошо видно, что ордер с неисполненным объемом TP просто удаляется. При этом новый TP с оставшимся объемом формируется не сразу, а дожидается нового тика - в данном случае на скрине это 2281(1) миллисекунда (в скобках - сколько времени с последнего тика) от активирующего тика. Неидеальное решение со стороны брокера.
Реджекты TakeProfit.
У каждой из позиций на скрине было два реджекта TP. Причем рождались они аж 48 и 68 миллисекунд. Т.е. и у TP-rejects можно видеть (зеленым выделено) длительность их рождения.
Лимитные ордера.
Уже хотел заканчивать с данной записью, но решил дополнительно проверить работу лимитных ордеров. По той же схеме, как выше, применил такой скрипт.
#property script_show_inputs #include <MT4Orders.mqh> // https://www.mql5.com/ru/blogs/post/745131 input double inLot = 0.1; input int inAmountOrders = 500; input int inTP = 10; // Асинхронно открывает множество лимитных ордеров. void OnStart() { const double Lot = MathMax(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN), inLot); const double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); for (int i = 0; i < inAmountOrders; i++) OrderSendAsync(_Symbol, OP_BUYLIMIT, Lot, Ask - inTP * _Point, 0, 0, Ask); const double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); for (int i = 0; i < inAmountOrders; i++) OrderSendAsync(_Symbol, OP_SELLLIMIT, Lot, Bid + inTP * _Point, 0, 0, Bid); }
Рождение лимитных ордеров.
Не нужно ничем вооружаться, чтобы увидеть, сколь медленно рождаются лимитные ордера!
Скорость рождения лимитных ордеров ~5 тикетов в миллисекунду. Ситуация почти ничем не отличается от маркет-ордеров, которые разбирали выше. Очень много уходит времени в MT5 на присвоение тикетов для любых типов ордеров: маркет и отложенные.
Исполнение лимитных ордеров.
На картинке нельзя не заметить рост длительности исполнения лимитных ордеров. Виноват в этом брокер или MT5 - невозможно сейчас сказать.
Что получилось?
Почти полное воспроизведение ситуаций, с которыми сталкиваюсь на реальных счетах.
На картинке выделил дикое по длительности рождение TP-ордеров. Количество реджектов зашкаливает (см. приложенный HTML-отчет). И т.д.
Очевидно, что MT5 не справляется с подобной нагрузкой. Перестаю активно торговать - ситуация улучшается. Возобновляю - ухудшается. Причем заметьте, что это касается в общем торгового сервера. Т.е. другие клиенты влияют на качество исполнения ваших же ордеров.
При скальпинге очень много формируется MT5-ордеров на торговом сервере всеми клиентами за короткий промежуток. Скрипты, что использовал в данной записи - это еще очень низкая нагрузка по сравнению с пиками, что создает клиентская база.
Очевидно, что и брокерам и, конечно, MQ нужно что-то делать. Рождение тех же тикетов для ордеров должно происходить быстрее даже не на один порядок. Надеюсь, столь скрупулезная запись побудит к изменению ситуации. А пока, действительно, фактор "Авось" имеет место быть в торговле через MT5, часто приводя к несистемным убыткам.
При нажатии на картинки они открываются в полном виде.