Правильная установка ордеров. мт5

 

Захотелось наконец то решить до конца вопрос с выставлением позиций в мт5 и обработкой всех поступающих сообщений. так сказать всё ли я правильно делаю. Можно сказать - обмен опытом.
Когда роботу нужно открыть позицию я действую следующим образом:

1. Проверяю необходимую маржу функцией OrderCalcMargin. Для одной позиции можно и не делать, но если нужно поставить сразу несколько позиций то это актуально.
2. Получаю коэффициенты маржи функцией SymbolInfoMarginRate, беру из них максимальный и умножаю его на пункт 1 (доп. вопрос - а есть ли смысл это делать для валютных пар ?)
3. Суммирую пункты 1 и 2 - узнаю всю сумму необходимого залога для открытия позиций.
4. Полученное значение должно быть меньше чем AccountInfoDouble(ACCOUNT_MARGIN_FREE)
5. Перед выставлением позиции чекаю её OrderCheck. Глобального смысла структуры MqlTradeCheckResult не понимаю. Возможно из-за наличия пункта 1. так как сам проверяю залог. Мне достаточно итогового тру.
6.Шлю запрос через OrderSendAsync или OrderSend.
7.Если результат отправки запроса=тру и retcode=10008 перехожу в OnTradeTransaction
8.Первая операция которая проходит в OnTradeTransaction это установка ордера. Его я запоминаю в глобальной переменной, чтобы дальше не путаться, т.е.пишу так:

 if (trans.type==TRADE_TRANSACTION_ORDER_ADD) order=trans.order;

9.Теперь меня интересует тип торговой транзакции и если он есть TRADE_TRANSACTION_REQUEST и относится к моему ордеру то проверяю retcode и если он = 10009, то значит позиция успешно открыта. В коде это выглядит так:

      if (trans.type==TRADE_TRANSACTION_REQUEST)
      if (result.order==order)
      if (result.retcode==10009) Print("Заявка успешно выполнена");

 

Что меня смущает:
Переход из пункта 7 в пункт 8, а именно, после  OrderSend и retcode=10008 я начинаю оценивать структуру trans в OnTradeTransaction и только там получаю тикет ордера с которым начинается работа, а если получится так что робот добавляет позицию и в ручную что то в этот же момент добавляется?

 

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

 
Alexey Oreshkin:

Захотелось наконец то решить до конца вопрос с выставлением позиций в мт5 и обработкой всех поступающих сообщений. так сказать всё ли я правильно делаю. Можно сказать - обмен опытом.
Когда роботу нужно открыть позицию я действую следующим образом:

1. Проверяю необходимую маржу функцией OrderCalcMargin. Для одной позиции можно и не делать, но если нужно поставить сразу несколько позиций то это актуально.
2. Получаю коэффициенты маржи функцией SymbolInfoMarginRate, беру из них максимальный и умножаю его на пункт 1 (доп. вопрос - а есть ли смысл это делать для валютных пар ?)
3. Суммирую пункты 1 и 2 - узнаю всю сумму необходимого залога для открытия позиций.
4. Полученное значение должно быть меньше чем AccountInfoDouble(ACCOUNT_MARGIN_FREE)
5. Перед выставлением позиции чекаю её OrderCheck. Глобального смысла структуры MqlTradeCheckResult не понимаю. Возможно из-за наличия пункта 1. так как сам проверяю залог. Мне достаточно итогового тру.
6.Шлю запрос через OrderSendAsync или OrderSend.
7.Если результат отправки запроса=тру и retcode=10008 перехожу в OnTradeTransaction
8.Первая операция которая проходит в OnTradeTransaction это установка ордера. Его я запоминаю в глобальной переменной, чтобы дальше не путаться, т.е.пишу так:

9.Теперь меня интересует тип торговой транзакции и если он есть TRADE_TRANSACTION_REQUEST и относится к моему ордеру то проверяю retcode и если он = 10009, то значит позиция успешно открыта. В коде это выглядит так:

Что меня смущает:
Переход из пункта 7 в пункт 8, а именно, после  OrderSend и retcode=10008 я начинаю оценивать структуру trans в OnTradeTransaction и только там получаю тикет ордера с которым начинается работа, а если получится так что робот добавляет позицию и в ручную что то в этот же момент добавляется?

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

Вы слишком усложняете. Что Вы будете делать, если по каким-то причинам OnTradeTransaction не наступит? Выставленный ордер либо сработает, либо нет. Если он сработает, то количество исторических или отложенных ордеров изменится. Эти изменения и надо анализировать, а не наступление OnTradeTransaction.

Второе, используйте стандартную библиотеку, класс CTrade. Он все сделает за Вас.

 
Когда алгоритм будет считаться выработанным, можно его оформить в виде наглядной схемы-картинки (если интересует, помогу нарисовать).
 
Vasiliy Sokolov:

Вы слишком усложняете. Что Вы будете делать, если по каким-то причинам OnTradeTransaction не наступит? Выставленный ордер либо сработает, либо нет. Если он сработает, то количество исторических или отложенных ордеров изменится. Эти изменения и надо анализировать, а не наступление OnTradeTransaction.

Второе, используйте стандартную библиотеку, класс CTrade. Он все сделает за Вас.

как это OnTradeTransaction не наступит ? а как же позиция откроется?

Вообще целый алгоритм открытия позиции в мт5 следующий:
1.Отправили запрос посредством OrderSend и если реткод=10008 то начинается установка ордера.то есть всё что происходит далее видно в структуре trans в событии OnTradeTransaction
2.В системе появляется ордер: trans.type=TRADE_TRANSACTION_ORDER_ADD. на этом этапе статус ордера, trans.order_type=ORDER_STATE_STARTED. т.е. он проверен и корректен и нам известен номер этого ордера
3.Далее появляется торговая заявка: trans.type=TRADE_TRANSACTION_DEAL_ADD. номер ордера у нас получен из пункта 2, здесь же мы уже можем узнать номер заявки, но тип ордера пока тот же=ORDER_STATE_STARTED. структуры request и result пока без особых изменений
4.Когда торговый запрос обработан сервером то мы получаем trans.type=TRADE_TRANSACTION_REQUEST, можно анализировать request и result, там видно что поставили ордер или нет и все его реквизиты
5.Теперь происходит удаление ордера из списка открытых, т.е. trans.type=TRADE_TRANSACTION_ORDER_DELETE
6.Создаём запись о ордере в истории, т.е. trans.type=TRADE_TRANSACTION_HISTORY_ADD. но ордер сюда добавится не только в случае исполнения, но и в случае отмены, правда здесь можно проверить trans.order_state и если получаем ORDER_STATE_FILLED то значит всё выполнено успешно, но как я понял до этого шага можно не доходить, так как здесь уже идёт оценка успешности не только открытия позиции но и переноса ордера в историю

.....Поэтому я не понимаю как OnTradeTransaction может не наступить

Стандартные классы я использую только когда нужно быстро накидать макет робота для проверки работоспособности идеи, и если всё ок то пишу всё сам, без использования стороннего кода. 

 
Alexey Oreshkin:

как это OnTradeTransaction не наступит ? а как же позиция откроется?

Вообще целый алгоритм открытия позиции в мт5 следующий:
1.Отправили запрос посредством OrderSend и если реткод=10008 то начинается установка ордера.то есть всё что происходит далее видно в структуре trans в событии OnTradeTransaction
2.В системе появляется ордер: trans.type=TRADE_TRANSACTION_ORDER_ADD. на этом этапе статус ордера, trans.order_type=ORDER_STATE_STARTED. т.е. он проверен и корректен и нам известен номер этого ордера
3.Далее появляется торговая заявка: trans.type=TRADE_TRANSACTION_DEAL_ADD. номер ордера у нас получен из пункта 2, здесь же мы уже можем узнать номер заявки, но тип ордера пока тот же=ORDER_STATE_STARTED. структуры request и result пока без особых изменений
4.Когда торговый запрос обработан сервером то мы получаем trans.type=TRADE_TRANSACTION_REQUEST, можно анализировать request и result, там видно что поставили ордер или нет и все его реквизиты
5.Теперь происходит удаление ордера из списка открытых, т.е. trans.type=TRADE_TRANSACTION_ORDER_DELETE
6.Создаём запись о ордере в истории, т.е. trans.type=TRADE_TRANSACTION_HISTORY_ADD. но ордер сюда добавится не только в случае исполнения, но и в случае отмены, правда здесь можно проверить trans.order_state и если получаем ORDER_STATE_FILLED то значит всё выполнено успешно, но как я понял до этого шага можно не доходить, так как здесь уже идёт оценка успешности не только открытия позиции но и переноса ордера в историю

.....Поэтому я не понимаю как OnTradeTransaction может не наступить

Стандартные классы я использую только когда нужно быстро накидать макет робота для проверки работоспособности идеи, и если всё ок то пишу всё сам, без использования стороннего кода. 

 

Это будет здорово! главное чтобы были комментарии.

Алексей, Вы правильно делаете, что не используете стандартную библиотеку на ФОРТС.

Событие TradeTransaction - не гарантировано, поэтому необходимо сделать альтернативную функцию проверки

ордеров. Например так:

https://www.mql5.com/ru/blogs/post/557544 

Отслеживание ордера, после команды OrderSendAsync
Отслеживание ордера, после команды OrderSendAsync
  • 2015.04.29
  • Михаил
  • www.mql5.com
Отслеживание ордера, после команды OrderSendAsync Михаил | 23 апреля, 2015 В статье рассказывается принцип отслеживания ордера после команды OrderSendAsync, если нет события...
 
Михаил:

Алексей, Вы правильно делаете, что не используете стандартную библиотеку на ФОРТС.

Событие TradeTransaction - не гарантировано, поэтому необходимо сделать альтернативную функцию проверки

ордеров. Например так:

https://www.mql5.com/ru/blogs/post/557544 

событие TradeTransaction не гарантированно.- это для меня разрыв шаблонов :(
А событие OnTrade интересно гарантировано или нет?
 
Vasiliy Sokolov:

Второе, используйте стандартную библиотеку, класс CTrade. Он все сделает за Вас.

Я тут глянул  класс CTrade и возвращаемый retcode. Нашёл только 10008, но этого мало. нужно получить 10009. Или я из-за беглого просмотра не заметил, или этих результатов в стандартной библиотеке мы получить не можем. Если так, то это уже говорит о том что класс можно использовать только в тестере, а для реальной работы он не подходит. Надеюсь я ошибаюсь.
 
Alexey Oreshkin:
Я тут глянул  класс CTrade и возвращаемый retcode. Нашёл только 10008, но этого мало. нужно получить 10009. Или я из-за беглого просмотра не заметил, или этих результатов в стандартной библиотеке мы получить не можем. Если так, то это уже говорит о том что класс можно использовать только в тестере, а для реальной работы он не подходит. Надеюсь я ошибаюсь.

Событие OnTrade гарантировано (использовать можно только с OrderSend() ), но  OrderSend() гораздо медленнее OrderSendAssync(). 

Алексей, у Вас немного не правильное представление о кодах

возврата на ФОРТС. Чуть позже я покажу как нужно делать. 

 
Михаил:

Событие OnTrade гарантировано (использовать можно только с OrderSend() ), но  OrderSend() гораздо медленнее OrderSendAssync(). 

Алексей, у Вас немного не правильное представление о кодах

возврата на ФОРТС. Чуть позже я покажу как нужно делать. 

Возможно. Я потому и поднял эту тему чтобы окончательно разобраться. Вроде всё понятно и работает, но я понимаю в каком месте может быть сбой, хотя ничего подобного ниразу ещё небыло.
Если OnTrade только для OrderSend, то это печально, мне нужен OrderSendAsync и ещё - событие TradeTransaction не гарантировано именно для ФОРТС или вообще везде?
 
Alexey Oreshkin:
Возможно. Я потому и поднял эту тему чтобы окончательно разобраться. Вроде всё понятно и работает, но я понимаю в каком месте может быть сбой, хотя ничего подобного ниразу ещё небыло.
Если OnTrade только для OrderSend, то это печально, мне нужен OrderSendAsync и ещё - событие TradeTransaction не гарантировано именно для ФОРТС или вообще везде?

TradeTransaction везде не гарантировано.

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

 Сбои будут. 
 

Порядок работы с OrderSendAssync():

1. Проверяете наличие средств.

double prim_go = SymbolInfoDouble( _Symbol, SYMBOL_MARGIN_INITIAL );

 

double free_margin = AccountInfoDouble( ACCOUNT_FREEMARGIN );

2. Не нужно делать лишнюю операцию OrderCheck()

Потому что (из справки)

 

В случае нехватки средств или ошибочно заполненных параметров функция возвращает false.
В случае успешной базовой проверки структур (проверка указателей) возвращается true – это не является свидетельством того,
что запрашиваемая торговая операция непременно выполнится успешно.
Для получения подробного описания результата выполнения функции следует анализировать поля структуры result. 

Чтобы получить информацию об ошибке, необходимо вызвать функцию GetLastError().

3. Отсылая ордер командой OrderSendAssymc() Вы должны получить номер запроса:

if ( OrderSendAsync( request, result ) )
  {
    if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      req_id = result.request_id;
    }
  }

 

 4. Далее в OnTradeTransaction:

void OnTradeTransaction( const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result )
{
  switch( trans.type )
  {
    case TRADE_TRANSACTION_REQUEST: if ( trans.order_state == ORDER_STATE_STARTED )
                                    {
                                      if ( ( req_id != 0 ) && ( result.request_id == req_id ) )
                                      {
                                        if ( result.retcode == TRADE_RETCODE_PLACED )
                                        {
                                          order_ticket = result.order;  //Получаем билет ордера
                                         }
                                      }
                                    } 
                                    break;
  }
} 

 А далее "по вкусу".

Причина обращения: