OnTradeTransaction 기능에 대한 질문

 

참고로

요청 식별자 позволяет связать выполненное действие (OrderSend 또는 OrderSendAsync 함수 호출)을 OnTradeTransaction에 전달 된 이 작업의 결과와 연결할 수 있습니다.


즉, OnTradeTransaction 기능에서 주문 실행의 정확성을 확인할 수 있습니다. 아니면 내가 뭔가를 오해하고 있습니까?

그러나 여기에 주의 사항이 있습니다.

동시에 터미널에서 이러한 거래를 수신하는 순서는 보장되지 않으므로 다른 거래가 도착한 후 일부 거래가 수신될 것으로 예상하여 거래 알고리즘을 구축할 수 없습니다 . 또한 서버에서 단말로 전달하는 과정에서 거래가 손실될 수 있습니다.

글쎄, 보장된 순서가 아닌 것은 문제의 절반입니다. 그러나 거래가 손실될 수 있으므로 수표를 위해 OnTradeTransaction 기능을 사용할 수 없다는 사실을 어떻게 해야 할까요?

여기에 다음과 같은 질문도 있습니다. 그러면 이벤트 처리 기능 이 필요한 이유는 무엇입니까? 터미널에 절대 소용없는 로션??? 아니면 제가 또 뭔가 오해하고 있는 건가요?

 
OnTradeTransaction 기능은 주로 비동기 거래 전문가를 생성하는 데 필요합니다. 그러한 개발에 종사하지 않는다면 이 기능을 연구할 필요가 없을 것입니다. 간단히 말해서 OnTradeTransaction은 거래 환경의 변화를 확인하는 것과 함께 사용해야 합니다. 이 문제를 더 자세히 논의하고 싶지 않습니다.
 

그것도 감사합니다. 하지만 내가 아닌 비동기 트레이딩 전문가를 생성할 때 거래 손실이 발생할 수 있는데 어떤 검증을 이야기할 수 있을까요?

일반적으로 대답은 나를 만족시킵니다. 그리고 저는 이 주제에 대해 더 자세히 논의할 충분한 지식이 없습니다.

그리고 다시 한 번 감사드립니다.

 
AlexeyVik :

그것도 감사합니다. 하지만 내가 아닌 비동기 트레이딩 전문가를 생성할 때 거래 손실이 발생할 수 있는데 어떤 검증을 이야기할 수 있을까요?

일반적으로 대답은 나를 만족시킵니다. 그리고 저는 이 주제에 대해 더 자세히 논의할 충분한 지식이 없습니다.

그리고 다시 한 번 감사드립니다.

이 문제에 대한 기사를 작성했습니다.

OrderSendAsync 명령으로 주문한 것을 "잃지 않는" 방법을 알려줍니다.

이제 확인 중이지만 나오지 않으면 이 기사의 예(포워드 마켓 FORTS)입니다.

 //+------------------------------------------------------------------+
//|                                                       Demo_1.mq5 |
//|                                          Copyright 2015, Mikalas |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Mikalas"
#property link        "https://www.mql5.com"
#property version    "1.00"

input uint TimerPeriod = 1000 ;     //Время ожидания проверки ордера (1 сек.)   

ulong       order_ticket;
uint        request_id;
//
ulong       magic_number = 1010000 ;   //по 10000 на каждый символ
ulong       magic_storage;
ulong       mem_magic;
datetime    mem_time;
uint        mem_tick;
ulong       deal_volume;             //Счётчик заливки ордера
//
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit ()
{
  deal_volume = 0 ;             
   //--- Установка таймера
   if ( ! EventSetMillisecondTimer ( 500 ) )     //0.5 cек.
  {
     MessageBox ( "Таймер не установлен!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( INIT_FAILED );
  } 
   return ( INIT_SUCCEEDED );
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason )
{
//--- удаление таймера
   EventKillTimer ();
}
//+------------------------------------------------------------------+
//| Expert Get retcode function                                      |
//+------------------------------------------------------------------+
string GetRetCode( const uint code )
{
   string retcode;
//---  
   switch ( code )
  {
     case 10004 : retcode = "Реквота" ;
         break ;
     case 10006 : retcode = "Запрос отвергнут" ;
         break ;
     case 10007 : retcode = "Запрос отменен трейдером" ;
         break ;
     case 10008 : retcode = "Ордер размещен" ;
         break ;
     case 10009 : retcode = "Заявка выполнена" ;
         break ;
     case 10010 : retcode = "Заявка выполнена частично" ;
         break ;
     case 10011 : retcode = "Ошибка обработки запроса" ;
         break ;
     case 10012 : retcode = "Запрос отменен по истечению времени" ;
         break ;
     case 10013 : retcode = "Неправильный запрос" ;
         break ;
     case 10014 : retcode = "Неправильный объем в запросе" ;
         break ;
     case 10015 : retcode = "Неправильная цена в запросе" ;
         break ;
     case 10016 : retcode = "Неправильные стопы в запросе" ;
         break ;
     case 10017 : retcode = "Торговля запрещена" ;
         break ;
     case 10018 : retcode = "Рынок закрыт" ;
         break ;
     case 10019 : retcode = "Нет достаточных денежных средств для выполнения запроса" ;
         break ;
     case 10020 : retcode = "Цены изменились" ;
         break ;
     case 10021 : retcode = "Отсутствуют котировки для обработки запроса" ;
         break ;
     case 10022 : retcode = "Неверная дата истечения ордера в запросе" ;
         break ;
     case 10023 : retcode = "Состояние ордера изменилось" ;
         break ;
     case 10024 : retcode = "Слишком частые запросы" ;
         break ;
     case 10025 : retcode = "В запросе нет изменений" ;
         break ;
     case 10026 : retcode = "Автотрейдинг запрещен сервером" ;
         break ;
     case 10027 : retcode = "Автотрейдинг запрещен клиентским терминалом" ;
         break ;
     case 10028 : retcode = "Запрос заблокирован для обработки" ;
         break ;
     case 10029 : retcode = "Ордер или позиция заморожены" ;
         break ;
     case 10030 : retcode = "Указан неподдерживаемый тип исполнения ордера по остатку" ;
         break ;
     case 10031 : retcode = "Нет соединения с торговым сервером" ;
         break ;
     case 10032 : retcode = "Операция разрешена только для реальных счетов" ;
         break ;
     case 10033 : retcode = "Достигнут лимит на количество отложенных ордеров" ;
         break ;
     case 10034 : retcode = "Достигнут лимит на объем ордеров и позиций для данного символа" ;
         break ;
     case 10035 : retcode = "Неверный или запрещённый тип ордера" ;
         break ;
     case 10036 : retcode = "Позиция с указанным POSITION_IDENTIFIER уже закрыта" ;
         break ;
     default : retcode = "Нет кода возврата." ;  
         break ; 
  }
   return ( retcode );
}
//+------------------------------------------------------------------+
//| Expert place order function                                      |
//+------------------------------------------------------------------+
bool PlaceOrder( const string a_symbol, const double price, const double volume, const bool buy_sell )
{
   MqlTradeRequest request = { 0 };
   MqlTradeResult   result  = { 0 };
//---  
  order_ticket = 0 ;
  request_id = 0 ;
  mem_time = TimeTradeServer ();   //Время установки ордера (для для сокращения поиска в истории)
  mem_tick = GetTickCount ();       //Начало отсчёта времени (для проверки, если не сработала функция OnTradeTransaction)   
  mem_magic = magic_storage + 1 ;   //Уникальный номер (magic) ордера
  
   if ( mem_magic >= ( magic_number + 9999 ) ) mem_magic = magic_number;   //Переполнение, начинаем сначала
     
//--- Fill structure
  request.action = TRADE_ACTION_PENDING ;
  request.magic  = mem_magic;
  request.symbol = a_symbol;
  request.volume = volume;
  request.price  = price;
    
   if ( buy_sell )
  {
    request.type       = ORDER_TYPE_BUY_LIMIT ;
  }
   else
  {
    request.type       = ORDER_TYPE_SELL_LIMIT ;
  } 
  request.comment      = "Отложенный ордер..." ;      
  request.type_filling = ORDER_FILLING_RETURN ;
  request.type_time    = ORDER_TIME_DAY ;
   
//--- Send order
   if ( OrderSendAsync ( request, result ) )
  {
     if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      request_id = result.request_id;
      magic_storage = mem_magic;
       return ( true );
    }
     else
    {
      mem_magic = 0 ;
      mem_time = 0 ;
      mem_tick = 0 ;
       Print ( "Ордер не отправлен! " , a_symbol, " Код возврата = " , GetRetCode( result.retcode ) );
       return ( false );
    }
  }
   else
  {
    mem_magic = 0 ;
    mem_time = 0 ;
    mem_tick = 0 ;
     Print ( "Ордер не отправлен! " , a_symbol, " Код возврата = " , GetRetCode( result.retcode ) );
     return ( false );
  }
}
//+------------------------------------------------------------------+
//| Expert place order function                                      |
//+------------------------------------------------------------------+
void OnTick ()
{
   MqlTick a_tick;
  
   if ( SymbolInfoTick ( _Symbol , a_tick ) )
  {
    PlaceOrder( _Symbol , a_tick.ask, 1 , false );   //Устанавливаем ордер
  }     
}

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
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 ( ( request_id != 0 ) && ( result.request_id == request_id ) )
                                          {
                                             if ( result.retcode == TRADE_RETCODE_PLACED )
                                            {
                                              order_ticket = result.order;         //Получаем билет ордера
                                              mem_tick     = GetTickCount ();       //Начало отсчёта времени (для проверки, если не сработает функция OnTradeTransaction) 
                                            }
                                             else
                                            {
                                              mem_tick = 0 ;
                                               Print ( "OnTradeTransaction: Не получен билет ордера. Запрос = " , request_id );
                                            }
                                            request_id = 0 ;
                                            mem_magic  = 0 ;
                                            mem_time   = 0 ;
                                          }  
                                        }
                                         break ;
                                    
     case TRADE_TRANSACTION_DEAL_ADD :     if ( trans.order_state == ORDER_STATE_STARTED )
                                        {
                                           if ( ( order_ticket != 0 ) && ( trans.order == order_ticket ) )
                                          { 
                                             if ( ! OrderSelect ( order_ticket ) ) order_ticket = 0 ;     //Обнуляем билет, так как ордер залился полностью.
                                             Print ( "OnTradeTransaction: Сделка совершена, билет = " , trans.order ); 
                                          } 
                                        }
                                         break ;
                                     
     case TRADE_TRANSACTION_HISTORY_ADD : if ( (order_ticket != 0 ) && ( trans.order == order_ticket ) )
                                        {
                                          order_ticket = 0 ;
                                          
                                           switch ( trans.order_state )
                                          {
                                             case ORDER_STATE_REJECTED : Print ( "OnTradeTransaction: Ордер отклонён." );
                                                                       break ;
                                                                       
                                             case ORDER_STATE_CANCELED : Print ( "OnTradeTransaction: Ордер удалён." ); 
                                                                       break ;
                                                                     
                                             case ORDER_STATE_EXPIRED :   Print ( "OnTradeTransaction: Срок действия ордера окончен." );
                                                                       break ;
                                          }   
                                        }
                                         break ;     
                                        
     case TRADE_TRANSACTION_ORDER_UPDATE : if ( trans.order_state == ORDER_STATE_REQUEST_MODIFY )
                                         {
                                           if ( ( order_ticket != 0 ) && ( trans.order == order_ticket ) )
                                           {
                                             Print ( "OnTradeTransaction: Ордер в состоянии модифицикации." );
                                              mem_tick = GetTickCount ();  
                                           }
                                         }
                                         break ;                                                                                          
  }     
}
//+------------------------------------------------------------------+
// Expert find histiry order function                                |
//+------------------------------------------------------------------+
ulong FindHistoryOrder( const ulong a_magic, const datetime a_time, const datetime b_time )
{
   if ( HistorySelect ( a_time, b_time ) )
  {
     for ( int i = HistoryOrdersTotal () - 1 ; i >= 0 ; i-- )
    {
       ulong cur_ticket = HistoryOrderGetTicket ( i );
      
       if ( ulong ( HistoryOrderGetInteger ( cur_ticket, ORDER_MAGIC ) ) == a_magic ) return ( cur_ticket );
    }
  }  
   return ( 0 ) ;
}
//+------------------------------------------------------------------+
// Expert find order function                                        |
//+------------------------------------------------------------------+
ulong FindOrder( const ulong a_magic )
{
   for ( int i = OrdersTotal () - 1 ; i >= 0 ; i-- )
  {
     ulong cur_ticket = OrderGetTicket ( i );
    
     if ( ulong ( OrderGetInteger ( ORDER_MAGIC ) ) == a_magic ) return ( cur_ticket );
  }
   return ( 0 );
}
//+------------------------------------------------------------------+
//| Expert Get order tiket function                                  |
//+------------------------------------------------------------------+
ulong GetOrderTicket( const ulong m_magic, const datetime m_time, const datetime cur_time )
{
   ulong a_ticket = FindOrder( m_magic );                         //Ищем действующий ордер
  
   if ( a_ticket > 0 )
  {
     return ( a_ticket );
  }
   else
  {
    a_ticket = FindHistoryOrder( m_magic, m_time, cur_time );   //Ищем ордер в истории
    
     if ( a_ticket > 0 )
    {
       return ( a_ticket );
    }
  }  
   return ( 0 ); 
}
//+------------------------------------------------------------------+
//| Expert Check time function                                      |
//+------------------------------------------------------------------+
bool CheckTime( const uint start_value, const uint per_value )
{
   uint end_value = GetTickCount ();
  
   if ( end_value < start_value )
  {
     if ( ( start_value - end_value ) >= per_value ) return ( true );
  } 
   else
  {
     if ( ( end_value - start_value ) >= per_value ) return ( true );
  }
   return ( false );
}
//+------------------------------------------------------------------+
// Expert Get History Deals function                                 |
//+------------------------------------------------------------------+
uint GetHistoryDeals( const ulong ticket )
{
   int deals_total = HistoryDealsTotal ();
   uint ticket_deals = 0 ;
          
   for ( int i = 0 ; i < deals_total; i++ )
  {
     ulong deal_ticket = HistoryDealGetTicket ( i );
     ulong ord_ticket = ulong ( HistoryDealGetInteger ( deal_ticket, DEAL_ORDER ) );
        
     if ( ( ord_ticket > 0 ) && ( ord_ticket == ticket ) ) ticket_deals++;
  }
           
   if ( ticket_deals > 0 ) return ( ticket_deals );
  
   return ( 0 );
}
//+------------------------------------------------------------------+
//| Expert Check order function                                      |
//+------------------------------------------------------------------+
void CheckOrder()
{
   if ( ( mem_tick > 0 ) && CheckTime( mem_tick, TimerPeriod ) )           //Проверка времени ожидания действия над ордером (установка, модификация или удадение) 
  {
     if ( mem_magic > 0 )                                                   //Нет билета, получаем билет
    {
      order_ticket = GetOrderTicket( mem_magic, mem_time, TimeTradeServer () );
      
       if ( order_ticket > 0 )
      {
        mem_tick  = GetTickCount ();                                       //Начало отсчёта времени, если в будующем вновь не сработает функция OnTradeTransaction 
      }
       else
      {
        mem_tick  = 0 ;
         Print ( "Timeout: Билет ордера не найден!" );  
      }
      mem_magic = 0 ;
      mem_time  = 0 ;
    }
     else                                                                  
    {
       if ( order_ticket > 0 )                                             //Есть билет, смотрим что произошло с ордером
      {
         if ( OrderSelect ( order_ticket ) )                                 //Ордер рабочий 
        {
           double init_volume = OrderGetDouble ( ORDER_VOLUME_INITIAL );
           double cur_volume = OrderGetDouble ( ORDER_VOLUME_CURRENT );
          
           if ( init_volume != cur_volume )
          {
             ulong d_volume = ( ulong ( init_volume - cur_volume ) - deal_volume );
            deal_volume = deal_volume + d_volume;
            
             if ( d_volume > 0 )
            { 
               Print ( "Timeout: Сделка совершена, билет = " , order_ticket, " Объём = " , d_volume );
            }  
          }
          mem_tick = GetTickCount ();
        }
         else                                                                //Ордер исполнился, удален или экпирировался   
        {
           if ( HistoryOrderSelect ( order_ticket ) )
          {
             datetime ord_time = datetime ( HistoryOrderGetInteger ( order_ticket, ORDER_TIME_SETUP ) );
            
             if ( HistorySelect ( ord_time, TimeTradeServer () ) )
            {
               uint deals = GetHistoryDeals( order_ticket );
              
               if ( deals > 0 )
              {
                 Print ( "Timeout: Сделка совершена, билет = " , order_ticket );
              }
            }
          }
           else
          {
             Print ( "Timeout: Ордер " , order_ticket, " не найден в истории!" );
          } 
          deal_volume  = 0 ;
          order_ticket = 0 ;
          mem_tick     = 0 ;
        }
      }
       else
      {
        deal_volume = 0 ;
        mem_tick    = 0 ;
         Print ( "Timeout: Нет билета ордера!" );
      }
    }
  }
}
//+------------------------------------------------------------------+
//| Expert timer function                                            |
//+------------------------------------------------------------------+
void OnTimer ()
{
  CheckOrder();
}
//+------------------------------------------------------------------+
 
Mikalas :

이 문제에 대한 기사를 작성했습니다.

OrderSendAssync 명령으로 주문한 것을 "잃지 않는" 방법을 알려줍니다.

이제 확인 중이지만 나오지 않으면 이 기사의 예(포워드 마켓 FORTS)입니다.

마치 우리 모두 이해하고 기쁨에 손뼉을 치는 것처럼. 죄송합니다. 하지만 악마가 코드에서 다리를 부러뜨릴 것입니다.
 
C-4 :
마치 모든 것을 이해하고 기뻐서 손뼉을 친다는 듯이. 죄송하지만 악마가 코드에서 다리를 부러뜨릴 것입니다.

그리고 누군가가 그것이 쉬울 것이라고 약속 했습니까?

죄송합니다 바실리 기사가 나올때까지 기다리세요....

P/S 글이 안나오면 여기에 예를 들어 설명을 쓰겠습니다.

 
Mikalas :

P/S 글이 안나오면 여기에 예를 들어 설명을 쓰겠습니다.

왜 그녀가 나오지 말아야 합니까? 자료가 흥미롭습니다.

내 생각에 당신, Mikalas는 MQ와의 대화에서 티켓과 주문 ID에 대한 많은 요점을 명확히하기 위해 많은 노력을 기울였습니다. 기다리자.

 
Mikalas :

이 문제에 대한 기사를 작성했습니다.

OrderSendAssync 명령으로 주문한 것을 "잃지 않는" 방법을 알려줍니다.

이제 확인 중이지만 나오지 않으면 이 기사의 예(포워드 마켓 FORTS)입니다.

질문이 마음에 들지 않는다면. OrderSendAssync() 함수 로 주문하는 데 집중하는 이유는 무엇입니까? OrderSend() 함수로 주문하지 않으면 거래가 손실되지 않습니까? 이 경우 더 많은 보장?


경험이 없어서 OnTradeTransactio()에 이런 저런 결정을 삽입하고 싶었습니다. 그러나 지금까지 일이 잘 풀리지 않았습니다. 그리고 가능한 거래 손실에 대해 읽은 후, 그는 설명을 위해 귀하에게 연락했습니다.

일반적으로 FORTS 시장에 글을 쓰려면 이 시장을 이해해야 합니다. 이것은 나를 위한 것이 아니며 어쩌면 나는 그것을 필요로 하지 않을 수도 있습니다. mql5를 공부하기 위해 mql4로 작성된 올빼미를 다시 쓰기로 결정했습니다. 공부하다가...

 
AlexeyVik :

질문이 마음에 들지 않는다면. OrderSendAssync() 함수 로 주문하는 데 집중하는 이유는 무엇입니까? OrderSend() 함수로 주문하면 트랜잭션이 손실되지 않습니까? 이 경우 더 많은 보장?


경험이 없어서 OnTradeTransactio()에 이런 저런 결정을 삽입하고 싶었습니다. 그러나 지금까지 일이 잘 풀리지 않았습니다. 그리고 가능한 거래 손실에 대해 읽은 후, 그는 설명을 위해 귀하에게 연락했습니다.

일반적으로 FORTS 시장에 글을 쓰려면 이 시장을 이해해야 합니다. 이것은 나를 위한 것이 아니며 어쩌면 나는 그것을 필요로 하지 않을 수도 있습니다. mql5를 공부하기 위해 mql4로 작성된 올빼미를 다시 쓰기로 결정했습니다. 공부하다가...

1. OrderSendAsync가 훨씬 빠름(서버의 응답을 기다리지 않음)

OrderSend는 서버로부터 응답을 수신하도록 보장됩니다.

2. 예제는 FOREX에서도 잘 작동합니다.

result.retcode == TRADE_RETCODE_PLACED를 result.retcode == TRADE_RETCODE_DONE 으로 변경

 
Mikalas :

1. OrderSendAsync가 훨씬 빠름(서버의 응답을 기다리지 않음)

2. 예제는 FOREX에서도 잘 작동합니다.

result.retcode == TRADE_RETCODE_PLACED를 result.retcode == TRADE_RETCODE_DONE 으로 변경

즉, 비동기를 사용하지 않으면 올빼미가 서버의 응답을 기다리기 때문에 OnTradeTransaction 핸들러가 필요하지 않습니다.

그러나 지금까지 중지 명령이 활성화되었는지 확인하는 가장 좋은 방법을 찾지 못했습니다. 예를 들어, 시장 Buy 0.1과 SellStop 0.3이 설정되어 있고 0.3이 활성화되면 0.2가 남고 어느 시점에서 모니터링해야 하는지 ... 각 틱에서 두 개의 주문을 모니터링해야 하는 것으로 나타났습니다. 그리고 올빼미를 언로드하고 트랜잭션이 완료된 후에만 제어하고 싶었습니다. 통제조차 하지 말고, 일단 일어난 일을 확인하고 어떻게 할지 결정하세요. 하지만 분명히 운명은 아닌 것 같습니다 ... 오래된 입증 된 방법으로 돌아가는 것이 아마도 더 나을 것입니다 ...

 
AlexeyVik :

즉, 비동기를 사용하지 않으면 올빼미가 서버의 응답을 기다리기 때문에 OnTradeTransaction 핸들러가 필요하지 않습니다.

그러나 지금까지 중지 명령이 활성화되었는지 확인하는 가장 좋은 방법을 찾지 못했습니다. 예를 들어, 시장 Buy 0.1과 SellStop 0.3이 설정되어 있고 0.3이 활성화되면 0.2가 남고 어느 시점에서 모니터링해야 하는지 ... 각 틱에서 두 개의 주문을 모니터링해야 하는 것으로 나타났습니다. 그리고 올빼미를 언로드하고 트랜잭션이 완료된 후에만 제어하고 싶었습니다. 통제조차 하지 말고, 일단 일어난 일을 확인하고 어떻게 할지 결정하세요. 하지만 분명히 운명은 아닌 것 같습니다 ... 오래된 입증 된 방법으로 돌아가는 것이 아마도 더 나을 것입니다 ...

예, OnTradeTransaction을 사용할 수 없지만 기록을 파헤쳐야 하므로 고문의 전반적인 성능이 크게 저하됩니다.

모든 개발자에게는 선택권이 있습니다!

사유: