CTrade И PositionClose - выдает ошибку

 

Добрый день,


Закрываю позицию таким кодом:

      int tik = (int) PositionGetInteger(POSITION_TICKET);
      while (!closed)
      {
         closed = trade.PositionClose(tik, 30);
         int err = GetLastError();
         if (!closed) {
            Print("Ошибка закрытия ордера: ", err);
         }
         
         int Rez = (int) trade.ResultRetcode();
         if (Rez != 10009){
            closed = false;
            Print("Ошибка закрытия ордера (ResultRetcode): ", Rez);
         }
         
         if (err == 4753) break; //уже закрыта, частная фигня

         if (!closed) {
            CSymbolInfo cs;
            cs.Name(val);
            cs.RefreshRates();
         }
         count++;
         if (count > 20) break;
      };


Получаю ошибки, что позиция не существует:

Т.е первая ошибка 4756: 

Не удалось отправить торговый запрос

Вторая 4753:

Позиция не найдена

Впринципе, все работает - позиция закрывается. Но мое чувство перфекционизма не дает спать спокойно, пока не пойму в чем дело. Подскажите, что я делаю не так?

 
Имя Торгового сервера?
 
SergeyN:

Добрый день,


Закрываю позицию таким кодом:


Получаю ошибки, что позиция не существует:

Т.е первая ошибка 4756: 

Не удалось отправить торговый запрос

Вторая 4753:

Позиция не найдена

Впринципе, все работает - позиция закрывается. Но мое чувство перфекционизма не дает спать спокойно, пока не пойму в чем дело. Подскажите, что я делаю не так?

Я не знаю какой будет результат, но так писать никогда не буду. Зачем вызывать GetLastError() если позиция закрылась?

      int tik = (int) PositionGetInteger(POSITION_TICKET);
      while (!closed)
      {
         closed = trade.PositionClose(tik, 30);
         if (!closed) {
         int err = GetLastError();
            Print("Ошибка закрытия ордера: ", err);
         }
         

На мой взгляд так правильней.

 
fxsaber:
Имя Торгового сервера?

AlpariMt5-Demo


Alexey Viktorov:

Я не знаю какой будет результат, но так писать никогда не буду. Зачем вызывать GetLastError() если позиция закрылась?

На мой взгляд так правильней.

Согласен, к GetLastError обращение лишнее. Но проблемы это не решает.

Сервер возвращает ошибку 4756 и закрывает позицию.

 
SergeyN:

AlpariMt5-Demo

Не воспроизводится.

 
SergeyN:

Добрый день,


Закрываю позицию таким кодом:


Получаю ошибки, что позиция не существует:

Т.е первая ошибка 4756: 

Не удалось отправить торговый запрос

Вторая 4753:

Позиция не найдена

Впринципе, все работает - позиция закрывается. Но мое чувство перфекционизма не дает спать спокойно, пока не пойму в чем дело. Подскажите, что я делаю не так?

Копайте в сторону двойного закрытия. Видимо позиция закрылась ещё до вашего кода.

 
fxsaber:

Не воспроизводится.

У меня стоят 5 терминалов с одним роботом с разными настройками. Ошибка стабильно воспроизводится на 2ух, на остальных - плавающая. Сервер у всех один - демо сервер Альпари. Разница только в источнике терминала - качал с сайтов разных брокеров (alpari, bcs, fxclub и другие).

Сергей Таболин:

Копайте в сторону двойного закрытия. Видимо позиция закрылась ещё до вашего кода.

Все действия обложил логами - получается, что эта ошибка после первого обращения. Обратите внимание, что ошибки разные: первая 4756 (не удалось отправить торговый запрос), потом 4753 (позиция не найдена)

 
SergeyN:

У меня стоят 5 терминалов с одним роботом с разными настройками. Ошибка стабильно воспроизводится на 2ух, на остальных - плавающая. Сервер у всех один - демо сервер Альпари. Разница только в источнике терминала - качал с сайтов разных брокеров (alpari, bcs, fxclub и другие).

Стресс-тест показал, что появляются ошибки [No price] и отсутствие записи истории после успешного маркет-OrderSend. Ваш баг воспроизвести не получилось.

 

Можете объяснить какой такой глубокий смысл в этой части вашего кода

         int Rez = (int) trade.ResultRetcode();
         if (Rez != 10009){
            closed = false;
            Print("Ошибка закрытия ордера (ResultRetcode): ", Rez);
         }

Зачем присваивать переменной closed значение false если в распечатке чётко сказано что позиция с указанным ID уже закрыта.

Не со второго-ли захода на закрытие получаются эти ошибки???

Добавьте распечатку успешного закрытия позиции и проверьте. Ещё не помешает, перед закрытием, проверить существует-ли позиция, одной из функций.

PositionGetTicket();
PositionSelectByTicket()
PositionSelect()
 
Alexey Viktorov:

Можете объяснить какой такой глубокий смысл в этой части вашего кода

Зачем присваивать переменной closed значение false если в распечатке чётко сказано что позиция с указанным ID уже закрыта.

Не со второго-ли захода на закрытие получаются эти ошибки???

Добавьте распечатку успешного закрытия позиции и проверьте. Ещё не помешает, перед закрытием, проверить существует-ли позиция, одной из функций.

Согласно документации к PositionClose:

"... Успешное окончание работы метода PositionClose(...) не всегда означает успешное совершение торговой операции. Необходимо проверять результат выполнения торгового запроса (код возврата торгового сервера) вызовом метода ResultRetcode(). …"

Оттуда же:

10009

TRADE_RETCODE_DONE

Заявка выполнена


Таким образом я проверяю выполнена ли заявка. Вроде все по документации.

Целиком процедура выглядит так:

   while (PositionSelect(val))
   {
      bool closed = false;
      Profit += PositionGetDouble(POSITION_PROFIT);
      int count = 0;
      
      int tik = (int) PositionGetInteger(POSITION_TICKET);
      while (!closed)
      {
         closed = trade.PositionClose(tik, 30);
         int err = GetLastError();
         if (!closed) {
            Print("Ошибка закрытия ордера: ", err);
         }
         
         int Rez = (int) trade.ResultRetcode();
         if (Rez != 10009){
            closed = false;
            Print("Ошибка закрытия ордера (ResultRetcode): ", Rez);
         }
         
         if (err == 4753) break; //уже закрыта, частная фигня

         if (!closed) {
            CSymbolInfo cs;
            cs.Name(val);
            cs.RefreshRates();
         }
         count++;
         if (count > 20) break;
      };
   }

Т.е PositionSelect() я делаю. В переменную closed я получаю сначала флаг отправки запроса, потом ее же использую как флаг в случае неуспешного ResultRetcode(). Что Вы здесь видите странного?

ResultRetcode возвращается к предыдущему PositionClose() - поэтому второго захода здесь нет. Может вызовы закрытия выполняются асинхронно? Тогда подскажите пжл, как установить синхронный режим или дождаться выполнения запроса?

fxsaber:

Стресс-тест показал, что появляются ошибки [No price] и отсутствие записи истории после успешного маркет-OrderSend. Ваш баг воспроизвести не получилось.

Спасибо за попытку! Может быть связано с особенностями интернет канала? Разница у нас с Вами получается только в этом.

 

SergeyN:

Что Вы здесь видите странного?

Странно то, что проверка ResultRetcode() идёт за пределами блока закрытия позиции.

У меня вот такой вариант закрытия:

bool CTradeManager::closingPosition(ulong ticket)
{
  bool closed = false, positionSelect = false;
  uint rez = 0;
 do
  {
   positionSelect = PositionSelectByTicket(ticket);
   closed = trade.PositionClose(ticket);
   rez = trade.ResultRetcode();
   if(rez != 10009)
    Print("****** Оштбка закрытия позиции ", GetLastError());
  }
 while(!positionSelect);
 return(closed);
};/*******************************************************************/
Это без обработки ошибок и подсчёта количества попыток. Пока не дописал...
Причина обращения: