Как правильно работать в MT5 с OrderSend - страница 11

 
prostotrader:

Да не в двух, а в одной :)

 

if(transaction.type == TRADE_TRANSACTION_REQUEST && request.action == TRADE_ACTION_DEAL)

TRADE_TRANSACTION_REQUEST нужен тогда, когда Вы используете OrderSendAsymc для получения тикета ордера.

И что же там не правильно? Откуда вы знаете, может быть я использую именно OrderSendAsync()?
А для проверки, например, штампа эксперта, пославшего торговый запрос, я не могу это использовать? Или, например, для проверки тикета позиции, с которой была совершена последняя сделка?

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

То есть, если я использую  асинхронную отправку ордера, код правильный?

 
Oleg Shenker:

И что же там не правильно? Откуда вы знаете, может быть я использую именно OrderSendAsync()?
А для проверки, например, штампа эксперта, пославшего торговый запрос, я не могу это использовать? Или, например, для проверки тикета позиции, с которой была совершена последняя сделка?

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

То есть, если я использую  асинхронную отправку ордера, код правильный?

Тема называется 

"Как правильно работать с OrderSend"

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

то всё с ордером впорядке. Но сейчас это функция не совсем корректно работает, поэтому, получив тикет ордера, Вы

в OnTradeTransaction должны получить подтверждение, что всё ОК.

Т.е данные по этому ордеру полностью синхронизированы в терминале.

//+------------------------------------------------------------------+
// Expert TradeTransaction function                                  |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   switch(trans.type)
     {
      case TRADE_TRANSACTION_ORDER_UPDATE:
           switch(trans.order_state)
           {
            case ORDER_STATE_PLACED:
               if(order_ticket==trans.order)
                 {
                  Print(__FUNCTION__," Order plased done. Ticket = ",trans.order);
                  if(order_ticket>0)
                    {
                     if(OrderSelect(order_ticket))
                       {
                        //Данные по ордеру синхронизированы
                       }
                     else
                       {
                        Print(__FUNCTION__," Order not select! Ticket = ",trans.order);
                       }
                    }
                  else
                    {
                     Print(__FUNCTION__," Wrong order ticket = ",trans.order);
                    }
                 }
               break;
           }
         break;
     }
  }


 

 
prostotrader:

Тема называется 

"Как правильно работать с OrderSend"

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

то всё с ордером впорядке. Но сейчас это функция не совсем корректно работает, поэтому, получив тикет ордера, Вы

в OnTradeTransaction должны получить подтверждение, что всё ОК.

Т.е данные по этому ордеру полностью синхронизированы в терминале.

//+------------------------------------------------------------------+
// Expert TradeTransaction function                                  |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   switch(trans.type)
     {
      case TRADE_TRANSACTION_ORDER_UPDATE:
           switch(trans.order_state)
           {
            case ORDER_STATE_PLACED:
               if(order_ticket==trans.order)
                 {
                  Print(__FUNCTION__," Order plased done. Ticket = ",trans.order);
                  if(order_ticket>0)
                    {
                     if(OrderSelect(order_ticket))
                       {
                        //Данные по ордеру синхронизированы
                       }
                     else
                       {
                        Print(__FUNCTION__," Order not select! Ticket = ",trans.order);
                       }
                    }
                  else
                    {
                     Print(__FUNCTION__," Wrong order ticket = ",trans.order);
                    }
                 }
               break;
           }
         break;
     }
  }


 

Замечательно! Я это знаю. Только я использую асинхронную отправку ордера. У меня другая проблема, событие REQUEST (по смыслу завершающее подведение итогов транзакции) для одной и той же сделки пришло два раза. 
 
Oleg Shenker:
Замечательно! Я это знаю. Только я использую асинхронную отправку ордера. У меня другая проблема, событие REQUEST (по смыслу завершающее подведение итогов транзакции) для одной и той же сделки пришло два раза. 

Вы просто не совсем понимаете как нужно обрабатывать сообщения в OnTradeTransaction, при установке ордеров OrderSEndAsync

Запистите этого советника и посмотрите как он работает

Файлы:
TestOrders.mq5  25 kb
 
prostotrader:

Вы просто не совсем понимаете как нужно обрабатывать сообщения в OnTradeTransaction, при установке ордеров OrderSEndAsync

Запистите этого советника и посмотрите как он работает

Так я вас и спрашиваю, как надо правильно обрабатывать TradeTransactions.

 
Oleg Shenker:

Так я вас и спрашиваю, как надо правильно обрабатывать TradeTransactions.

Порядок, для OrderSendAsync такой:

Отправляя ордер командой OrderSendAsync Вы, при успешной отсылке получаете order_id 

 

bool SendOrderAsyncMode()
  {
   double price=SymbolInfoDouble(Symbol(),SYMBOL_SESSION_PRICE_LIMIT_MAX);
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};
   order_ticket=0;
   order_id=0;
   request.action = TRADE_ACTION_PENDING;
   request.magic  = 9876543210;
   request.symbol = Symbol();
   request.volume = 1;
   request.price  = price;
   request.type=ORDER_TYPE_SELL_LIMIT;
   request.comment="Async mode";
   request.type_filling=ORDER_FILLING_RETURN;
   request.type_time=ORDER_TIME_DAY;
   if(OrderSendAsync(request,result))
     {
      if((result.retcode==TRADE_RETCODE_PLACED) || (result.retcode==TRADE_RETCODE_DONE))
        {
         if(result.request_id>0)
           {
            order_id=result.request_id;
            Print(__FUNCTION__," Order sent in async mode");
            return(true);
           }
         else
           {
            Print(__FUNCTION__," Error order sent in async mode! Retcode = ",result.retcode);
           }
        }
      else
        {
         Print(__FUNCTION__," Error order sent in async mode! Retcode = ",result.retcode);
        }
     }
   else
     {
      Print(__FUNCTION__," Order not sent in async mode.");
     }
   return(false);
  }

Далее ВСЕ остальные данные получаем в OnTradeTransaction

1. Получение тикета ордера

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   switch(trans.type)
     {
      case TRADE_TRANSACTION_REQUEST:
         if((order_id>0) && (order_id==result.request_id))
           {
            order_id=0;
            order_ticket=result.order;
            Print(__FUNCTION__," Order get ticket done. Ticket = ",result.order);
           }
         break;
     }
}

 2. Если Вы используете рыночные или лимитные (не отложенные) ордера, т.е те, которые сразу исполняются

или отвергаются, то нужно мониторить TRADE_TRANSACTION_HISTORY_ADD, потому что в любом случае

такие ордера добавляются в историю. 

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   switch(trans.type)
     {
      case TRADE_TRANSACTION_HISTORY_ADD:
         if(order_ticket==trans.order)
           {
             //Берем данные из истории
           }
         break;
    }
  }


 3. Если Вы тспользуете отложенные ордера (могут исполнятся частями), то следует мониторить

стазу три события  TRADE_TRANSACTION_ORDER_UPDATE, TRADE_TRANSACTION_HISTORY_ADD, TRADE_TRANSACTION_DEAL_ADD

TRADE_TRANSACTION_ORDER_UPDATE - служит для получения информации, что ордер установлен (модифицирован) 

TRADE_TRANSACTION_DEAL_ADD - узнаём, что произошла сделка

 TRADE_TRANSACTION_HISTORY_ADD - ордера НЕТ в торговой системе, смотрим данные по ордеру

 Вот и все "премудрости"

Добавлено

Связка  OrderSendAsync и OnTradeTransaction работает без нареканий, проверял и на ФОРЕКС (демо)

и на ФОРТС (реал) 

 
prostotrader:

Добавлено

Связка  OrderSendAsync и OnTradeTransaction работает без нареканий, проверял и на ФОРЕКС (демо)

и на ФОРТС (реал) 

Спасибо! Теперь я знаю, как пользоваться функцией OnTradeTransaction() или есть еще какие-то секреты?

Как же без нареканий, если событие TradeTransaction() может потеряться? 

 
Oleg Shenker:

Спасибо! Теперь я знаю, как пользоваться функцией OnTradeTransaction() или есть еще какие-то секреты?

Как же без нареканий, если событие TradeTransaction() может потеряться? 

Больше нет никаких секретов.

Может потерятся ( но это присходило раза 3-4 за 4-5 месяцев и в моменты сильной активности рынка),

поэтому страховка не помешает.

 

А вот и конкретный пример проверки ордера

Лог терминала:

2017.01.05 11:46:01.673 Trades  'xxxxx': buy limit 1.00 PLT-6.17 at 952.3
2017.01.05 11:46:02.895 Trades  'xxxxx': accepted buy limit 1.00 PLT-6.17 at 952.3
2017.01.05 11:46:02.896 Trades  'xxxxx': buy limit 1.00 PLT-6.17 at 952.3 placed for execution in 1223.187 ms

 Лог эксперта:

2017.01.05 11:46:02.829 trader (PLT-3.17,H1)      CheckOrders: Задержка ответа сервера. Ожидание продолжается...


 Приказ был отправлен в 2017.01.05 11:46:01.673

Ответа от сервера небыло более 1 сек., произошла проверка ордера. 

В обычном режиме ответ приходит через 7-10 мсек. 

 

Отвечая на вопрос темы "Как правильно работать в MT5 с OrderSend"

Есть простой ответ

Пока рзработчики не исправят недочёт, то

ulong pre_ticket; //Предварительный тикет
ulong order_ticket; //Тикет ордера
//---
if(OrderSend(request,result))
  {
    if(result.retcode==TRADE_RETCODE_DONE)
    {
      pre_ticket=result.order;
    }  
  }
//----------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
   switch(trans.type)
   {
     case TRADE_TRANSACTION_ORDER_UPDATE:
       if((pre_ticket>0) && (trans.order==pre_ticket))
       {
         switch(trans.order_state)
         {
           case ORDER_STATE_PLACED:
             order_ticket = pre_ticket;
           break;
         }
       }
     break;
   }
}

 

А когда исправят, то 

ulong order_ticket; //Тикет ордера
//---
if(OrderSend(request,result))
  {
    if(result.retcode==TRADE_RETCODE_DONE)
    {
      order_ticket=result.order;
    }  
  }


 

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