Организация цикла перебора ордеров

 

В продолжении темы запуска MQL5-библиотек под MT4

#property strict

// https://www.mql5.com/ru/docs/standardlibrary/graphics/cgraphic
#include <Graphics\Graphic.mqh> // MQL5\Include\Graphics\Graphic.mqh

void OnStart()
{
  double Y[] = {1, 2};
  
  GraphPlot(Y);
}
 

Часто в тестере, если бегунок скорости поставить на 31 - это медленно, если поставить на 32 - тест со сверхскоростью устремляется к своему завершению.

Выкручиваюсь, вставляя в код задержку через счетчик:

input int gDelay = 10000;        // Счетчик для задержки, off=0

void OnTick()
{
  int delayCount = 0;
  while(delayCount < gDelay) ++delayCount;
}

Задержку через input можно регулировать в зависимости от быстроты советника и мощности процессора.

Теперь на скорости 32 можно двигаться к тем моментам, которые интересуют, с той скоростью, которая меня устраивает.

 

Ниже будет затронута тема, которая касается не только MT4, но и MT5 с другими платформами. Но для удобного восприятия логика будет написана на MQL4, поэтому в этой ветке.


Чаще всего костяк (мясо наращивается любое) модификации/удаления ордеров сводится к следующей логике

// Самый распространенный костяк логики модификации ордеров
for (int i = OrdersTotal() - 1; i >= 0; i--)
  if (OrderSelect(i, SELECT_BY_POS))
    OrderModify(OrderTicket(), Price, SL, TP, OrderExpiration());


А теперь подход редкий, но гораздо правильнее

// Редкий, но правильный костяк модификации ордеров
for (int i = OrdersTotal() - 1; i >= 0; i--)
  if (OrderSelect(i, SELECT_BY_POS))
    if (OrderModify(OrderTicket(), Price, SL, TP, OrderExpiration()))     
    {
      i = OrdersTotal(); // Хотя бы так
      
      // А лучше так
//      OnTick(); break; // вместо строки выше лучше делать такой вызов (переполнения стека от рекурсивных вызовов быть не должно)
    }


После отправки торгового приказа меняется торговое окружение, поэтому желательно сразу после ответа торгового сервера выполнять с нуля всю торговую логику ТС.

 
fxsaber:

А теперь подход редкий, но гораздо правильнее

Этот вариант при любой ошибке зацикливается на модификации последнего в списке ордера, и советник, у которого ордеров больше 1, все остальные "теряет из виду".

Мой рецепт: цикл по всем своим ордерам, обработка каждого (при необходимости, перед обработкой обновление рыночной информации), на следующем тике — следующий подход. В некоторых случаях следующий подход (вызов OnTick) можно сделать сразу после завершения текущего цикла, если в нем были ошибки.

 
Andrey Khatimlianskii:

Этот вариант при любой ошибке зацикливается на модификации последнего в списке ордера, и советник, у которого ордеров больше 1, все остальные "теряет из виду".

Зацикливания не будет из-за этого условия

if (OrderModify(OrderTicket(), Price, SL, TP, OrderExpiration()))

Мой рецепт: цикл по всем своим ордерам, обработка каждого (при необходимости, перед обработкой обновление рыночной информации), на следующем тике — следующий подход. В некоторых случаях следующий подход (вызов OnTick) можно сделать сразу после завершения текущего цикла, если в нем были ошибки.

Тогда в журнале терминала можно будет увидеть больше ошибок торговых запросов.

 
fxsaber:

Зацикливания не будет из-за этого условия

Да, неправ, прочел его как !OrderModify.

При успешной модификации тоже нельзя повторять обработку с начала списка, т.к. в этом случае тоже один ордер будет модифицироваться (например, подтягиваться за ценой), а остальные могут надолго остаться без внимания.

Мой рецепт в силе.


fxsaber:

Тогда в журнале терминала можно будет увидеть больше ошибок торговых запросов.

Этого не понял.

 
Andrey Khatimlianskii:

При успешной модификации тоже нельзя повторять обработку с начала списка, т.к. в этом случае тоже один ордер будет модифицироваться (например, подтягиваться за ценой), а остальные могут надолго остаться без внимания.

Что-то в этой логике неправильно изначально. Тут надо сделать осознанный выбор: лучше один актуальный ордер или много неактуальных.

Мой рецепт в силе.

Этого не понял.

Пусть OrderModify выполняется 5 секунд. За время его выполнения пусть несколько раз на торговом сервере исполнился частично лимитный ордер, породив десяток сделок.

 
fxsaber:

Что-то в этой логике неправильно изначально. Тут надо сделать осознанный выбор: лучше один актуальный ордер или много неактуальных.

Один ордер не может быть на разных уровнях одновременно. Или заводить под каждый уровень своего советника? Сомнительное решение для подавляющего большинства стратегий.

Как частный случай — несколько позиций (набрали по тренду несколькими входами) и трейлинг-стоп для них. Тянуть СЛ только одной сделки, или модифицировать все? На резком движении с таким же резким последующим откатом вариант модификации только одного ордера сильно проиграет (а до остальных дело не дойдет, потому что каждый новый вызов ОнТик будет модифицировать тот самый первый в списке ордер).


fxsaber:

Пусть OrderModify выполняется 5 секунд. За время его выполнения пусть несколько раз на торговом сервере исполнился частично лимитный ордер, породив десяток сделок.

Пусть. Мы обработаем все ордера, которые были (и должны быть обработаны), и перейдем к новым на следующем тике или непосредственно после завершения первого цикла.

Иначе всегда есть риск работать с одной — последней — исполненной частью одного последнего ордера. Возможно, самой маленькой частью. Оставив крупный ордер висеть без присмотра.

 
Andrey Khatimlianskii:

Один ордер не может быть на разных уровнях одновременно. Или заводить под каждый уровень своего советника? Сомнительное решение для подавляющего большинства стратегий.

Как частный случай — несколько позиций (набрали по тренду несколькими входами) и трейлинг-стоп для них. Тянуть СЛ только одной сделки, или модифицировать все? На резком движении с таким же резким последующим откатом вариант модификации только одного ордера сильно проиграет (а до остальных дело не дойдет, потому что каждый новый вызов ОнТик будет модифицировать тот самый первый в списке ордер).

Не понимаю, почему OnTick будет модифицировать только один ордер? Все будут модифицироваться.

Пусть. Мы обработаем все ордера, которые были (и должны быть обработаны), и перейдем к новым на следующем тике или непосредственно после завершения первого цикла.

Иначе всегда есть риск работать с одной — последней — исполненной частью одного последнего ордера. Возможно, самой маленькой частью. Оставив крупный ордер висеть без присмотра.

Обращаю внимание на слово "костяк". Мясо в виде выбора приоритета по лоту или что-то иное всегда можно нарастить. Основа логики же остается неизменной: после успешного торгового приказа запусти всю торговую логику с нуля.

 
fxsaber:

Не понимаю, почему OnTick будет модифицировать только один ордер? Все будут модифицироваться.

Потому что цена будет двигаться, и на каждом новом вызове ОнТик будет выполняться условие для новой модификации все того же, первого в списке, ордера. Особенно, если модификация будет длиться 5 секунд ;)


fxsaber:

Обращаю внимание на слово "костяк". Мясо в виде выбора приоритета по лоту или что-то иное всегда можно нарастить. Основа логики же остается неизменной: после успешного торгового приказа запусти всю торговую логику с нуля.

Такой "костяк" сломает логику советника, работающего с более чем одним ордером.
Какой в нем смысл, если он не даст ни каких преимуществ для систем с одним ордером и испортит остальные?

Сортировка по объему и/или отдаленности от цены перед работой с ордерами — правильное решение. Но не нужно подразумевать, что все, кто скопирует код с форума, будут ее реализовывать.
В этом смысле мой код безопаснее.

Причина обращения: