Ошибки, баги, вопросы - страница 540

 

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

Использую функцию PositionClose для закрытия позиций. Но вместе с закрытием позиций эта функцию сама ОТКРЫВАЕТ сделки!

Функция используется так:

//--- Объект класса СTrade
CTrade mytrade;
//--- Объект класса СPositionInfo
CPositionInfo myposition;

//+------------------------------------------------------------------+
//| Проверяет и если нужно, закрывает открытую позицию               |
//+------------------------------------------------------------------+
bool ClosePosition(string ptype,double clp)
  {
   bool R=false, marker=false; int i;
     
      if(myposition.Select(_Symbol)==true)
        {
         if(myposition.Symbol()==_Symbol)
           {
            //--- Делаем попытки закрыть позицию, если позиция не закрылась с первого раза
              for (i=5; i>=1; i--) 
                {R=mytrade.PositionClose(_Symbol,50,5); if (R == true && myposition.Select(_Symbol)==false) break;}
               if(i >= 1) 
                 {//--- запрос успешно выполнен
                  Alert("Открытая позиция была успешно закрыта!!");
                  marker=true;
                 }
               else
                 {
                  Alert("Запрос на закрытие позиции не выполнен - ошибка: ",mytrade.ResultRetcodeDescription());
                 }
            //  }
           }
        }
      return(marker);
     }

 В итоге PositionClose открывает иногда лишние ордеры.

 

Здесь сделка Buy сначала была закрыта, а потом была открыта лишняя сделка Sell такого же объема. Более того, AccountInfoDouble(ACCOUNT_FREEMARGIN) не заметил этой лишней сделки. Поскольку следом была открыта сделка с увеличенным лотом, хотя средств для этого согласно используемого ММ было не достаточно с учетом открытой лишней сделки.

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

 
masharov:

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

Почитайте статью Торговые события в MetaTrader 5:

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

А также статья Ордерa, позиции и сделки в MetaTrader 5
 

Я не использовал функцию OrderSend. Используется функция PositionClose из стандартной библиотеки MQL, предназначенной для работы с ордерами.

В справке по этой функции не описано, что она может открывать сделки. 

Цитата из справки:

PositionClose

Закрывает позицию по указанному символу.

bool PositionClose(
const string symbol, // символ
ulong deviation=ULONG_MAX // отклонение
)

Параметры

symbol

[in] Наименование торгового инструмента, по которому предполагается закрыть позицию.

deviation=ULONG_MAX

[in] Максимальное отклонение от текущей цены (в пунктах).

Возвращаемое значение

true - в случае успешной базовой проверки структур, иначе false.

Примечание

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

 
masharov:

Я не использовал функцию OrderSend. Используется функция PositionClose из стандартной библиотеки MQL, предназначенной для упрощений работы с ордерами.

В справке по этой функции не описано, что она может открывать сделки. 

Цитата из справки:

PositionClose

Закрывает позицию по указанному символу.

bool PositionClose(
const string symbol, // символ
ulong deviation=ULONG_MAX // отклонение
)

Параметры

symbol

[in] Наименование торгового инструмента, по которому предполагается закрыть позицию.

deviation=ULONG_MAX

[in] Максимальное отклонение от текущей цены (в пунктах).

Возвращаемое значение

true - в случае успешной базовой проверки структур, иначе false.

Примечание

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

Ошибки в библиотечной функции PositionClose(...) ни какой нет. А вот в коде у вас есть. Вот вы сами привели цитату из справки.

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

Я вот например не вижу у вас в коде этой проверки.

 
masharov:

Я не использовал функцию OrderSend. Используется функция PositionClose из стандартной библиотеки MQL, предназначенной для работы с ордерами.

В справке по этой функции не описано, что она может открывать сделки. 


А вы посмотрите реализацию функции PositionClose:

bool CTrade::PositionClose(const string symbol,ulong deviation)
  {
   bool   partial_close=false;
   int    retry_count  =10;
   uint   retcode      =TRADE_RETCODE_REJECT;
//--- check stopped
   if(IsStopped(__FUNCTION__)) return(false);
//--- variables
   string action,result;
//--- clean
   ClearStructures();
   do
     {
      //--- checking
      if(PositionSelect(symbol))
        {
         if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            //--- prepare request for close BUY position
            m_request.type =ORDER_TYPE_SELL;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_BID);
           }
         else
           {
            //--- prepare request for close SELL position
            m_request.type =ORDER_TYPE_BUY;
            m_request.price=SymbolInfoDouble(symbol,SYMBOL_ASK);
           }
        }
      else
        {
         //--- position not found
         m_result.retcode=retcode;
         return(false);
        }
      //--- setting request
      m_request.action      =TRADE_ACTION_DEAL;
      m_request.symbol      =symbol;
      m_request.deviation   =(deviation==ULONG_MAX) ? m_deviation : deviation;
      m_request.type_filling=m_type_filling;
      m_request.volume      =PositionGetDouble(POSITION_VOLUME);
      //--- check volume
      double max_volume=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
      if(m_request.volume>max_volume)
        {
         m_request.volume=max_volume;
         partial_close=true;
        }
      else
         partial_close=false;
      //--- order check
      if(!OrderCheck(m_request,m_check_result))
        {
         //--- copy return code
         m_result.retcode=m_check_result.retcode;
         if(m_log_level>LOG_LEVEL_NO)
            printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
         return(false);
        }
      //--- order send
      if(!OrderSend(m_request,m_result))
        {
         if(--retry_count!=0) continue;
         if(retcode==TRADE_RETCODE_DONE_PARTIAL)
            m_result.retcode=retcode;
         if(m_log_level>LOG_LEVEL_NO)
            printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
         return(false);
        }
      retcode=TRADE_RETCODE_DONE_PARTIAL;
      if(partial_close) Sleep(1000);
     }
   while(partial_close);
   if(m_log_level>LOG_LEVEL_ERRORS)
      printf(__FUNCTION__+": %s [%s]",FormatRequest(action,m_request),FormatRequestResult(result,m_request,m_result));
//--- ok
   return(true);
  }
 

Полагал, что мне не нужно изучать исходный код стандартных библиотек.

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

Цитата:

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

 
masharov:

Полагал, что мне не нужно изучать исходный код стандартных библиотек.

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

Незнание законов не освобождает от ответственности. Где в вашем коде проверка того, что позиция закрылась?

            //--- Делаем попытки закрыть позицию, если позиция не закрылась с первого раза
              for (i=5; i>=1; i--) 
                {
                 R=mytrade.PositionClose(_Symbol,50,5); 
                 if (R == true && myposition.Select(_Symbol)==false) break;
                }

Выражение

R == true

говорит только об успешном выполнении функции PositionClose(), но не о закрытии позиции:

Примечание

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

А второе выражение 

myposition.Select(_Symbol)==false)

эквивалентно 

PositionSelect(_Symbol)==false)

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

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

 

Повторюсь.

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

 

Все что вы говорите, относится к закрытию сделок. Да, советник не оптимально проверяет закрытие позиции. Но это не разрешает функции, предназначенной для закрытия, открывать самостоятельно сделки.

В справке сказано:

PositionClose

Закрывает позицию по указанному символу. 

Ни каких условий не описано, что функция может открыть сделку. Рекомендация о проверке кода возврата тоже служит только для дополнительной проверки закрылась или не закрылась сделка.

 
masharov:

Повторюсь.

Я понимаю, что, возможно, не оптимально использую функции MQL. Но то что функция из фирменной библиотеки MQL, предназначенная для закрытия сделок, будет сама открывать сделки, не укладывается в мое представление о допустимом поведении функций.
Нет функции закрытия позиции, есть только функции отправки запроса на покупку или продажу (а что будет в результате - открытие или закрытие позиции - неизвестно). В Вашем случае из-а алгоритмической ошибки повторные запросы отсылаются без проверки выполнения предыдущего запроса.
 
Rosh:
Нет функции закрытия позиции, есть только функции отправки запроса на покупку или продажу (а что будет в результате - открытие или закрытие позиции - неизвестно). В Вашем случае из-а алгоритмической ошибки повторные запросы отсылаются без проверки выполнения предыдущего запроса.

В справке такая функция есть

Справочник MQL5 / Стандартная библиотека / Торговые классы / CTrade / PositionClose 

Закрывает позицию по указанному символу.

 

Как реализовано выполнение функции на низком уровне пользователя не должно волновать. Раз уж такая функция есть, то, полагаю, MetaQuotes гарантировал, что у нее не будет нестандартного поведения неописанного в справке. 

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

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