Скачать MetaTrader 5

Удаление отложенных ордеров

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
yuri_zavyalov
106
yuri_zavyalov  

Здравствуйте!

Есть функция удаления всех отложенных ордеров с определенным мэджиком. Вот она:

//+------------------------------------------------------------------+
//| Удаление всех своих отложников                                   |
//+------------------------------------------------------------------+
void delete_all_limit_orders()
{
  uint i, lv_total;
  ulong lv_ticket;
  bool lv_is_here;
  
  lv_is_here = true;
  while (lv_is_here)
  {
    lv_is_here = false;
    lv_total = OrdersTotal();
    for (i = 0; i < lv_total; i++ )
      if ((lv_ticket = OrderGetTicket(i)) > 0)
        if (((OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT) || (OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT)) && (OrderGetInteger(ORDER_MAGIC) == gv_magic))
        {
          lv_is_here = true;
          delete_limit_order(lv_ticket);
          break;
        }
  }
}

//+------------------------------------------------------------------+
//| Удаление отложника                                               |
//+------------------------------------------------------------------+
bool delete_limit_order(ulong p_ticket)
{
  int lv_return;
  MqlTradeRequest ls_trade;
  MqlTradeResult ls_result;
  string lv_error_list, lv_retcode;
  
  ZeroMemory(ls_trade);
  ZeroMemory(ls_result);
  
  ls_trade.action = TRADE_ACTION_REMOVE;
  ls_trade.order = p_ticket;
  lv_error_list = "";
  
  while (!IsStopped())
  {
    lv_return = 2;
    OrderSend(ls_trade, ls_result);
    switch (ls_result.retcode)
    {
      case TRADE_RETCODE_DONE: lv_return = 1; if (gv_logging) Print("order ", ls_result.order, " successfully deleted"); break;
      case TRADE_RETCODE_REQUOTE: lv_return = 2; Sleep(1000); break;
      case TRADE_RETCODE_INVALID_PRICE: lv_return = 2; break;
      case TRADE_RETCODE_INVALID_STOPS: lv_return = 2; Sleep(1000); break;
      case TRADE_RETCODE_PRICE_CHANGED: lv_return = 2; break;
      case TRADE_RETCODE_FROZEN: lv_return = 2; Sleep(1000); break;
      default: lv_return = 2; break;
    }  
    
    lv_retcode = "<";
    StringAdd(lv_retcode, IntegerToString(ls_result.retcode));
    StringAdd(lv_retcode, ">");
    if (lv_return == 1) break;
    if ((lv_return == 2)&&(StringFind(lv_error_list, lv_retcode, 0) == -1))
    {
      StringAdd(lv_error_list, lv_retcode);
      if (gv_logging) Print("error of order ", p_ticket, " delete: ", ls_result.retcode, "; GetLastError() = ", GetLastError(), "; Bid = ", ls_result.bid, "; Ask = ", ls_result.ask, "; Price = ", ls_result.price);
    }
  }
  
  if (lv_return == 1) return (true); else return (false); 
}

 С недавнего времени функция удаления всех отложников перестала работать нормально, происходит зависание (по логике delete_limit_order) на ошибке:

IE      2       Trades  17:17:01        '1041788': failed cancel order #10887830 buy 0.00  at market [Invalid request]

ErrorCode = 10013 (Неправильный запрос); GetLastError() = 4756 (Не удалось отправить торговый запрос)

То есть удаляется ордер, который уже удален. А это значит что после удаления ордера OrderGetTicket возвращает уже удаленный ордер. Такое ощущение, что этот ордер удалился, но терминал почему-то не успел сообразить, что он уже в истории.

Я, конечно, понимаю, что могу поставить проверку на эту ошибку: если есть такая ошибка, то  просто подождать секунду и проверить список ордеров еще раз.

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

Заранее благодарен за любые комментарии. 

yuri_zavyalov
106
yuri_zavyalov  
Ни у кого нет никаких идей, почему такое может происходить?
Victor Kirillin
491
Victor Kirillin  
yuri_zavyalov:
Ни у кого нет никаких идей, почему такое может происходить?

Попробуйте вместо:

    for (i = 0; i < lv_total; i++ )

сделать:

    for(i=lv_total-1;i>=0;i--)

либо:

    for(i=0;i<lv_total;i++)
      if((lv_ticket=OrderGetTicket(0))>0)
yuri_zavyalov
106
yuri_zavyalov  
uncleVic:

Попробуйте вместо:

сделать:

либо:

Спасибо. Первое, что вы рекомендовали, выдает те же самые результаты (ошибка через некоторое время). А второе мне не подходит, потому что у меня анализируются мэджики, которые например у нулевого элемента может и не быть, да и зачем тогда в таком случае вообще по списку ордеров бегать, если все равно мы каждый раз анализуем нулевой элемент (OrderGetTicket(0)). В общем, попробую отписаться в Сервис-деск, возможно там мне разработчики что-то прокомментируют.

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий