Баг: ложное информирование советника об отсутствии ордера и позиции

 

Столкнулся с такой проблемой:

  1. Советник проверяет наличие ордера. Если ордера нет, ставит его. Завершает работу.
  2. Цена подходит близко к цене исполнения ордера. Ордер исчезает из списка ордеров и позиций, видимо в это время он исполняется.
  3. Советник информируется, что нет ни ордера, ни позиции и естественно снова восстанавливает ордер. Завершает работу.
  4. На следующей проверке советник имеет две позиции вместо одной.

Правильная работа терминала - в одной транзакции сообщить терминалу, что ордер исполнен, а не сообщать советнику об отсутствии ордера и позиции.

Дублирую в отдельную тему пост https://forum.mql4.com/ru/73105/page4#1039798, так как на мой пост ответа не было.

 
Никогда еще с таким не сталкивался именно по "вине" терминала. Другое дело - баги в коде. Они были, и именно они приводили к подобному положению вещей, как Вы описываете. Ищите проблемы в коде. Если сами не можете, но хотите разобраться, приложите код.
 

Бага в советнике нет. В начале работы советника делается распечатка отложенных ордеров и позиций, в конце работы делается такая же распечатка. В течение секунды советник успевает установить ордер и получить в итоге две позиции вместо одной:

12:34:08.073    '104478700': pending order buy limit 0.10 GBPUSD.r at 1.33670 sl: 1.31650 tp: 1.39230
12:34:08.213    '104478700': order #154958 buy stop 0.10 GBPUSD.r at 1.33670 activated at price 1.33670

12:34:08.273    '104478700': order was opened : #155022 buy limit 0.10 GBPUSD.r at 1.33670 sl: 1.31650 tp: 1.39230
12:34:08.353    '104478700': order #155022 buy limit 0.10 GBPUSD.r at 1.33670 activated at price 1.33670

И такое было не один раз. Терминал работает не правильно. Правильный алгоритм описан в первом моем посте.

 

Не может так быть, что в терминале баг, а определяется он только у Вас.

Код, как я понимаю, секретный. Значит как-то постарайтесь по-подробней описать последовательность действий кода без определения условий открытия ордеров.

 
Gelium:

Бага в советнике нет. В начале работы советника делается распечатка отложенных ордеров и позиций, в конце работы делается такая же распечатка. В течение секунды советник успевает установить ордер и получить в итоге две позиции вместо одной:

12:34:08.073    '104478700': pending order buy limit 0.10 GBPUSD.r at 1.33670 sl: 1.31650 tp: 1.39230
12:34:08.213    '104478700': order #154958 buy stop 0.10 GBPUSD.r at 1.33670 activated at price 1.33670

12:34:08.273    '104478700': order was opened : #155022 buy limit 0.10 GBPUSD.r at 1.33670 sl: 1.31650 tp: 1.39230
12:34:08.353    '104478700': order #155022 buy limit 0.10 GBPUSD.r at 1.33670 activated at price 1.33670

И такое было не один раз. Терминал работает не правильно. Правильный алгоритм описан в первом моем посте.

Что имеется в виду под терминами: "в начале работы советника" и "в конце работы советника"? Если имеются в виду функции OnInit и OnDeinit, то слишком рано и слишком поздно определяете наличие ордеров. Если же имеется в виду начало и конец работы функции OnTick, то это уже другое дело. Приведите распечатку логов эксперта в начале функции и перед тем местом, когда устанавливаете второй ордер. То, что Вы привели, это общий лог, здесь он никак не поможет.
 
GeliumВ течение секунды советник успевает установить ордер и получить в итоге две позиции вместо одной:

12:34:08.073    '104478700': pending order buy limit 0.10 GBPUSD.r at 1.33670 sl: 1.31650 tp: 1.39230
12:34:08.213    '104478700': order #154958 buy stop 0.10 GBPUSD.r at 1.33670 activated at price 1.33670

12:34:08.273    '104478700': order was opened : #155022 buy limit 0.10 GBPUSD.r at 1.33670 sl: 1.31650 tp: 1.39230
12:34:08.353    '104478700': order #155022 buy limit 0.10 GBPUSD.r at 1.33670 activated at price 1.33670

Советник, как видно из протокола, установил 2 разных лимитных ордера (buy limit  и  buy stop) на одну и ту же цену. Они и открылись. И все это происходит в одну секунду. выход: 1) Добавьте функции Alert к установке ордеров с указанием номера ордера и времени. 2) сделайте задержку на эту одну секунду и RefreshRates - исчезнувший ордер появится.
 
Попробую пояснить ситуацию. В начале процедуры проверки наличия нужных ордеров в лог сохраняется список установленных ордеров и позиций для дальнейшей отладки или проверки правильности работы советника. В 12:34:08:000 ордера #154958 в списке существующих или отмененных ордеров терминала не было. То есть, ордер не существовал для советника ни в каком виде. Хотя до этого ордер был создан советником. Далее советник установил ордер #155022 и после проверки наличия остальных ордеров снова сделал распечатку существующих ордеров и позиций в конце процедуры. В итоге в логе по окончанию работы было 2 позиции. Команда RefreshRates выполняется, но к обновлению списка ордеров и позиций она не имеет никакого отношения, судя по справке.
 

Давайте с самого начала.

1. Речь идет об MT4 или MT5 ? Дело в том, что в MT5 при работе без хеджирования одна совокупная позиция, образованная исполнением всех ордеров. В MT4 позиции отсутствуют, а есть лишь ордера. Вспомните OrderSend  OrderModify OrderClose ...

2. Что значит завершает работу? ExpertRemove? Но тогда как он информируется? Если это return, то это всего лишь выход до следующего вызова.

3. Что значит ставит ордер  и  восстанавливает ордер? Судя по buy limit и buy stop  вы ставите отложки?

4. Поясните появление этих словосочетаний buy limit и buy stop в двух соседних строках журнала.

5. Покажите кусок кода, определяющий наличие позиции и ордеров

 
Gelium:
Попробую пояснить ситуацию. В начале процедуры проверки наличия нужных ордеров в лог сохраняется список установленных ордеров и позиций для дальнейшей отладки или проверки правильности работы советника. В 12:34:08:000 ордера #154958 в списке существующих или отмененных ордеров терминала не было. То есть, ордер не существовал для советника ни в каком виде. Хотя до этого ордер был создан советником. Далее советник установил ордер #155022 и после проверки наличия остальных ордеров снова сделал распечатку существующих ордеров и позиций в конце процедуры. В итоге в логе по окончанию работы было 2 позиции. Команда RefreshRates выполняется, но к обновлению списка ордеров и позиций она не имеет никакого отношения, судя по справке.
Как раз об этом мы Вас и просим - покажите этот лог, если, конечно, Ваша цель - разобраться в проблеме, а не просто заполнить ветку комментариями. Тот лог, который приведен, это общий лог терминала, никакого отношения к экспертам он не имеет.
 

Установка первого ордера:

2016.08.03 08:59:20 Требуется установить новый ордер: BUY-S GBPUSD.R Lot 0.10 @ 1.33670 Stop 1.31650 Limit 1.39230 gbp BID 1.33028 ASK 1.33066
2016.08.03 08:59:20 Создан ордер: GBPUSD.r BUY-S 1.33670 lot 0.10 -1.31650 +1.39230 +gbp 1.3367 #154958

Установка дублирующего ордера, так как первый ордер отсутствовал:

2016.08.03 12:34:08 Проверка OrderBuy BUY-L @ 1.33670 stop 1.31650 limit 1.39230
2016.08.03 12:34:08 Требуется установить новый ордер: BUY-L GBPUSD.R Lot 0.10 @ 1.33670 Stop 1.31650 Limit 1.39230 gbp BID 1.33633 ASK 1.33671
2016.08.03 12:34:08 Создан ордер: GBPUSD.r BUY-L 1.33670 lot 0.10 -1.31650 +1.39230 +gbp 1.3367 #155022

Выше уже привел лог терминала, который показывает почему терминал не сообщил советнику, что ордер #154958 существует. В это время открывалась позиция и до терминала от сервера дошло, что ордера уже нет, но не дошло, что есть позиция. Информацию о замене ордера позицией надо передавать одной транзакцией в терминал, чтобы не вводить советник в заблуждение.

Судя по реакции разработчиков, на MT4 они забили. Обход этого бага делается через "костыли". Похоже относительно МТ4 только такая практика и останется актуальной до его кончины.
 

1. Речь идет об MT4 или MT5 ? Дело в том, что в MT5 при работе без хеджирования одна совокупная позиция, образованная исполнением всех ордеров. В MT4 позиции отсутствуют, а есть лишь ордера. Вспомните OrderSend  OrderModify OrderClose ...

---

На форуме MT4 думаю пишут про MT4, а не MT5. Для MT5 есть отдельный форум. Так что речь идет про MT4. Речь идет об ордерах, а не о позициях. Думаю тут отличие должно быть понятно.


2. Что значит завершает работу? ExpertRemove? Но тогда как он информируется? Если это return, то это всего лишь выход до следующего вызова.

---

У процедуры обработки тика есть вход и выход. Она не выполняется в вечном цикле. Завершение процедуры - это и есть выход из нее.

3. Что значит ставит ордер  и  восстанавливает ордер? Судя по buy limit и buy stop  вы ставите отложки?
---

Все ордера - это отложенные ордера. Limit или stop - зависит от текущего курса. Для buy по заданной цене ордер входа может быть и buy limit, и buy stop.


4. Поясните появление этих словосочетаний buy limit и buy stop в двух соседних строках журнала.

---

Выше привел лог советника. ASK меняется, меняется и тип ордера.


5. Покажите кусок кода, определяющий наличие позиции и ордеров
---

  // Проверяем возможность закрытия позиции по ордеру
  for(cnt = OrdersHistoryTotal() - 1; cnt >= 0; cnt--) 
  {
    if (OrderSelect(cnt, SELECT_BY_POS, MODE_HISTORY)) 
    {
      s1 = OrderInfo() + " Close: " + TimeToString(OrderCloseTime(), TIME_DATE|TIME_MINUTES);
      if (StringFind(ps_ok, "(" + DoubleToString(OrderTicket(), 0) + ")", 0) != -1) continue;
      if (UpperCase(OrderSymbol()) != SetSymbol + u_SymbolRightPrefics) continue;
      if (StringFind(LowerCase(OrderComment()), SignalName + " " + SetStrOpenPrice, 0) == -1) continue;
      if (OrderType() != NeedTypeBasic) continue;
      if (OrderCloseTime() >= OrTime1 && OrderCloseTime() <= OrTime2)         
      {
             lg("Ордер не выставляем, так как найдена закрытая позиция: " + OrderInfo());
        ps_ok = ps_ok + "(" + DoubleToString(OrderTicket(), 0) + ")";
        return(1);
      }
    }
  }

...

  for(cnt = OrdersTotal() - 1; cnt >= 0; cnt--)
  {
    if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES))
    {
      s1 = OrderInfo();
      if (UpperCase(OrderSymbol()) != SetSymbol + u_SymbolRightPrefics) continue;
      // Проверяем именно открытые позиции
      if (OrderType() != NeedTypeBasic) continue;
      if (StringFind(LowerCase(OrderComment()), SignalName + " " + SetStrOpenPrice, 0) == -1) continue;
      lg("Позиция по ордеру уже открыта(1): " +  OrderInfo());
      ps_ok = ps_ok + "(" + DoubleToString(OrderTicket(), 0) + ")";
      return(1);
    }
  }

...

  // Поиск ранее установленного отложенного ордера
  for(cnt = OrdersTotal() - 1; cnt >= 0; cnt--)
  {
    if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES))
    {
      s1 = OrderInfo();
      if (UpperCase(OrderSymbol()) != SetSymbol + u_SymbolRightPrefics) continue;
      if (StringFind(LowerCase(OrderComment()), SignalName + " " + SetStrOpenPrice, 0) == -1) continue;
      if (MathAbs(NormalizeDouble(OrderLots(), 2) - NormalizeDouble(SetTradeLot, 2)) > 0.01) continue;
      if (OrderType() != NeedTypeWork) continue;
      if (StringFind(or_ok, "(" + DoubleToString(OrderTicket(), 0) + ")", 0) != -1) continue;
      if ((iTicket == 0) || (iTicket > OrderTicket()))
      {  
        iTicket = OrderTicket();
        lg("Найден подходящий ордер: " + OrderInfo());
      }  
    }  
  }