Invalid expiration в отложенных ордерах. Как правильно выставлять?

 
Салют! Есть код, который должен выставлять отложки сразу после открытия рыночных ордеров (например, цена для ордеров типа селл_стоп чуть ниже стопов рыночных баев):
bool SendPending(ENUM_ORDER_TYPE orderType, double price) {
   bool b = false;
   MqlTradeRequest request = {0};
   MqlTradeResult  result = {0};
   request.action   = TRADE_ACTION_PENDING;       // тип торговой операции
   request.symbol   = Symbol();                   // символ
   request.price    = NormalizeDouble(price,_Digits);                      // цена для открытия
   request.type     = orderType;                  // тип ордера
   request.type_filling = ORDER_FILLING_IOC;
   request.type_time = ORDER_TIME_SPECIFIED;
   request.expiration = (datetime)(Time(0) + PendingOrderLifetimeBars*PeriodSeconds(PERIOD_CURRENT));
   Print("EXPIRATION: "+TimeToString(request.expiration));
   if(!AutoSl)
      request.sl    = (orderType == ORDER_TYPE_SELL_STOP ? NormalizeDouble(price + StopLoss, _Digits) : NormalizeDouble(price - StopLoss, _Digits)) ;
   else
      request.sl    = (orderType == ORDER_TYPE_SELL_STOP ? NormalizeDouble(channelHigherBorder + AddSl, _Digits) : NormalizeDouble(channelLowerBorder - AddSl, _Digits));

   if(MathAbs(request.price-request.sl)>MaxStop) {
      Print("Слишком (SendPending) большой стоп!");
      return true; // если стоп больше максимально допустимого, не открываем
   }
   request.tp       = (orderType == ORDER_TYPE_SELL_STOP ? NormalizeDouble(price - TakeProfit, _Digits):NormalizeDouble(price + TakeProfit, _Digits));
   request.deviation = Slipp;                                   // допустимое отклонение от цены
   request.magic    = Magic;
   request.volume   = lot(request.sl,request.price,request.type);
   if(request.volume == 0) {
      Print("Cant calculate volume SELL! Volume is 0");
      return false;
   }
   if(!OrderSend(request, result)) {
      PrintFormat("SendPending error %d", GetLastError());
      ExpertRemove();
   } else {
      b = true;
   }
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u", result.retcode, result.deal, result.order);
   return b;
}

Но не выставляет. Пишет постоянно ошибку:

2020.08.23 19:26:03.317 2020.08.04 10:00:00   failed sell stop 2 RTS-9.20 at 125450 (125450) sl: 126320 tp: 120450 [Invalid expiration]
2020.08.23 19:26:03.317 2020.08.04 10:00:00   SendPending error 4756
2020.08.23 19:26:03.317 2020.08.04 10:00:00   ExpertRemove() function called
2020.08.23 19:26:03.317 2020.08.04 10:00:00   retcode=10022  deal=0  order=0

Хотя дата истечения вроде норм:

2020.08.23 19:26:03.317 2020.08.04 10:00:00   EXPIRATION: 2020.08.04 10:25


Пробовал так же просто проверить пример из справочника - не получилось. Так же все время писало Invalid expiration... Подскажите, с чем это может быть связано и как корректно выставлять их?

 
Yevhenii Levchenko:
Салют! Есть код, который должен выставлять отложки сразу после открытия рыночных ордеров (например, цена для ордеров типа селл_стоп чуть ниже стопов рыночных баев):

Но не выставляет. Пишет постоянно ошибку:

Хотя дата истечения вроде норм:


Пробовал так же просто проверить пример из справочника - не получилось. Так же все время писало Invalid expiration... Подскажите, с чем это может быть связано и как корректно выставлять их?

Открывашка не даёт выставлять ордера с экспирацией. Можно-ли модификацией назначить не проверял. Буду рад если вы проверите и сообщите результат.

 
Alexey Viktorov:

Открывашка не даёт выставлять ордера с экспирацией. Можно-ли модификацией назначить не проверял. Буду рад если вы проверите и сообщите результат.

Дело в том, что вообще никакой не могу выставить. Даже скопированный пример со справочника почему-то не хочет - постоянно пишет Invalid expiration :(

 
Yevhenii Levchenko:

Дело в том, что вообще никакой не могу выставить. Даже скопированный пример со справочника почему-то не хочет - постоянно пишет Invalid expiration :(

Я об этом и говорю. Попробуйте поставить без экспирации, а потом модифицировать установив экспирацию. Когда я с этим столкнулся, заказчик сказал что лучше пусть советник удаляет отложки в указанное время. Если нет связи и отложка не удалилась, не моя вина. На том я и закончил. Проверять версию модификации не стал.

 
Alexey Viktorov:

Я об этом и говорю. Попробуйте поставить без экспирации, а потом модифицировать установив экспирацию. Когда я с этим столкнулся, заказчик сказал что лучше пусть советник удаляет отложки в указанное время. Если нет связи и отложка не удалилась, не моя вина. На том я и закончил. Проверять версию модификации не стал.

Без экспирации тож не хочет - постоянно пишет Invalid expiration.

Убирал полностью все , что по экспирации. Так же менял ORDER_TIME_SPECIFIED на ORDER_TIME_GTC.  Потом просто пример выставления отложки (без экспирации) со справочника брал - постоянно выскакивает Invalid expiration:

2020.08.23 20:21:19.652 2020.08.04 10:00:00   failed sell stop 1 RTS-9.20 at 125450 [Invalid expiration]
 
Yevhenii Levchenko:
Салют! Есть код, который должен выставлять отложки сразу после открытия рыночных ордеров (например, цена для ордеров типа селл_стоп чуть ниже стопов рыночных баев):

Но не выставляет. Пишет постоянно ошибку:

Хотя дата истечения вроде норм:


Пробовал так же просто проверить пример из справочника - не получилось. Так же все время писало Invalid expiration... Подскажите, с чем это может быть связано и как корректно выставлять их?

ORDER_TYPE_SELL_STOP - это не отложенный ордер, этот тип ордера хранится на сервере МТ5, а не ставится в стакан
MqlTradeRequest request = {0};
  MqlTradeResult  result  = {0};
 
//--- Fill structure
  request.action = TRADE_ACTION_PENDING;
  request.magic  = mem_magic;
  request.symbol = a_symbol;
  request.volume = volume;
  request.price  = price;
  if(buy_sell)
  {
    request.type = ORDER_TYPE_BUY_LIMIT;
  }
  else
  {
    request.type = ORDER_TYPE_SELL_LIMIT;
  } 
  request.comment = "Отложенный ордер...";      
  request.type_filling = ORDER_FILLING_RETURN;
  request.type_time = ORDER_TIME_DAY;

Добавлено

Прежде чем выставлять режимы, нужно проверить поддерживает ли эти режимы Броекр

bool CheckMarketParam(const string a_symbol)
{
//--- Check real accaunt
  ENUM_ACCOUNT_TRADE_MODE acc_trade_mode = ENUM_ACCOUNT_TRADE_MODE(AccountInfoInteger(ACCOUNT_TRADE_MODE));
#ifdef DEBUG
  if(acc_trade_mode != ACCOUNT_TRADE_MODE_DEMO)
  {
    MessageBox("Эксперт запущен не на демо-счёте!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
#else
  if(acc_trade_mode != ACCOUNT_TRADE_MODE_REAL)
  {
    MessageBox("Эксперт запущен не на реальном счёте!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
#endif  
//--- Check margine mode
  ENUM_ACCOUNT_MARGIN_MODE margin_mode = ENUM_ACCOUNT_MARGIN_MODE(AccountInfoInteger(ACCOUNT_MARGIN_MODE));
  if(margin_mode != ACCOUNT_MARGIN_MODE_RETAIL_NETTING)
  {
    MessageBox("Брокер не поддерживает биржевой расчёт маржи в режиме 'Неттинг'!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
//--- Check symbol calc mode 
  ENUM_SYMBOL_CALC_MODE calc_mode = ENUM_SYMBOL_CALC_MODE(SymbolInfoInteger(a_symbol, SYMBOL_TRADE_CALC_MODE));
  
  if((calc_mode != SYMBOL_CALC_MODE_EXCH_FUTURES_FORTS) && (calc_mode != SYMBOL_CALC_MODE_EXCH_OPTIONS_MARGIN))
  {
    MessageBox("Символ " + a_symbol + " не поддерживает расчёт фьючерсов для FORTS!", "Ошибка", MB_OK | MB_ICONHAND);
    Print("Текуший расчёт: ", EnumToString(calc_mode));
    return( false );
  } 
//--- Check for full mode
  ENUM_SYMBOL_TRADE_MODE trade_mode = ENUM_SYMBOL_TRADE_MODE(SymbolInfoInteger(a_symbol, SYMBOL_TRADE_MODE));
  
  if(trade_mode != SYMBOL_TRADE_MODE_FULL)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает полную торговлю!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
//--- Check trade execution mode
  ENUM_SYMBOL_TRADE_EXECUTION market_info = ENUM_SYMBOL_TRADE_EXECUTION( SymbolInfoInteger(a_symbol, SYMBOL_TRADE_EXEMODE));
    
  if((market_info & SYMBOL_TRADE_EXECUTION_EXCHANGE) != SYMBOL_TRADE_EXECUTION_EXCHANGE)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает TRADE EXECUTION EXCHANGE режим!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
//--- Check orders mode
  int order_mode = int(SymbolInfoInteger(a_symbol, SYMBOL_ORDER_MODE));
  
  if((SYMBOL_ORDER_MARKET & order_mode) != SYMBOL_ORDER_MARKET)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает Market Execution режим установки ордеров!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
  
  if((SYMBOL_ORDER_LIMIT & order_mode) != SYMBOL_ORDER_LIMIT)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает Limit режим установки ордеров!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
  
  if((SYMBOL_ORDER_STOP_LIMIT & order_mode) != SYMBOL_ORDER_STOP_LIMIT)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает Stop Limit режим установки ордеров!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
  
  if((SYMBOL_ORDER_STOP & order_mode) != SYMBOL_ORDER_STOP)
  {
    MessageBox( "Символ " + a_symbol + " не поддерживает Stop режим установки ордеров!", "Ошибка", MB_OK | MB_ICONHAND );
    return(false);
  }
  
  if((SYMBOL_ORDER_SL & order_mode) != SYMBOL_ORDER_SL)
  {
    MessageBox( "Символ " + a_symbol + " не поддерживает Stop Loss режим установки ордеров!", "Ошибка", MB_OK | MB_ICONHAND );
    return(false);
  }
  
  if((SYMBOL_ORDER_TP & order_mode) != SYMBOL_ORDER_TP)
  {
    MessageBox( "Символ " + a_symbol + " не поддерживает Take Profit режим установки ордеров!", "Ошибка", MB_OK | MB_ICONHAND );
    return(false);
  }
//---Filing mode
  int filling_mode = int(SymbolInfoInteger(a_symbol, SYMBOL_FILLING_MODE));
  
  if((SYMBOL_FILLING_IOC & filling_mode) != SYMBOL_FILLING_IOC)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает filling IOC режим исполнения ордеров!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
  
  if((SYMBOL_FILLING_FOK & filling_mode) != SYMBOL_FILLING_FOK)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает filling FOK режим исполнения ордеров!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
//---Ckeck expiration
  int symbol_exp_type = int( SymbolInfoInteger(a_symbol, SYMBOL_EXPIRATION_MODE));
//---  
  if((symbol_exp_type & SYMBOL_EXPIRATION_DAY) != SYMBOL_EXPIRATION_DAY)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает экспирацию DAY!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
  if((symbol_exp_type & SYMBOL_EXPIRATION_SPECIFIED_DAY) != SYMBOL_EXPIRATION_SPECIFIED_DAY)
  {
    MessageBox("Символ " + a_symbol + " не поддерживает экспирацию SPECIFIED DAY!", "Ошибка", MB_OK | MB_ICONHAND);
    return(false);
  }
  return(true);
}
 
Alexey Viktorov:

Открывашка не даёт выставлять ордера с экспирацией. Можно-ли модификацией назначить не проверял. Буду рад если вы проверите и сообщите результат.

Можно! После выставления отложки используйте те же request и result:  берете тикет с result, меняете action, type_time и прописываете экспирацию:

   ResetLastError();
   if(!OrderSend(request, result)) {
      PrintFormat("SendPending error %d", GetLastError());
      //ExpertRemove();
   } else {
      request.action=TRADE_ACTION_MODIFY; 
      request.order = result.order; 
      request.type_time = ORDER_TIME_SPECIFIED;
      request.expiration = (datetime)(Time(0) + PendingOrderLifetimeBars*PeriodSeconds(PERIOD_CURRENT));
      Print("EXPIRATION: "+TimeToString(request.expiration));
      ResetLastError();
      if(!OrderSend(request, result)) {
         PrintFormat("Modify Pending error %d", GetLastError());
        // ExpertRemove();
      }
      b = true;
   }

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

prostotrader:

Добавлено

Прежде чем выставлять режимы, нужно проверить поддерживает ли эти режимы Броекр

Спасибо!

Мне нужно что-то типа Sell stop и Buy stop, как в мт4... Делаю через ORDER_TYPE_SELL_STOP_LIMIT и ORDER_TYPE_BUY_STOP_LIMIT, но оно как-то коряво работает - при сильной движухе ордер не исполняется...

ORDER_TYPE_SELL_STOP - это не отложенный ордер, этот тип ордера хранится на сервере МТ5, а не ставится в стакан

Это типа нельзя его использовать? В мт5 есть аналог отложек Sell stop и Buy stop ?

 
Yevhenii Levchenko:

Можно!

Спасибо, одного этого слова мне достаточно.))) Всё остальное я знаю как сделать.

 
Alexey Viktorov:

Спасибо, одного этого слова мне достаточно.))) Всё остальное я знаю как сделать.

Ничего страшного)

 
Yevhenii Levchenko:
Салют! Есть код, который должен выставлять отложки сразу после открытия рыночных ордеров (например, цена для ордеров типа селл_стоп чуть ниже стопов рыночных баев):

Но не выставляет. Пишет постоянно ошибку:

Хотя дата истечения вроде норм:


Пробовал так же просто проверить пример из справочника - не получилось. Так же все время писало Invalid expiration... Подскажите, с чем это может быть связано и как корректно выставлять их?

Не менее 11 минут время жизни должно быть. Если менее ордер не выставляется.
 
Valeriy Yastremskiy:
Не менее 11 минут время жизни должно быть. Если менее ордер не выставляется.

Не пробовал так близко. Но плохо, раз такое есть... Спасибо!