ФОРТС: не происходит модификация отложенных ордеров [Invalid request]

 
Добрый день!
Робот действует по типичному алгоритму: выставляет лимитированные заявки на ФОРСТе (брокер Открытие) на покупку и продажу и модифицирует их, чтобы оставаться всегда лучшим (пока спрэд это позволяет). Модификации ордеров проходят в основном успешно, но пару раз в течении дня возникает ситуация когда какой-нибудь из ордеров (либо сразу два) перестают модифицироваться и вовсе пропадают из стакана, при этом в самом коде вроде как происходят модификации, но сам ордер не модифицируется - постоянно повторяется одна и та же модификация и иногда вылезает ошибка [Invalid request] (лог ниже).

Есть еще момент, после того как ордеры перестали модифицироваться и  пропали из стакана, они остаются во вкладке торговля, и их от туда невозможно удалить, причем даже после перезапуска терминала и компа. Такая вот чертовщина. Может, кто сталкивался с подобным или разработчики чего скажут.
Подскажите, пожалуйста, в чем может быть проблема? 

HP 0 22:01:02.604 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0
PO 0 22:01:02.667 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0 placed for execution in 59 ms
IL 0 22:01:02.968 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0
JK 0 22:01:03.028 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0 placed for execution in 59 ms
GK 2 22:01:03.029 Trades '1007836': failed modify order #20484688 sell limit 1.00  at 23916.00000 sl: 0.00000 tp: 0.00000 -> 23691.00000, sl: 0.00000 tp: 0.00000 [Invalid request]
CQ 0 22:01:03.132 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0
QQ 0 22:01:03.179 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0 placed for execution in 59 ms
EM 0 22:01:03.602 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0
EM 0 22:01:03.665 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0 placed for execution in 59 ms

 
iiivasyaiii:
Добрый день!
Робот действует по типичному алгоритму: выставляет лимитированные заявки на ФОРСТе (брокер Открытие) на покупку и продажу и модифицирует их, чтобы оставаться всегда лучшим (пока спрэд это позволяет). Модификации ордеров проходят в основном успешно, но пару раз в течении дня возникает ситуация когда какой-нибудь из ордеров (либо сразу два) перестают модифицироваться и вовсе пропадают из стакана, при этом в самом коде вроде как происходят модификации, но сам ордер не модифицируется - постоянно повторяется одна и та же модификация и иногда вылезает ошибка [Invalid request] (лог ниже).

Есть еще момент, после того как ордеры перестали модифицироваться и  пропали из стакана, они остаются во вкладке торговля, и их от туда невозможно удалить, причем даже после перезапуска терминала и компа. Такая вот чертовщина. Может, кто сталкивался с подобным или разработчики чего скажут.
Подскажите, пожалуйста, в чем может быть проблема? 

HP 0 22:01:02.604 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0
PO 0 22:01:02.667 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0 placed for execution in 59 ms
IL 0 22:01:02.968 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0
JK 0 22:01:03.028 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0 placed for execution in 59 ms
GK 2 22:01:03.029 Trades '1007836': failed modify order #20484688 sell limit 1.00  at 23916.00000 sl: 0.00000 tp: 0.00000 -> 23691.00000, sl: 0.00000 tp: 0.00000 [Invalid request]
CQ 0 22:01:03.132 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0
QQ 0 22:01:03.179 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23691, sl: 0 tp: 0 placed for execution in 59 ms
EM 0 22:01:03.602 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0
EM 0 22:01:03.665 Trades '1007836': modify order #20484688 sell limit 1.00 LKOH-9.15 at 23916 sl: 0 tp: 0 -> 23697, sl: 0 tp: 0 placed for execution in 59 ms

Добрый день!

Выложите код, как Вы модифицируете ордер.

Чтобы правильно оформить код, нажмите кнопку SRC 

 
Михаил:

Добрый день!

Скорее всего, Вы превышаете лимиты по символу. 

Михаил, спасибо за ответ, но я не совсем понял превышение каких лимитов Вы имели в виду. Лимит по выставлению заявок за определенный промежуток времени? или Превышение в заявке максимального или минимального значения цены за сессию?
 
iiivasyaiii:
Михаил, спасибо за ответ, но я не совсем понял превышение каких лимитов Вы имели в виду. Лимит по выставлению заявок за определенный промежуток времени? или Превышение в заявке максимального или минимального значения цены за сессию?

Да, я не посмотрел, что цена уменьшилась

Выложите код модификации ордера.

У меня это происходит так (ошибок не бывает)

//+------------------------------------------------------------------+
// Modify order                                                      |
//+------------------------------------------------------------------+
bool Modify( const double price, const string a_symbol, const ulong ticket )
{
  if ( ticket > 0 )
  {
    if ( OrderSelect( ticket ) )
    {
      MqlTradeRequest request = {0};
      MqlTradeResult  result  = {0};
   
      request.action    = TRADE_ACTION_MODIFY;
      request.symbol    = a_symbol;
      request.order     = ticket;
      request.price     = price;
      request.type_time = ORDER_TIME_DAY;
  
      if ( OrderSend( request, result ) )
      {
        if ( result.retcode == TRADE_RETCODE_PLACED ) 
        {
          return( true );
        }
        else
        {
          Print( "Modify: Ошибка модификации ордера на сервере! Билет = ", ticket );
        }
      }
      else
      {
        Print( "Modify: Ордер не модифицирован! Билет = ", ticket );
      }
    }
  }
  return( false );
}
 

Правда, до модификации, я ещё проверяю цену на лимиты,

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

bool Modify( const double price, const string a_symbol, const ulong ticket )
{
  if ( ticket > 0 )
  {
    if ( OrderSelect( ticket ) )
    {
      double min_price = SymbolInfoDouble( a_symbol, SYMBOL_SESSION_PRICE_LIMIT_MIN );
      double max_price = SymbolInfoDouble( a_symbol, SYMBOL_SESSION_PRICE_LIMIT_MAX );
    
      if ( ( price <= max_price ) && ( price >= min_price ) )
      {
        MqlTradeRequest request = {0};
        MqlTradeResult  result  = {0};
   
        request.action    = TRADE_ACTION_MODIFY;
        request.symbol    = a_symbol;
        request.order     = ticket;
        request.price     = price;
        request.type_time = ORDER_TIME_DAY;
  
        if ( OrderSend( request, result ) )
        {
          if ( result.retcode == TRADE_RETCODE_PLACED ) 
          {
            return( true );
          }
          else
          {
            Print( "Modify: Ошибка модификации ордера на сервере! Билет = ", ticket );
          }
        }
        else
        {
          Print( "Modify: Ордер не модифицирован! Билет = ", ticket );
        }
      }
    }
  }
  return( false );
}
 
Михаил:

Да, я не посмотрел, что цена уменьшилась

Выложите код модификации ордера 

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

//+--Описание функции модификации отложенного ордера по заданному Инструменту--------------------------------------------------------------------------------------+
bool FuncModifyOrder(string  In,                                  // Требуемый Инструмент.
                     ulong   ticket,                              // Тикет модифицируемого ордера.
                     double  Price,                               // Цена для модификации.
                     double  In_ask,                              // Лучший аск (для целей отчета).
                     double  In_bid,                              // Лучший бид (для целей отчета).
                     string &AccumDealLog)                        // Переменная хранящая лог-записи.
  {
   bool modify=false;
   int    i;                                                      // Счетчик попыток модифицировать сделку для оператора for.
   
   for(i=0; i<5; i++)
      {
      if(i!=0){Sleep(100);}                                       // Если это непервая попытка модифицировать ордер, то выждем паузу.
      
      if(ticket>0)
         {
         if(OrderSelect(ticket))
            {
            if(trade.OrderModify(ticket,NormalizeDouble(Price,(int)SymbolInfoInteger(In1,SYMBOL_DIGITS)),0,0,ORDER_TIME_SPECIFIED_DAY,SymbolInfoInteger(In,SYMBOL_EXPIRATION_TIME)))
           
               {
               if(trade.ResultRetcode()==TRADE_RETCODE_PLACED || trade.ResultRetcode()==TRADE_RETCODE_DONE)
                  {
                  Print("Приказ о модификации размещен на бирже по ордеру №",ticket);
                  modify=true;
                  break;                                          // Затем происходит выход из оператора цикла for.
                  }
                else
                  {
                  Print("Ордер не модифицирован! Код возврата НЕ \"TRADE_RETCODE_PLACED\" и НЕ \"TRADE_RETCODE_DONE\", а ", trade.ResultRetcode()," Ошибка № ",GetLastError()); ResetLastError();
                  }
               }
            else
               {
               Print("Ордер № ",ticket," не модифицирован! Функция OrderSend()=false. "+FuncStatusOrder(ticket)+". Ошибка № ",GetLastError()); ResetLastError();
               }
            }
         else
            {
            Print("Ордер № ",ticket," не выбран. OrderSelect()=false. "+FuncStatusOrder(ticket)+". Ошибка № ",GetLastError()); ResetLastError();
            }
         }
      else
         {
         Print("У ордера нет номера, модификация не выполнена! Ошибка № ",GetLastError()); ResetLastError();
         }  
      }
   
  return(modify);                                                 // Логический вывод результата работы функции.
  }
 
iiivasyaiii:

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

Я настоятельно советую для работы на ФОРТС не использовать стандартную библиотеку.

Возьмите этот код и будет Вам счастье:

bool Modify( const double price, const string a_symbol, const ulong ticket )
{
  if ( ticket > 0 )
  {
    if ( OrderSelect( ticket ) )
    {
      double min_price = SymbolInfoDouble( a_symbol, SYMBOL_SESSION_PRICE_LIMIT_MIN );
      double max_price = SymbolInfoDouble( a_symbol, SYMBOL_SESSION_PRICE_LIMIT_MAX );
    
      if ( ( price <= max_price ) && ( price >= min_price ) )
      {
        MqlTradeRequest request = {0};
        MqlTradeResult  result  = {0};
   
        request.action    = TRADE_ACTION_MODIFY;
        request.symbol    = a_symbol;
        request.order     = ticket;
        request.price     = price;
        request.type_time = ORDER_TIME_DAY;
  
        if ( OrderSend( request, result ) )
        {
          if ( result.retcode == TRADE_RETCODE_PLACED ) 
          {
            return( true );
          }
          else
          {
            Print( "Modify: Ошибка модификации ордера на сервере! Билет = ", ticket );
          }
        }
        else
        {
          Print( "Modify: Ордер не модифицирован! Билет = ", ticket );
        }
      }
    }
  }
  return( false );
}
 
Михаил:

Я настоятельно советую для работы на ФОРТС не использовать стандартную библиотеку.

Возьмите этот код и будет Вам счастье:

Я в стандартную библиотеку пару дней назад полез, думал может она поможет (хотя результат такой же был, что и до библиотеки). А так код кстати был почти такой же как у Вас. Вот только Вы ставите request.type_time = ORDER_TIME_DAY; , а я сделал ORDER_TIME_SPECIFIED_DAY и поставил в поле expiration дату истечения фьюча: SymbolInfoInteger(In,SYMBOL_EXPIRATION_TIME). Может здесь где-то кроется ошибка. Вот как это было раньше (до стандартной библиотеки):

            MqlTradeRequest request = {0};
            MqlTradeResult  result  = {0};
            
            request.action= TRADE_ACTION_MODIFY;
            request.order = ticket;
            request.price = Price;
            request.type_time=    ORDER_TIME_SPECIFIED_DAY;             
            request.expiration=   (datetime)(SymbolInfoInteger(In,SYMBOL_EXPIRATION_TIME)); // Ордер будет находится до дату экспирации фьюча.
            
            if(OrderSend(request,result))
 
iiivasyaiii:

Я в стандартную библиотеку пару дней назад полез, думал может она поможет (хотя результат такой же был, что и до библиотеки). А так код кстати был почти такой же как у Вас. Вот только Вы ставите request.type_time = ORDER_TIME_DAY; , а я сделал ORDER_TIME_SPECIFIED_DAY и поставил в поле expiration дату истечения фьюча: SymbolInfoInteger(In,SYMBOL_EXPIRATION_TIME). Может здесь где-то кроется ошибка. Вот как это было раньше (до стандартной библиотеки):

У меня работает без ошибок.

И ещё...

Не забывайте, что на ФОРТС есть ограничение по кол-ву транзакций = 2000 за полную сессию (т.е от 19-05 до 18-45 следующего дня) 

Модификация ордера = 1 транзакция 

 
Михаил:

У меня работает без ошибок.

И ещё...

Не забывайте, что на ФОРТС есть ограничение по кол-ву тразакций = 2000 за полную сессию (т.е от 19-05 до 18-45 следующего дня) 

Михаил, спасибо большое за советы и код! Попробую Вашу версию, глядишь поправиться всё)

А вот про ограничение транзакций подскажите, пожалуйста, где можно почитать по-подробнее?

"2000 транзакций за сессию" это лимит с одного инвест счета или для каждого инструмента дается по 2000? И если превысить лимит транзакций то, что тогда делать, перезагрузить робота/терминал и дальше можно "колбасить" или ФОРТС больше вообще не даст сделать никаких транзакций в эту сессию? 

 
iiivasyaiii:

Михаил, спасибо большое за советы и код! Попробую Вашу версию, глядишь поправиться всё)

А вот про ограничение транзакций подскажите, пожалуйста, где можно почитать по-подробнее?

"2000 транзакций за сессию" это лимит с одного инвест счета или для каждого инструмента дается по 2000? И если превысить лимит транзакций то, что тогда делать, перезагрузить робота/терминал и дальше можно "колбасить" или ФОРТС больше вообще не даст сделать никаких транзакций в эту сессию? 

2000 с одного физического лица (не важно сколько у этого лица счетов. И по всем инструментам)

Нет, биржа ничего не ограничивает, просто за лишние транзакции берёт денежку (не символическую)... 

Щас поищу файлы с регламентом...  

Файлы:
Причина обращения: