Ошибка перевода стоп-лос и тейк-профит из пунктов в цену

 

Есть функции пересчета стопов из пунктов в цену но иногда она не срабатывает и я получаю ошибку типо: 2022.12.09 13:29:29.347 forexteam-consumer (EURGBP,H1) CTrade::OrderSend: market sell 0.23 USDCAD sl: 0.00050 tp: -0.00150 [invalid stops] Ошибка возникает редко 1 раз на 30 - 40 вызовов, что вызывает еще большее недоумение.

input int TakeProfit = 150;
input int StopLoss = 50;


double ConvertTakeProfit(ENUM_ORDER_TYPE type, string symbol) {
    double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
    return (type == ORDER_TYPE_BUY ? Ask(symbol) + TakeProfit * point : Bid(symbol) - TakeProfit * point);
}

double ConvertStopLoss(ENUM_ORDER_TYPE type, string symbol) {
    double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
    return (type == ORDER_TYPE_BUY ? Ask(symbol) - StopLoss * point : Bid(symbol) + StopLoss * point);
}


double Ask(string symbol) { int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS); return NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), digits); } double Bid(string symbol) { int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS); return NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), digits); }

В примере ошибки видно что тейк-профит вообще отрицательный tp: -0.00150 Подскажите из-за чего это может быть, и почему возникает иногда?

Возникает ощущение что в при каких-то обстоятельствах функции  Ask и  Bid или SymbolInfoDouble(symbol, SYMBOL_BID) возвращают 0. Хотя не понятно почему.


Вызов самого торгового вызова выглядит так:




int OrderSendRetryPolicy = 50;

void
OpenSell(OpenMessage &m) {     int count = 0;     while(!trade.Sell(m.lot, m.symbol, Bid(m.symbol),             ConvertStopLoss(ORDER_TYPE_SELL, m.symbol),             ConvertTakeProfit(ORDER_TYPE_SELL, m.symbol), m.comment)                 && count < OrderSendRetryPolicy) {         Print(GetLastError());         count++;         Sleep(100);     } }
Документация по MQL5: Торговые функции / OrderSend
Документация по MQL5: Торговые функции / OrderSend
  • www.mql5.com
OrderSend - Торговые функции - Справочник MQL5 - Справочник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Павел Раввич:

Есть функции пересчета стопов из пунктов в цену но иногда она не срабатывает и я получаю ошибку типо: 2022.12.09 13:29:29.347 forexteam-consumer (EURGBP,H1) CTrade::OrderSend: market sell 0.23 USDCAD sl: 0.00050 tp: -0.00150 [invalid stops] Ошибка возникает редко 1 раз на 30 - 40 вызовов, что вызывает еще большее недоумение.

В примере ошибки видно что тейк-профит вообще отрицательный tp: -0.00150 Подскажите из-за чего это может быть, и почему возникает иногда?

Возникает ощущение что в при каких-то обстоятельствах функции  Ask и  Bid или SymbolInfoDouble(symbol, SYMBOL_BID) возвращают 0. Хотя не понятно почему.


Вызов самого торгового вызова выглядит так:


А вы откуда берёте цены Ask и Bid?

Судя по коду из ниоткуда.

У вас есть  в коде , что нибудь похожее на это?

MqlTick tick;
SymbolInfoTick(Symbol(), tick)
 

Вот накидал примерно. (не проверял)

//+------------------------------------------------------------------+
input int TakeProfit = 150;
input int StopLoss = 50;
MqlTick tick;
//+------------------------------------------------------------------+
void OnTick(void)
  {
   if(!IsRefreshRates())
      return;
   trade.Sell(m.lot, m.symbol, Bid(m.symbol),
              ConvertStopLoss(ORDER_TYPE_SELL, m.symbol),
              ConvertTakeProfit(ORDER_TYPE_SELL, m.symbol), m.comment);
  }
//+------------------------------------------------------------------+
double ConvertTakeProfit(ENUM_ORDER_TYPE type, string symbol)
  {
   double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   return (type == ORDER_TYPE_BUY ? IsNormalizePrice(tick.ask + TakeProfit * point) : IsNormalizePrice(tick.bid - TakeProfit * point));
  }
//+------------------------------------------------------------------+
double ConvertStopLoss(ENUM_ORDER_TYPE type, string symbol)
  {
   double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   return (type == ORDER_TYPE_BUY ? IsNormalizePrice(tick.ask - StopLoss * point) : IsNormalizePrice(tick.bid + StopLoss * point));
  }
//+------------------------------------------------------------------+
double IsNormalizePrice(double price)
  {
   double tick_size = 0;
   SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE, tick_size);
   return(NormalizeDouble(MathRound(price / tick_size) * tick_size, _Digits));
  }
//+------------------------------------------------------------------+
bool IsRefreshRates()
  {
   if(SymbolInfoTick(Symbol(), tick))
      if(tick.ask != 0 && tick.bid != 0)
         return(true);
   return(false);
  }
//+------------------------------------------------------------------+
 
Aleksandr Slavskii #:

Вот накидал примерно. (не проверял)

Цену Bid забыл поменять в

trade.Sell(m.lot, m.symbol, Bid(m.symbol)

  вместо Bid(m.symbol)  надо написать   tick.bid

 
Aleksandr Slavskii #:

А вы откуда берёте цены Ask и Bid?

Судя по коду из ниоткуда.

У вас есть  в коде , что нибудь похожее на это?

Получаю из SymbolInfoDouble(symbol, SYMBOL_ASK) и  SymbolInfoDouble(symbol, SYMBOL_BID) по спеке вроде должно работать.



По 

bool IsRefreshRates()

не понял а что данных о котировках может не быть? То есть нет способа гарантированно получить актуальную цену инструмента? 

 
Павел Раввич:

Есть функции пересчета стопов из пунктов в цену но иногда она не срабатывает и я получаю ошибку типо: 2022.12.09 13:29:29.347 forexteam-consumer (EURGBP,H1) CTrade::OrderSend: market sell 0.23 USDCAD sl: 0.00050 tp: -0.00150 [invalid stops] Ошибка возникает редко 1 раз на 30 - 40 вызовов, что вызывает еще большее недоумение.

В примере ошибки видно что тейк-профит вообще отрицательный tp: -0.00150 Подскажите из-за чего это может быть, и почему возникает иногда?

Возникает ощущение что в при каких-то обстоятельствах функции  Ask и  Bid или SymbolInfoDouble(symbol, SYMBOL_BID) возвращают 0. Хотя не понятно почему.

https://www.mql5.com/ru/forum/387558/page2#comment_28471023

Скальпинг в классическом арбитраже - У меня есть реальный счет на MOEX Тики, акция SBER, время желтым выделил.
Скальпинг в классическом арбитраже - У меня есть реальный счет на MOEX Тики, акция SBER, время желтым выделил.
  • 2022.01.27
  • www.mql5.com
есть хоть какой то простенький советник в мт5 для торговли допустим акциями в Открытии или в БКСе. Посмотрите пожалуйста у кого есть реальный счет на MOEX Тики. Сегодня поставил ТС на финальное тестирование на реальных серверах
 
Павел Раввич #:

Получаю из SymbolInfoDouble(symbol, SYMBOL_ASK) и  SymbolInfoDouble(symbol, SYMBOL_BID) по спеке вроде должно работать.

По 

не понял а что данных о котировках может не быть? То есть нет способа гарантированно получить актуальную цену инструмента? 

Можно использовать  SymbolInfoDouble(symbol, SYMBOL_ASK) и  SymbolInfoDouble(symbol, SYMBOL_BID) , как вам удобнее, но нужно проверять. Вы же сами видели, что без проверки у вас тейкпрофит получился отрицательным)

  TakeProfit = 150;    tp: -0.00150   такое может быть если котировка равна нулю.

 
Aleksandr Slavskii #:

Можно использовать  SymbolInfoDouble(symbol, SYMBOL_ASK) и  SymbolInfoDouble(symbol, SYMBOL_BID) , как вам удобнее, но нужно проверять. Вы же сами видели, что без проверки у вас тейкпрофит получился отрицательным)

  TakeProfit = 150;    tp: -0.00150   такое может быть если котировка равна нулю.

Проверить то можно вопрос как выкручиваться если не вышло а сделку открывать все равно надо, остается только в цикле запрашивать на пример так:

int retryAskTick = 0;
double Ask(string symbol) {
    MqlTick tick;
    while(!SymbolInfoTick(symbol, tick) && tick.ask == 0 && retryAskTick < 25) {
        retryAskTick++;
        Sleep(100);
    }
    retryAskTick = 0;
    int digits = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
    return NormalizeDouble(tick.ask, digits);
}

Получается надежного способа все таки нет? Если смотреть на пример выше то и с 25 раза может не сработать... 

 
Павел Раввич #:

Проверить то можно вопрос как выкручиваться если не вышло а сделку открывать все равно надо, остается только в цикле запрашивать на пример так:

Получается надежного способа все таки нет? Если смотреть на пример выше то и с 25 раза может не сработать... 

Ну во первых отсутствие цены бывает не часто, во вторых есть функция OnTick(), которая обрабатывает событие NewTick.

Вполне достаточно дождаться нового тика в  OnTick() и получить свежие цены SymbolInfoTick().

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

 
Да, я у себя тоже тик с нулевыми ask или bid пропускаю.
Причина обращения: