Разработчики! Ошибка 10024 (Слишком частые запросы) - страница 4

 
Renat:
Кроме терминала есть очень много этапов, на которых принимаются решения. А терминал лишь указывает финальное время получения подтверждений с той стороны.

Ренат.

Я участник форума Московской биржи.

Я задавал вопрос по поводу задержек исполнения приказов

по Plaza II.

НИ У КОГО не наблюдаются.

Более того, нет ни одного сообщения о задержках.

А скальперы подняли бы такой вой, если бы они были.

Я думаю, что вам нужно искать причину в связке терминал МТ-5 <--> сервер МТ-5 

Кстати, до лета 2013 года, их не было. 

Посмотрите на картинку:

 

Задержки наблюдаются, когда над одним инструментом происходят частые операции. 

 
Mikalas:

Попробуйте из терминала устанавливать, модифицировать и удалять ордера "руками".

Но только не один раз, а много 2-3 минуты. 

И вы увидите что вызывает задержки. 

Может это просто  настройка сервера МТ5 брокером такая.  -" после Х минут гиперактивности "скорострела",  придерживать его операции на N мс, а то вообще охренел".
 
Renat:
По вопросу о частых сделках на асинхронных запросах мы завершили проверки. Извините за задержки, так как все были сконцентрированы на выпуске MT4 билдов.

Оказалось, что со стороны терминала или сервера ошибок нет. Дело в том, что у нас буфер подтверждения/ожидания на 16 ожидающих транзакций, которые вы полностью использовали и вследствие достаточно большого пинга(50-70 мс) до торгового сервера (+ исполнение/регистрация на бирже) не успевали получать ответы. Поэтому сразу идущие следующие транзакции были отклонены как частые.

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

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

В официальном билде 1010 мы увеличили буфер ожидающих подтверждения транзакций до 64, что дает возможность проводить массовые асинхронные транзакции даже при больших сетевых задержках. Обновитесь на эту версию, подключившись к MetaQuotes-Demo, если ваш брокер еще не обновился сам.

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

К сожалению не удалось избежать ошибок при массовой отправке ордеров.

Брутфорс метод:

//+------------------------------------------------------------------+
//|                                               Send5000Orders.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"

int OrdersLimit = 200;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
   int ordersCount = 0;
   bool marketWatchOnly = true;
   MqlTradeRequest request = {0};
   FilingRequest(request);
   MqlTradeResult result = {0};
   uint tiks = GetTickCount();
   while(true)
   {
      for(int symbolIndex = 0; symbolIndex < SymbolsTotal(marketWatchOnly); symbolIndex++)
      {
         string symbolName = SymbolName(symbolIndex, marketWatchOnly);
         request.symbol = symbolName;
         GetRandomBuyOrSell(request);
         if(OrderSendAsync(request, result))
            ordersCount++;
         else if(result.retcode == 10024)
            Sleep(20);
         else
            printf("Error Send order. Reason: " + (string)result.retcode);
         if(ordersCount >= OrdersLimit)
         {
            uint delta = GetTickCount() - tiks;
            printf("Complete task. Time: " + (string)delta + " msc.");
            return;
         }
      }
   }
}
void OnTimer()
{

}

void FilingRequest(MqlTradeRequest& request)
{
   request.magic=12345;
   request.symbol = Symbol();
   request.volume = 0.1;
   request.type=ORDER_TYPE_BUY;
   request.comment="open order";
   request.action = TRADE_ACTION_DEAL;
   request.type_filling=ORDER_FILLING_FOK;
}

//+------------------------------------------------------------------+
//| Get random buy or sell order.                                    |
//+------------------------------------------------------------------+
void GetRandomBuyOrSell(MqlTradeRequest& m_request)
{
   ENUM_ORDER_TYPE type = MathRand()%2 == 0 ? ORDER_TYPE_BUY:
                                              ORDER_TYPE_SELL;
   m_request.type = type;
   if(type == ORDER_TYPE_BUY)
      m_request.price = SymbolInfoDouble(m_request.symbol, SYMBOL_ASK);
   else
      m_request.price = SymbolInfoDouble(m_request.symbol, SYMBOL_BID);
   m_request.deviation = 40;
}

При попытки открыть 200 ордеров Выдает ошибки на MQ-Demo: Неправильная цена в запросе, Торговля запрещена, Слишком частые запросы. Засыпание не помогает.

Попытка рассчитать свободные слоты в буфере транзакций:

//+------------------------------------------------------------------+
//|                                                SendAsyncTest.mq5 |
//|                        Copyright 2013, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"

int OrdersTotalNeed = 200;            // Number of placed orders.
int SlotsTotal = 64;                // Slots total in transactions buffer.
int SlotCurrent = 0;                // Index of current slot.
int CountOrders = 0;                // Count of send orders.
uint Tiks = 0;                      // Begin time in msc.
datetime TimeBegin = 0;
bool MarketWatchOnly = true;        // True if show and work only MarketWatch symbols, otherwise false.
int SymbolIndex = 0;                // Current symbol index.
int CurrentOrdersTotal = 0;         // Current orders total.
MqlTradeRequest request = {0};      // Trade request.
MqlTradeResult result = {0};        // Trade result.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetMillisecondTimer(5);  //Extrime refresh rate!
   CurrentOrdersTotal = HistoryOrdersTotal();
   FilingRequest(request);
   TimeBegin = TimeCurrent();
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();
      
  }

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   while(SlotCurrent < SlotsTotal && SlotsTotal <= OrdersTotalNeed)
   {
      for(; SymbolIndex < SymbolsTotal(MarketWatchOnly) && SlotCurrent < SlotsTotal; SymbolIndex++)
      {
         string symbolName = SymbolName(SymbolIndex, MarketWatchOnly);
         request.symbol = symbolName;
         GetRandomBuyOrSell(request);
         if(OrderSendAsync(request, result))
            SlotCurrent++;
         else
            printf("Error Send order. Reason: " + (string)result.retcode);
      }
      if(SymbolIndex == SymbolsTotal(MarketWatchOnly))SymbolIndex = 0;
   }
  }
//+------------------------------------------------------------------+
//| TradeTransaction function (not work)                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& m_request,
                        const MqlTradeResult& m_result)
  {
//---
   // If the request was completed successfully - 1 slot is freed. 
   switch(m_result.retcode)
   {
      case 10008:
      case 10009:
      case 10010:
         SlotsTotal++;
   }
  }
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| Trade function (not work)                                        |
//+------------------------------------------------------------------+
/*void OnTrade()
{
   SlotsTotal++;
}*/

//+------------------------------------------------------------------+
//| Filing request for exchange execution.                           |
//+------------------------------------------------------------------+
void FilingRequest(MqlTradeRequest& m_request)
{
   request.magic=12345;
   request.symbol = Symbol();
   request.volume = 0.1;
   request.type=ORDER_TYPE_BUY;
   request.comment="open order";
   request.action = TRADE_ACTION_DEAL;
   request.type_filling=ORDER_FILLING_FOK;
}

//+------------------------------------------------------------------+
//| Get random buy or sell order.                                    |
//+------------------------------------------------------------------+
void GetRandomBuyOrSell(MqlTradeRequest& m_request)
{
   ENUM_ORDER_TYPE type = MathRand()%2 == 0 ? ORDER_TYPE_BUY:
                                              ORDER_TYPE_SELL;
   m_request.type = type;
   if(type == ORDER_TYPE_BUY)
      m_request.price = SymbolInfoDouble(request.symbol, SYMBOL_ASK);
   else
      m_request.price = SymbolInfoDouble(request.symbol, SYMBOL_BID);
   m_request.deviation = 40;
}

int CountNewOrders()
{
   HistorySelect(TimeBegin, TimeCurrent());
   return HistoryOrdersTotal();
}

 Видно что метод более интеллектуальный и построен без задержек Sleep. Получив ответ от сервера в OnTradeTransaction или OnTrade увеличиваем количество свободных слотов на единицу. Однако как и в первом случае "Слишком частые запросы", а количество ответов не дотягивает до общего количества выставляемых ордеров. 

При попытке установить SlotsTotal = 64, ошибка 10024 выскакивает уже на 60 итерации цикла for:

void OnTimer()
  {
//---
   while(SlotCurrent < SlotsTotal && SlotsTotal <= OrdersTotalNeed)
   {
      for(; SymbolIndex < SymbolsTotal(MarketWatchOnly) && SlotCurrent < SlotsTotal; SymbolIndex++)
      {
         string symbolName = SymbolName(SymbolIndex, MarketWatchOnly);
         request.symbol = symbolName;
         GetRandomBuyOrSell(request);
         if(OrderSendAsync(request, result))
            SlotCurrent++;
         // Здесь при SlotCurrent = 60 будет ошибка - 10024
         else
            printf("Error Send order. Reason: " + (string)result.retcode);
      }
      if(SymbolIndex == SymbolsTotal(MarketWatchOnly))SymbolIndex = 0;
   }
  }

... чего по идее быть не должно, ведь буфер еще не заполнен.

В общем, пока не совсем не понятно как избежать ошибок и узнать причину отказа в обслуживании.

 

p/s/ Тестировал массовые запросы на сервере AdmialMarkets. Через некоторое время терминал перестал соединятся с сервером. Пинг есть, а связь пропала. Вот и думаю, может забанили меня?

 

 
C-4:

К сожалению не удалось избежать ошибок при массовой отправке ордеров.

Брутфорс метод:


В общем, пока не совсем не понятно как избежать ошибок и узнать причину отказа в обслуживании.

Прочтите еще раз внимательно:

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


Кроме того:

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

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

 
C-4:

p/s/ Тестировал массовые запросы на сервере AdmialMarkets. Через некоторое время терминал перестал соединятся с сервером. Пинг есть, а связь пропала. Вот и думаю, может забанили меня?

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

Но вообще наивность на фоне деструктивного поведения поражает. Мир - не тупая железка, он реагирует и защищается.

 
Renat:

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

Но вообще наивность на фоне деструктивного поведения поражает. Мир - не тупая железка, он реагирует и защищается.

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

Попробую изложить по порядку. Во втором примере в цикле for делается попытка 64 раза отправить торговый запрос через OrderSendAsync. 64 - потому что буфер вмешает 64 транзакции. Прерывать цикл for и ожидать ответа от сервера, как я понимаю, не нужно, ведь лимит не исчерпан, однако в примере выскакивает ошибка при попытке отправить транзакцию №60: слишком частые запросы:

2014.11.07 14:40:31.264 SendAsyncTest (AUDCAD,H1)       ExpertRemove() function called
2014.11.07 14:40:31.264 SendAsyncTest (AUDCAD,H1)       Error Send order. Reason: 10024
2014.11.07 14:40:27.222 Experts AutoTrading is enabled

 Вот часть кода, которая вызывает это сообщение:

 

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   while(SlotCurrent < SlotsTotal && SlotsTotal <= OrdersTotalNeed)
   {
      for(; SymbolIndex < SymbolsTotal(MarketWatchOnly) && SlotCurrent < SlotsTotal; SymbolIndex++)
      {
         string symbolName = SymbolName(SymbolIndex, MarketWatchOnly);
         request.symbol = symbolName;
         GetRandomBuyOrSell(request);
         if(OrderSendAsync(request, result))
            SlotCurrent++;
         else
         {
            printf("Error Send order. Reason: " + (string)result.retcode);
            ExpertRemove();
            return;
         }
      }
      if(SymbolIndex == SymbolsTotal(MarketWatchOnly))SymbolIndex = 0;
   }
  }

 Внизу прикрепляю логи. Там тоже самое. Вот часть лога:

JE      0       14:40:27.222    Experts AutoTrading is enabled
CJ      0       14:40:28.838    Experts expert SendAsyncTest (AUDCAD,H1) loaded successfully
HH      0       14:40:31.214    Trades  '10052699': exchange sell 0.10 AUDCAD at market
FR      0       14:40:31.215    Trades  '10052699': exchange sell 0.10 AUDCHF at market
MK      0       14:40:31.216    Trades  '10052699': exchange sell 0.10 AUDJPY at market
NM      0       14:40:31.218    Trades  '10052699': exchange sell 0.10 AUDNZD at market
IK      0       14:40:31.219    Trades  '10052699': exchange buy 0.10 AUDSGD at market
PQ      0       14:40:31.221    Trades  '10052699': exchange buy 0.10 AUDUSD at market
DQ      0       14:40:31.222    Trades  '10052699': exchange sell 0.10 CADCHF at market
EG      0       14:40:31.223    Trades  '10052699': exchange buy 0.10 CADJPY at market
HS      0       14:40:31.225    Trades  '10052699': exchange sell 0.10 CHFJPY at market
FD      0       14:40:31.226    Trades  '10052699': exchange buy 0.10 CHFPLN at market
FM      0       14:40:31.227    Trades  '10052699': exchange sell 0.10 EURUSD at market
QI      0       14:40:31.229    Trades  '10052699': exchange buy 0.10 GBPUSD at market
EQ      0       14:40:31.230    Trades  '10052699': exchange buy 0.10 USDJPY at market
FN      0       14:40:31.232    Trades  '10052699': exchange buy 0.10 USDCAD at market
MG      0       14:40:31.233    Trades  '10052699': exchange buy 0.10 XAUUSD at market
DS      0       14:40:31.234    Trades  '10052699': exchange sell 0.10 EURCAD at market
GK      0       14:40:31.236    Trades  '10052699': exchange sell 0.10 EURGBP at market
IR      0       14:40:31.237    Trades  '10052699': exchange buy 0.10 USDPLN at market
HH      0       14:40:31.239    Trades  '10052699': exchange buy 0.10 USDCHF at market
KO      0       14:40:31.240    Trades  '10052699': exchange sell 0.10 USDSGD at market
PO      0       14:40:31.241    Trades  '10052699': exchange buy 0.10 NZDUSD at market
LF      0       14:40:31.243    Trades  '10052699': exchange buy 0.10 AUDCAD at market
OR      0       14:40:31.243    Trades  '10052699': exchange sell 0.10 AUDCHF at market
LD      0       14:40:31.244    Trades  '10052699': exchange sell 0.10 AUDJPY at market
QL      0       14:40:31.244    Trades  '10052699': exchange sell 0.10 AUDNZD at market
FG      0       14:40:31.245    Trades  '10052699': exchange sell 0.10 AUDSGD at market
PP      0       14:40:31.245    Trades  '10052699': exchange buy 0.10 AUDUSD at market
HN      0       14:40:31.246    Trades  '10052699': exchange buy 0.10 CADCHF at market
OK      0       14:40:31.247    Trades  '10052699': exchange sell 0.10 CADJPY at market
NM      0       14:40:31.247    Trades  '10052699': exchange buy 0.10 CHFJPY at market
RD      0       14:40:31.248    Trades  '10052699': exchange sell 0.10 CHFPLN at market
OL      0       14:40:31.248    Trades  '10052699': exchange sell 0.10 EURUSD at market
QF      0       14:40:31.249    Trades  '10052699': exchange sell 0.10 GBPUSD at market
OF      0       14:40:31.249    Trades  '10052699': exchange buy 0.10 USDJPY at market
RP      0       14:40:31.250    Trades  '10052699': exchange sell 0.10 USDCAD at market
KK      0       14:40:31.251    Trades  '10052699': exchange sell 0.10 XAUUSD at market
QM      0       14:40:31.251    Trades  '10052699': exchange buy 0.10 EURCAD at market
OK      0       14:40:31.252    Trades  '10052699': exchange buy 0.10 EURGBP at market
PN      0       14:40:31.252    Trades  '10052699': exchange sell 0.10 USDPLN at market
RI      0       14:40:31.253    Trades  '10052699': exchange buy 0.10 USDCHF at market
KH      0       14:40:31.253    Trades  '10052699': exchange sell 0.10 USDSGD at market
FQ      0       14:40:31.254    Trades  '10052699': exchange sell 0.10 NZDUSD at market
NE      0       14:40:31.254    Trades  '10052699': exchange buy 0.10 AUDCAD at market
RS      0       14:40:31.255    Trades  '10052699': exchange buy 0.10 AUDCHF at market
KE      0       14:40:31.256    Trades  '10052699': exchange sell 0.10 AUDJPY at market
JP      0       14:40:31.256    Trades  '10052699': exchange buy 0.10 AUDNZD at market
KI      0       14:40:31.257    Trades  '10052699': exchange buy 0.10 AUDSGD at market
CH      0       14:40:31.257    Trades  '10052699': exchange sell 0.10 AUDUSD at market
MO      0       14:40:31.258    Trades  '10052699': exchange buy 0.10 CADCHF at market
ME      0       14:40:31.258    Trades  '10052699': exchange buy 0.10 CADJPY at market
MM      0       14:40:31.259    Trades  '10052699': exchange sell 0.10 CHFJPY at market
RE      0       14:40:31.259    Trades  '10052699': exchange sell 0.10 CHFPLN at market
IO      0       14:40:31.260    Trades  '10052699': exchange sell 0.10 EURUSD at market
GG      0       14:40:31.261    Trades  '10052699': exchange sell 0.10 GBPUSD at market
IG      0       14:40:31.261    Trades  '10052699': exchange buy 0.10 USDJPY at market
IL      0       14:40:31.262    Trades  '10052699': exchange buy 0.10 USDCAD at market
QE      0       14:40:31.262    Trades  '10052699': exchange buy 0.10 XAUUSD at market
FM      0       14:40:31.263    Trades  '10052699': exchange sell 0.10 EURCAD at market
OJ      0       14:40:31.263    Trades  '10052699': exchange buy 0.10 EURGBP at market
QQ      0       14:40:31.264    Trades  '10052699': exchange buy 0.10 USDPLN at market
IP      0       14:40:31.269    Experts expert SendAsyncTest (AUDCAD,H1) removed
LG      0       14:40:31.282    Trades  '10052699': order #1010796099 sell 0.10 / 0.10 AUDCAD at 0.98261 done in 68 ms
JR      0       14:40:31.282    Trades  '10052699': order #1010796100 sell 0.10 / 0.10 AUDCHF at 0.83512 done in 67 ms
GN      0       14:40:31.283    Trades  '10052699': order #1010796101 sell 0.10 / 0.10 AUDJPY at 99.016 done in 66 ms
PE      0       14:40:31.283    Trades  '10052699': deal #1009458559 sell 0.10 AUDCAD at 0.98261 done (based on order #1010796099)
QD      0       14:40:31.283    Trades  '10052699': deal #1009458560 sell 0.10 AUDCHF at 0.83512 done (based on order #1010796100)
OD      0       14:40:31.283    Trades  '10052699': deal #1009458561 sell 0.10 AUDJPY at 99.016 done (based on order #1010796101)
EE      0       14:40:31.316    Trades  '10052699': order #1010796102 sell 0.10 / 0.10 AUDNZD at 1.11697 done in 98 ms
IK      0       14:40:31.316    Trades  '10052699': deal #1009458562 sell 0.10 AUDNZD at 1.11697 done (based on order #1010796102)
LN      0       14:40:31.316    Trades  '10052699': order #1010796103 buy 0.10 / 0.10 AUDSGD at 1.11393 done in 97 ms
DP      0       14:40:31.316    Trades  '10052699': deal #1009458563 buy 0.10 AUDSGD at 1.11393 done (based on order #1010796103)

 Между двумя маркерами было отправлено как раз 60 транзакций. Если бы ошибка была вызвана на 65 итерации цикла она была бы мне понятна - превышен размер буфера, но почему ошибка выскакивает на 60?

 З.Ы. с торговым сервером разобрался. Сервера похоже перезагружались. Сейчас подключился нормально.

p.s.s.  Наверное еще надо учитывать время между первым и последним запросом. Но тогда сколько времени ждать? Это секретная информация?

Файлы:
20141107_1.txt  19 kb
 
C-4:


Между двумя маркерами было отправлено как раз 60 транзакций. Если бы ошибка была вызвана на 65 итерации цикла она была бы мне понятна - превышен размер буфера, но почему ошибка выскакивает на 60?

Мы резервируем 4 транзакции из буфера на 64 записи для ручных операций и сигналов.

Иначе может получиться, что эксперты могут полностью заблокировать ручную/сигнал торговлю, когда ожидают на долгом исполнении своих заявок.

 
Renat:

Мы резервируем 4 транзакции из буфера на 64 записи для ручных операций и сигналов.

Иначе может получиться, что эксперты могут полностью заблокировать ручную/сигнал торговлю, когда ожидают на долгом исполнении своих заявок.

Спасибо за ответ. Все стало на свои места. Еще пару вопросов:

1. Как не выйти за пределы буфера и контролировать оставшийся его размер при асинхронной отправке? Я пробовал считать аналитически через OnTradeTransaction: выставляем 64 60 транзакций и ждем срабатывания первого ордера в OnTradeTransaction. Когда он срабатывает увеличиваем размер буфера на единицу. Но OnTradeTransaction  не надежен (событие может не дойти), и количество отправленных и сработавших ордеров у меня почему-то не совпало.

2. Какие ошибки надо ловить при асинхронной отправке? Заметил что на MQ-Demo приходят ошибки 10017 (Торговля запрещена) и 10024 (Слишком частые запросы) а вот на Admiral-Markets сервере ошибки 10017 не возникает, а есть только 10024. В общем не понятно каких именно ошибок от серверов нужно ждать.

 
C-4:

Спасибо за ответ. Все стало на свои места. Еще пару вопросов:

1. Как не выйти за пределы буфера и контролировать оставшийся его размер при асинхронной отправке? Я пробовал считать аналитически через OnTradeTransaction: выставляем 64 60 транзакций и ждем срабатывания первого ордера в OnTradeTransaction. Когда он срабатывает увеличиваем размер буфера на единицу. Но OnTradeTransaction не надежен, и количество отправленных и сработавших ордеров у меня почему-то не совпало.

2. Какие ошибки надо ловить при асинхронной отправке? Заметил что на MQ-Demo приходят ошибки 10017 (Торговля запрещена) и 10024 (Слишком частые запросы) а вот на Admiral-Markets сервере ошибки 10017 не возникает, а есть только 10024. В общем не понятно каких именно ошибок от серверов нужно ждать.

1. Контролировать буфер можно по коду 10024 - это мгновенный ответ самого терминала. То есть, комбинируя OnTradeTransaction и код ответа 10024 можно достаточно точно регулировать скорость, поддерживая ее на максимуме.

2. Нужно контролировать все типы ошибок, обрабатывая известные, а остальные по плану критической неизвестной ошибки.


Главный вопрос - вы уверены, что хотите строить торговую систему на уровне сотен транзакций в секунду так, чтобы упираться в лимиты? Это ведь только для краткосрочного теста годится.