Проблема ввода нескольких ордеров для реального счета у конкретного брокера - страница 2

 
Malacarne:

Здравствуйте,BlindMist, имеет смысл проверить локальную базу данных, чтобы убедиться, что ваша учетная запись синхронизирована с сервером брокера.

Пожалуйста, посмотрите предложенный пост для решения этой проблемы.

Я только что просмотрел предложенный пост, и в нем не упоминается, как предотвратить многократное исполнение ордеров...

Даже с функцией Sleep(), как долго нужно ждать, чтобы быть уверенным, что сделка не удалась?....

В моем советнике запрос на отправку ордера выполняется через 10 секунд после повторной попытки... но иногда ордер исполняется через 15-20 секунд после первоначального запроса, что приводит к нежелательной двойной сделке.

 
BlindMist:

Я только что просмотрел предложенный пост, и в нем не упоминается, как предотвратить многократное исполнение ордеров...

Даже с функцией Sleep(), как долго нужно ждать, чтобы быть уверенным, что сделка не удалась?...

В моем советнике запрос на отправку ордера выполняется через 10 секунд после повторной попытки... но иногда ордер исполняется через 15-20 секунд после первоначального запроса, что приводит к нежелательной двойной сделке.

ПриветBlindMist, моя идея на эту тему, которую я все еще считаю единственным способом проверить это (вместо одного теста PositionSelect или только одного Sleep), это создать что-то вроде фатальной ошибки после долгого ожидания, или прыгнуть, как только у вас есть позиция символа (код ниже).

Единственный плюс этой проблемы в том, что, вероятно, PositionSelect, рано или поздно, получит обновленную позицию с сервера, поэтому нам остается только ждать максимальное время (наш таймаут) для индикации фатальной ошибки и делать небольшие выборки, чтобы проверить, все ли в порядке (100 мс в моем примере).

bool fatalError=false; // atention: declare this as global

....

if (fatalError==false) {
  if (m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0)) {
    Print("Position opened in ", Symbol());
    int maxTimeout=0;
    while (!PositionSelect(Symbol())) {
       Sleep(100);
       maxTimeout++;
       if (maxTimeout>100) {
          Print("### PositionSelect fatal error!");
          fatalError=true;
          break;
       }
    }
    Print("--> PositionSelect delay=",maxTimeout*100);
    break;
  }
}

Другой способ сделать это более модульно - создать функцию, например, для управления таймаутом:

bool PositionSelectTimeout(string symbol,int timeout) 
  { // timeout in seconds
   int maxTimeout=0;
   while(!PositionSelect(symbol)) 
     {
      Sleep(100);
      maxTimeout++;
      if(maxTimeout>(timeout*10)) return(false); // fatal error (timeout)
     }
   return(true); // position selected
  }

Основная идея здесь заключается в том, чтобы моя PositionSelectTimeout() заменила оригинальную PositionSelect(), в качестве обходного пути, конечно, поскольку только MQ может решить действительно хорошее и окончательное решение.

Например:

if (PositionSelectTimeout(Symbol(),60)) { // 60 seconds timeout
 ...
}

// instead of ...

if (PositionSelect(Symbol())) {
 ...
}

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

 
figurelli:

Привет,BlindMist, моя идея на эту тему, которую я все еще считаю единственным способом проверить это (вместо одного теста PositionSelect или одного Sleep), это создать что-то вроде фатальной ошибки после долгого ожидания, или прыгнуть, как только у вас есть позиция символа (код ниже).

Единственное, что хорошо в этой проблеме, это то, что, вероятно, PositionSelect, рано или поздно, получит обновленную позицию с сервера, так что нам остается только ждать максимальное время (наш таймаут) для индикации фатальной ошибки и делать небольшие выборки, чтобы проверить, все ли в порядке (100 мс в моем примере).

Другой способ сделать это более модульно - создать функцию для управления тайм-аутом, например:

Основная идея здесь заключается в том, чтобы моя PositionSelectTimeout() заменила оригинальную PositionSelect(), в качестве обходного пути, конечно, поскольку только MQ может решить действительно хорошее и окончательное решение.

Например:

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

Спасибо figurelli, очень подробный ответ. Я попробую и посмотрю, улучшит ли это мою систему.
 
BlindMist:
Спасибо figurelli, очень подробный ответ. Я попробую и посмотрю, улучшит ли это мою систему.
Спасибо, всегда пожалуйста.
 
BlindMist:

Я только что просмотрел предложенный пост, и в нем не упоминается, как предотвратить многократное исполнение ордеров...

Даже с функцией Sleep(), как долго нужно ждать, чтобы быть уверенным, что сделка не удалась?...

В моем советнике запрос на отправку ордера завершается через 10 секунд после повторной попытки... но иногда ордер исполняется через 15-20 секунд после первоначального запроса, что приводит к нежелательной двойной сделке.

15 секунд на исполнение одного ордера. Это очень плохо. Проблема в том, что мы ничего не можем получить от сервера брокера (например, даже простой код проверки статуса и т.д.).
 
FinanceEngineer:
15 секунд на исполнение одного ордера. Это очень плохо. Проблема в том, что мы ничего не можем получить от сервера брокера (например, даже простой код проверки статуса и т.д.).

ПриветFinanceEngineer, вы правы, однако первое, что нужно сделать, это выбрать брокера с низкой задержкой, так как рынки с каждым разом становятся все быстрее, и такие проблемы будут обычными.

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

В любом случае, OrderSend() в MT5 не так легко управлять, как в MT4, потому что возвращаемое значение в MT4 - это Ticket. Это изменение было необходимо в MT5, потому что асинхронная коммуникация фондовых рынков, введенная в архитектуре MQL5, позволяет общаться с брокером по протоколу OMS (как FIX, например).

Но я думаю, что это большое изменение OMS для управления ордерами сегодня, поскольку очень трудно получить Ticket в реальном времени, и MT5 обновлен для этого нового сценария, в основном, если мы используем фондовые рынки, где у нас больше задержки.

В этом смысле, более актуальная вещь, которую вы делаете после OrderSend() в MT5 - это проверка PositionSelect(), и я настоятельно рекомендую использовать предложенное мной обходное решение PositionSelectTimeout(), по всем вышеуказанным причинам.

Единственный способ, который я вижу, чтобы думать о худших случаях, это управлять всеми условиями if { } else { } после отправки ордера на рынок, таким образом, чтобы вы могли управлять любой ситуацией.

Я бы тоже хотел иметь catch { }, но мы можем использовать GetLastError(), чтобы сделать что-то близкое к этому.

Это потому, что вам также нужен тикет для подтверждения позиции, а MT5 OrderSend() не возвращает тикет так синхронно, как это делает MT4.

 
BlindMist:

Я только что просмотрел предложенный пост, и в нем не упоминается, как предотвратить многократное исполнение ордеров...

Даже с функцией Sleep(), как долго нужно ждать, чтобы быть уверенным, что сделка не удалась?...

В моем советнике запрос на отправку ордера выполняется через 10 секунд после повторной попытки... но иногда ордер исполняется через 15-20 секунд после первоначального запроса, что приводит к нежелательной двойной сделке.

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

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

 
FinanceEngineer:

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

      bool checkOrderSend = OrderSend(request, result);
     
      if(result.retcode==10009 || result.retcode==10008)
      {
          Print("OrderSend was successful. Code: ",result.retcode);

          
          break;
      }
      else
      {
          Print(ResultRetcodeDescription(result.retcode));
      }
     

Что вы делаете с переменной checkOrderSend?

Как вы предотвращаете исполнение нескольких ордеров без проверки завершения сделки на сервере?

 
figurelli:

Что вы делаете с переменной checkOrderSend?

Как предотвратить выполнение нескольких ордеров без проверки завершения сделки на сервере?

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

Я имел в виду, что нужно проверять оба кода 10009 и 10008 в конце функции OrderSend. Потому что я обнаружил, что многие люди проверяют только один код возврата (т.е. 10009 или 10008) и получают много множественных ордеров, так как они обычно размещают цикл for, чтобы избежать ситуации отсутствия ордеров.

В моем случае цикл for будет повторяться 10 раз, если я не получу ни одного ордера у этого брокера. Поэтому, вероятно, стоит уточнить, что если кто-то получает множественные ордера, то он должен проверить, останавливает ли он свой цикл Ordersending, проверяя и 10009, и 10008.

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

С уважением.

 
FinanceEngineer:

Здравствуйте, figurelli

Я имел в виду проверку обоих кодов 10009 и 10008 в конце функции OrderSend. Потому что я обнаружил, что многие люди проверяют только один код возврата (т.е. 10009 или 10008) и получают много множественных ордеров, так как они обычно размещают цикл for, чтобы избежать ситуации отсутствия ордеров.

В моем случае цикл for будет повторяться 10 раз, если я не получу ни одного ордера у этого брокера. Поэтому, вероятно, стоит уточнить, что если кто-то получает множественные ордера, то он должен проверить, останавливает ли он свой цикл Ordersending, проверяя и 10009, и 10008.

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

С уважением.

Здравствуйте,FinanceEngineer, возможно, было бы лучше начать проверять проблему множественных ордеров в вашем оригинальном коде, так как если мы это сделаем, возможно, мы рассмотрим другие критические моменты здесь и не потеряем фокус, что вы думаете об этом?