OnTradeTransaction

TradeTransaction事件发生时在EA中调用这个函数。这个函数旨在处理交易请求执行结果。

void  OnTradeTransaction()
   const MqlTradeTransaction&    trans,     // 交易事务结构
   const MqlTradeRequest&        request,   // 请求结构
   const MqlTradeResult&         result     // 回应结构
   );

参数

trans

[in] MqlTradeTransaction类型变量描述了在交易账户上进行的交易。

request

[in] MqlTradeRequest类型变量描述了导致交易的交易请求。它只包含TRADE_TRANSACTION_REQUEST类型交易的值。

result

[in] MqlTradeResult类型变量描述了导致交易的交易请求的执行结果。它只包含TRADE_TRANSACTION_REQUEST类型交易的值。

返回值

无返回值

注意

调用OnTradeTransaction()来处理在下列情况下由交易服务器发送至程序端的TradeTransaction事件:

  • 使用OrderSend()/OrderSendAsync()函数,从MQL5程序发送交易请求及其后续执行;
  • 通过GUI手动发送交易请求及其后续执行;
  • 激活服务器上的挂单和止损单;
  • 在交易服务器端执行操作。

 

关于交易类型的数据包含在trans变量的类型字段中。交易事务类型在ENUM_TRADE_TRANSACTION_TYPE枚举中描述:

  • TRADE_TRANSACTION_ORDER_ADD – 添加一个新的活跃订单
  • TRADE_TRANSACTION_ORDER_UPDATE – 更改现有订单
  • TRADE_TRANSACTION_ORDER_DELETE – 从活跃订单列表删除一个订单
  • TRADE_TRANSACTION_DEAL_ADD – 在历史中添加一笔交易
  • TRADE_TRANSACTION_DEAL_UPDATE – 在历史中改变一笔交易
  • TRADE_TRANSACTION_DEAL_DELETE – 从历史删除一笔交易
  • TRADE_TRANSACTION_HISTORY_ADD – 在历史中添加一个订单作为执行或取消的结果
  • TRADE_TRANSACTION_HISTORY_UPDATE – 在订单历史中更改一个订单
  • TRADE_TRANSACTION_HISTORY_DELETE – 从订单历史中删除一个订单
  • TRADE_TRANSACTION_POSITION – 与交易执行无关的持仓变化
  • TRADE_TRANSACTION_REQUEST – 已收到服务器处理交易请求的通知和处理结果。

当处理TRADE_TRANSACTION_REQUEST类型交易时,需要分析OnTradeTransaction()函数的第二和第三个参数 – requestresult – 来获取额外信息。

发送买入交易请求会导致交易账户上的一系列交易:1) 请求被接受进行处理,2) 为该账户创建了一个适当的购买订单,3) 然后执行订单,4) 已执行订单从活跃订单列表中移除,5) 添加到订单历史中,6) 随后事务被添加到历史中以及 7) 创建新持仓。所有这些阶段都是交易事务过程。每一个这类交易事务到达程序端就是TradeTransaction事件。不保证这些交易到达程序端的优先级。因此,在开发您的EA交易时,您不应该期望一组交易将在另一组之后到达。

当交易由EA的OnTradeTransaction()处理程序进行处理时,程序端将继续处理传入的交易事务。因此,在OnTradeTransaction()操作过程中,交易账户状态可能会发生变化。例如,当MQL5程序处理添加新订单时,它可以被执行,被从已开设订单的列表中删除以及被移动到历史中。所有这些事件的消息都将通知该程序。

交易事务队列长度由1024个要素组成。如果OnTradeTransaction()处理另一个事务时间太长,那么之前的事务就可能被队列中的新事物所取代。

适当调用OnTradeTransaction()之后调用OnTrade()处理程序。通常,在OnTrade ()和OnTradeTransaction ()调用的数量上没有确切的相关性。OnTrade()一次调用对应一次或多次的OnTradeTransaction调用。

每一个Trade事件都可能作为一个或多个交易请求的结果出现。交易请求使用OrderSend()OrderSendAsync(),被发送到服务器。每个请求都可能导致多个交易事件。您不能依赖“一个请求,一个交易事件”的声明,因为事件的处理可能分为几个阶段执行,并且每个操作都可能更改订单的状态、持仓和交易历史记录。

EA样例,OnTradeTransaction()处理程序

//+------------------------------------------------------------------+
//|                                    OnTradeTransaction_Sample.mq5 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property description "Sample listener of TradeTransaction events"
//+------------------------------------------------------------------+
//| EA交易初始化函数                                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   PrintFormat("LAST PING=%.f ms",
               TerminalInfoInteger(TERMINAL_PING_LAST)/1000.);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| EA报价函数                                                        |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
 
  }
//+------------------------------------------------------------------+
//| TradeTransaction函数                                              |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//---
   static int counter=0;   // counter of OnTradeTransaction() calls
   static uint lasttime=0; // time of the OnTradeTransaction() last call
//---
   uint time=GetTickCount();
//--- 如果最后一个交易事务在1秒之前执行,
   if(time-lasttime>1000)
     {
      counter=0; // 那么这是一个新交易操作,计数器可被重置
      if(IS_DEBUG_MODE)
         Print(" New trade operation");
     }
   lasttime=time;
   counter++;
   Print(counter,". ",__FUNCTION__);
//--- 交易请求执行的结果
   ulong            lastOrderID   =trans.order;
   ENUM_ORDER_TYPE  lastOrderType =trans.order_type;
   ENUM_ORDER_STATE lastOrderState=trans.order_state;
//--- 执行交易的交易品种名称
   string trans_symbol=trans.symbol;
//--- 交易事务类型
   ENUM_TRADE_TRANSACTION_TYPE  trans_type=trans.type;
   switch(trans.type)
     {
      case  TRADE_TRANSACTION_POSITION:   //持仓变化
        {
         ulong pos_ID=trans.position;
         PrintFormat("MqlTradeTransaction: Position  #%I64u %s modified: SL=%.5f TP=%.5f",
                     pos_ID,trans_symbol,trans.price_sl,trans.price_tp);
        }
      break;
      case TRADE_TRANSACTION_REQUEST:     // sending a trade request
         PrintFormat("MqlTradeTransaction: TRADE_TRANSACTION_REQUEST");
         break;
      case TRADE_TRANSACTION_DEAL_ADD:    // 添加一个交易
        {
         ulong          lastDealID   =trans.deal;
         ENUM_DEAL_TYPE lastDealType =trans.deal_type;
         double        lastDealVolume=trans.volume;
         //--- 内部系统中的交易ID(Trade ID) - 由交易所分配的单号
         string Exchange_ticket="";
         if(HistoryDealSelect(lastDealID))
            Exchange_ticket=HistoryDealGetString(lastDealID,DEAL_EXTERNAL_ID);
         if(Exchange_ticket!="")
            Exchange_ticket=StringFormat("(Exchange deal=%s)",Exchange_ticket);
 
         PrintFormat("MqlTradeTransaction: %s deal #%I64u %s %s %.2f lot   %s",EnumToString(trans_type),
                     lastDealID,EnumToString(lastDealType),trans_symbol,lastDealVolume,Exchange_ticket);
        }
      break;
      case TRADE_TRANSACTION_HISTORY_ADD// 在历史中添加一个订单
        {
         //--- 内部系统中的订单ID - 由交易所分配的单号
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_FILLED)
           {
            if(HistoryOrderSelect(lastOrderID))
               Exchange_ticket=HistoryOrderGetString(lastOrderID,ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("(Exchange ticket=%s)",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),trans_symbol,EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
      default// 其他交易事务
        {
         //--- 内部系统中的订单ID - 由莫斯科交易所(Moscow Exchange)分配的单号
         string Exchange_ticket="";
         if(lastOrderState==ORDER_STATE_PLACED)
           {
            if(OrderSelect(lastOrderID))
               Exchange_ticket=OrderGetString(ORDER_EXTERNAL_ID);
            if(Exchange_ticket!="")
               Exchange_ticket=StringFormat("Exchange ticket=%s",Exchange_ticket);
           }
         PrintFormat("MqlTradeTransaction: %s order #%I64u %s %s   %s",EnumToString(trans_type),
                     lastOrderID,EnumToString(lastOrderType),EnumToString(lastOrderState),Exchange_ticket);
        }
      break;
     }
//--- 订单单号    
   ulong orderID_result=result.order;
   string retcode_result=GetRetcodeID(result.retcode);
   if(orderID_result!=0)
      PrintFormat("MqlTradeResult: order #%d retcode=%s ",orderID_result,retcode_result);
//---   
  }
//+------------------------------------------------------------------+
//| 将数字响应代码转换为字符串记忆                                       |
//+------------------------------------------------------------------+
string GetRetcodeID(int retcode)
  {
   switch(retcode)
     {
      case 10004: return("TRADE_RETCODE_REQUOTE");             break;
      case 10006: return("TRADE_RETCODE_REJECT");              break;
      case 10007: return("TRADE_RETCODE_CANCEL");              break;
      case 10008: return("TRADE_RETCODE_PLACED");              break;
      case 10009: return("TRADE_RETCODE_DONE");                break;
      case 10010: return("TRADE_RETCODE_DONE_PARTIAL");        break;
      case 10011: return("TRADE_RETCODE_ERROR");               break;
      case 10012: return("TRADE_RETCODE_TIMEOUT");             break;
      case 10013: return("TRADE_RETCODE_INVALID");             break;
      case 10014: return("TRADE_RETCODE_INVALID_VOLUME");      break;
      case 10015: return("TRADE_RETCODE_INVALID_PRICE");       break;
      case 10016: return("TRADE_RETCODE_INVALID_STOPS");       break;
      case 10017: return("TRADE_RETCODE_TRADE_DISABLED");      break;
      case 10018: return("TRADE_RETCODE_MARKET_CLOSED");       break;
      case 10019: return("TRADE_RETCODE_NO_MONEY");            break;
      case 10020: return("TRADE_RETCODE_PRICE_CHANGED");       break;
      case 10021: return("TRADE_RETCODE_PRICE_OFF");           break;
      case 10022: return("TRADE_RETCODE_INVALID_EXPIRATION");  break;
      case 10023: return("TRADE_RETCODE_ORDER_CHANGED");       break;
      case 10024: return("TRADE_RETCODE_TOO_MANY_REQUESTS");   break;
      case 10025: return("TRADE_RETCODE_NO_CHANGES");          break;
      case 10026: return("TRADE_RETCODE_SERVER_DISABLES_AT");  break;
      case 10027: return("TRADE_RETCODE_CLIENT_DISABLES_AT");  break;
      case 10028: return("TRADE_RETCODE_LOCKED");              break;
      case 10029: return("TRADE_RETCODE_FROZEN");              break;
      case 10030: return("TRADE_RETCODE_INVALID_FILL");        break;
      case 10031: return("TRADE_RETCODE_CONNECTION");          break;
      case 10032: return("TRADE_RETCODE_ONLY_REAL");           break;
      case 10033: return("TRADE_RETCODE_LIMIT_ORDERS");        break;
      case 10034: return("TRADE_RETCODE_LIMIT_VOLUME");        break;
      case 10035: return("TRADE_RETCODE_INVALID_ORDER");       break;
      case 10036: return("TRADE_RETCODE_POSITION_CLOSED");     break;
      default:
         return("TRADE_RETCODE_UNKNOWN="+IntegerToString(retcode));
         break;
     }
//---
  }

另见

OrderSendOrderSendAsyncOnTradeTransaction交易请求结构交易事务结构交易事务类型交易操作类型客户端事件