Invalid Stops

 

Здравствуйте. Только начинаю, прочитал много теории пока, но есть ошибки с практикой. 
Открываю позицию с помощью функции Buy() библиотеки CTrade. Всегда ошибки invalid stops. Инструмент RTS 3.17

Файлы:
 
Fresto:

Здравствуйте. Только начинаю, прочитал много теории пока, но есть ошибки с практикой. 
Открываю позицию с помощью функции Buy() библиотеки CTrade. Всегда ошибки invalid stops. Инструмент RTS 3.17

Код вставьте в сообщение с помощью кнопки SRC. Со скриншота не вставляется в метаэдитор
 
Sergey Gritsay:
Код вставьте в сообщение с помощью кнопки SRC. Со скриншота не вставляется в метаэдитор
            double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);               //--- последняя цена ask
            double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
            double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
            if(mytrade.Buy(10,_Symbol,mprice,stloss,tprofit))
            //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit))
            {//--- Запрос выполнен или ордер размещен
              Alert("Ордер на покупку был успешно размещен, Ticket#:",mytrade.ResultDeal(),"!!");
            }
          else
           {
              Alert("Ордер на покупку объема:",mytrade.RequestVolume(),
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                    ", цена:", mytrade.RequestPrice(),
                    " не выполнен -ошибка:",mytrade.ResultRetcodeDescription());
              return;
           }
 
Fresto:
            double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);               //--- последняя цена ask
            double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
            double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
            if(mytrade.Buy(10,_Symbol,mprice,stloss,tprofit))
            //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit))
            {//--- Запрос выполнен или ордер размещен
              Alert("Ордер на покупку был успешно размещен, Ticket#:",mytrade.ResultDeal(),"!!");
            }
          else
           {
              Alert("Ордер на покупку объема:",mytrade.RequestVolume(),
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                    ", цена:", mytrade.RequestPrice(),
                    " не выполнен -ошибка:",mytrade.ResultRetcodeDescription());
              return;
           }
Перед вычислением цен, Вы метод RefreshRates() вызываете для объекта класса CSymbolInfo?
 
Vladimir Karputov:
Перед вычислением цен, Вы метод RefreshRates() вызываете для объекта класса CSymbolInfo?
Да, беру информацию отсюда https://www.mql5.com/ru/articles/138

if (!mysymbol.RefreshRates())
     {
      Alert("Ошибка обновления котировок - ошибка: ",GetLastError(),"!");
      return;
     } 

Как использовать торговые классы Стандартной библиотеки при написании советника
Как использовать торговые классы Стандартной библиотеки при написании советника
  • 2010.11.10
  • Samuel Olowoyo
  • www.mql5.com
В статье рассказывается о том, как использовать основной функционал торговых классов Стандартной библиотеки при написании советников, в которых применяется открытие, закрытие и модификация позиции, проверка свободной маржи перед размещением торговых ордеров, размещение и удаление отложенных ордеров. Показано, как использовать торговые классы для получения свойств ордеров и сделок.
 

Я проверил код на MetaQuotes-Demo - прошёл на ура!

Проверьте ещё для данного символа минимальный отступ: StopsLevel

 
Fresto:
Да, беру информацию отсюда https://www.mql5.com/ru/articles/138

if (!mysymbol.RefreshRates())
     {
      Alert("Ошибка обновления котировок - ошибка: ",GetLastError(),"!");
      return;
     } 

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

bool OrderOpen(ENUM_ORDER_TYPE type,double volume)
  {
   double price_open=0.0;
   volume=NormalizeVolume(_Symbol,volume);
   if(type==WRONG_VALUE)return(false);
   if(!disabled(_Symbol))return(false);
   double bid=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   double ask=NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   price_open=(type==ORDER_TYPE_BUY)?ask:bid;

   if(AccountInfo.FreeMarginCheck(_Symbol,type,volume,price_open)<=0.0)return(false);
   if(NormalizeDouble(NormalizePrice(_Symbol,price_open),_Digits)!=price_open)return(false);
   ResetLastError();
   if(type==ORDER_TYPE_BUY)trade.Buy(volume,_Symbol,0,0,0,CommentDeals);
   else trade.Sell(volume,_Symbol,0,0,0,CommentDeals);

   if(trade.ResultRetcode()==TRADE_RETCODE_DONE)return(true);
   else
     {
      StringConcatenate(rezult,_Symbol,": error open deal ",StrToType((ENUM_ORDER_TYPE)type)," ",DoubleToString(volume,2),": ",trade.ResultRetcodeDescription());
      Print(rezult);
      return(false);
     }
   return(false);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double NormalizePrice(string symbol,double value)
  {
   double ts=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
   if(ts==0)return(value);
   return(NormalizeDouble(value/ts,0)*ts);
  }


 

 
Значит ещё проверить и TickSize - даже очень интересно, что там такое брокер намутил.
 
Vladimir Karputov:
Значит ещё проверить и TickSize - даже очень интересно, что там такое брокер намутил.
я с этой проблемой столкнулся когда у меня бота в маркете не пропускали при прогоне на золоте, там три знака после запятой, а шаг цены в спецификации 0,01, и постоянно нарывался на эту ошибку, пока не сделал нормализацию кратно шагу цены.
 
Sergey Gritsay:
я с этой проблемой столкнулся когда у меня бота в маркете не пропускали при прогоне на золоте, там три знака после запятой, а шаг цены в спецификации 0,01, и постоянно нарывался на эту ошибку, пока не сделал нормализацию кратно шагу цены.

Сейчас посмотрю реализацию метода NormalizePrice...

 

Добавлено: вот оно:

//+------------------------------------------------------------------+
//| Normalize price                                                  |
//+------------------------------------------------------------------+
double CSymbolInfo::NormalizePrice(const double price) const
  {
   if(m_tick_size!=0)
      return(NormalizeDouble(MathRound(price/m_tick_size)*m_tick_size,m_digits));
//---
   return(NormalizeDouble(price,m_digits));
  }

то есть, когда считается Sl и TP нужно просто применять NormalizePrice, а не NormalizeDouble и проблем не будет.
 

 
Vladimir Karputov:
Значит ещё проверить и TickSize - даже очень интересно, что там такое брокер намутил.

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

double NormalizePrice(string symbol,double value)
  {
   double ts=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);
   if(ts==0)return(value);
   return(NormalizeDouble(value/ts,0)*ts);
  }
...
Причина обращения: