Ошибка 143

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

Вопросы.
1. Что это за ошибка с кодом 143?
2. Как её обрабатывать?
 
Это - один из внутренних кодов обмена между клиентом и сервером.

Код 143 означает, что ордер принят дилером к исполнению. Но он не должен был быть отдан клиенту. Будем разбираться.
 
А можно попросить у Вас вчерашние логи экспертов и терминала? stringo AT metaquotes DOT ru
 
А можно попросить у Вас вчерашние логи экспертов и терминала? stringo AT metaquotes DOT ru
Отправил...
 
Спасибо.
Расследование показало следующее:
В процессе выполнения торговой операции произошёл обрыв связи и перелогин. При этом торговый поток был остановлен и его последнее состояние (ордер принят дилером к исполнению) было передано обратно эксперту.

Ситуация по нашему мнению невозможная. Как оказалось, наше мнение было ошибочным. Мы обязательно добавим описание недостающих служебных кодов 142, 143 и 144. Эти коды необходимо обрабатывать так же, как и 128 (таймаут)
 

Ситуация по нашему мнению невозможная. Как оказалось, наше мнение было ошибочным. Мы обязательно добавим описание недостающих служебных кодов 142, 143 и 144. Эти коды необходимо обрабатывать так же, как и 128 (таймаут)

Как же таймаут, если KimIV сразу уточнил, что второй запрос пошел через 45с? И получил две открытых позиции. Значит, не помогает?
 
Благодарю, Slawa!

Если кому-то интересно, ошибку 128 я обрабатываю следующим образом:
1. Делаю паузу Sleep().
2. После паузы проверяю открылась позиция или нет.
3. Если открылась, то прерываю цикл запросов.
4. Если не открылась, то продолжаю цикл запросов.

Вот необходимый код
//+------------------------------------------------------------------+
//| Открытие позиции                                                 |
//| Параметры:                                                       |
//|   op     - операция                                              |
//|   ldStop - уровень стопа                                         |
//|   ldTake - уровень тэйка                                         |
//|   pn     - порядковый номер Атомарной Торговой Системы (АТС)     |
//+------------------------------------------------------------------+
void OpenPosition(int op, double ldStop, double ldTake, int pn) {
  color  clOpen;
  double pp;
  int    err, it, ticket;
  string lsComm=mn[pn]+" "+Name_Expert+" "+GetNameTF(Period());

  if (op==OP_BUY) clOpen=clOpenBuy; else clOpen=clOpenSell;
  Lots=GetSizeLot();
  for (it=1; it<=NumberOfTry; it++) {
    while (!IsTradeAllowed()) Sleep(5000);
    RefreshRates();
    if (op==OP_BUY) pp=Ask; else pp=Bid;
    pp=NormalizeDouble(pp, Digits);
    ticket=OrderSend(Symbol(),op,Lots,pp,Slippage,ldStop,ldTake,lsComm,mn[pn],0,clOpen);
    if (ticket>0) {
      OpenDay[pn]=Day();
      if (UseSound) PlaySound(NameFileSound); break;
    } else {
      err=GetLastError();
      if (err==128) {
        Sleep(1000*PauseAfterError);
        if (ExistPosition(pn)) {
          if (UseSound) PlaySound(NameFileSound); break;
        }
        Print("Error(",err,") opening position: ",ErrorDescription(err),", try ",it);
        continue;
      }
      Print("Error(",err,") opening position: ",ErrorDescription(err),", try ",it);
      Sleep(1000*PauseAfterError);
    }
  }
}

//+------------------------------------------------------------------+
//| Возвращает флаг существования позиции конкретной АТС             |
//| Параметры:                                                       |
//|   pn - порядковый номер Атомарной Торговой Системы (АТС)         |
//+------------------------------------------------------------------+
bool ExistPosition(int pn) {
  for (int i=0; i<OrdersTotal(); i++) {
    if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
      if (OrderSymbol()==Symbol() && OrderMagicNumber()==mn[pn]) {
        if (OrderType()==OP_BUY || OrderType()==OP_SELL) {
          return(True);
        }
      }
    }
  }
  return(False);
}
 
Как же таймаут, если KimIV сразу уточнил, что второй запрос пошел через 45с? И получил две открытых позиции. Значит, не помогает?

Запрос пошёл потому что ошибка не была обработана. Игорь спросил, как должна обрабатываться ошибка 143. Я и ответил: "143 ошибка должна обрабатываться также как и таймаут". Обрабатываться в эксперте. Программистом
 
Я и ответил: "143 ошибка должна обрабатываться также как и таймаут". Обрабатываться в эксперте. Программистом

Спасибо, Slawa, огромное за ответ, столь же полезный, сколь и содержательный. Вызывает большой респект. Опять.

Способ, предложенный уважаемым (честно, без дурацкого сарказма на этот раз) KimIV, безусловно может решить проблему подтверждения торговли в реальном времени. Особенно, если сделать его работу асинхронной и избежать таким образом пропусков запуска обработчика тиков.
Одно ощутимое но - он требует уникальный идентификатор, задаваемый вызываемой программой, а именно уникальное магическое число (или менее приемлемый уникальный комментарий, который может быть подправлен сервером), что делает затруднительной идентификацию ордеров, принадлежащих определенной стратегии. Конечно, это не проблема для настоящего Программиста, Обрабатывающего Таймауты в Эксперте. Можно, например, разбить integer на "действительную" и "мнимую" части и использовать одну для идентификации стратегии, а другую для идентификации ордера. Но, к сожалению, не все трейдеры - программисты. Ну и, наоборот, конечно.

Не могли бы Вы, Slawa, дать релевантный ответ на вопрос, как должна обрабатываться ошибка №143, то есть, как должен быть обработан таймаут конкретно. Какова официальная точка зрения разработчиков на данную проблему?
 
Irtron, однозначного ответа я дать не могу. Может быть масса вариантов. Общий ответ мы дали в "MQL4: Ошибки исполнения" Он звучит так:
===
Прежде, чем производить повторную попытку (не менее, чем через 1 минуту), необходимо убедиться, что торговая операция действительно не прошла (новая позиция не была открыта, либо существующий ордер не был изменён или удалён, либо существующая позиция не была закрыта)
===
Причина обращения: