交易请求结构 (MqlTradeRequest)

客户端与交易服务器执行其他安置操作相互作用,通过使用交易请求来执行。交易请求由特殊预定MqlTradeRequest类型的结构来体现,包含必要的执行交易订单。该请求执行结果由MqlTradeResult的类型结构来表示。

struct MqlTradeRequest
  {
   ENUM_TRADE_REQUEST_ACTIONS    action;           // 交易操作类型
   ulong                         magic;            // EA交易 ID (幻数)
   ulong                         order;            // 订单号
   string                        symbol;           // 交易的交易品种
   double                        volume;           // 一手需求的交易量
   double                        price;            // 价格
   double                        stoplimit;        // 订单止损限价点位
   double                        sl;               // 订单止损价位点位
   double                        tp;               // 订单盈利价位点位
   ulong                         deviation;        // 需求价格最可能的偏差
   ENUM_ORDER_TYPE               type;             // 订单类型
   ENUM_ORDER_TYPE_FILLING       type_filling;     // 订单执行类型
   ENUM_ORDER_TYPE_TIME          type_time;        // 订单执行时间
   datetime                      expiration;       // 订单终止期 (为 ORDER_TIME_SPECIFIED 类型订单)
   string                        comment;          // 订单注释
   ulong                         position;         // 持仓编号
   ulong                         position_by;      // 反向持仓编号
  };

字段描述

字段 描述
操作 交易操作类型,可以是 ENUM_TRADE_REQUEST_ACTIONS 项目值中的一个。
幻数 EA交易ID,允许操作分析交易命令过程,当发送交易请求时,每个EA交易都能建立自己独特的ID
订单 订单命令按钮,用来修改待办订单。
交易品种 交易品种命令,不需要修改命令和关闭放置操作。
交易量 要求命令成交手数,标识每笔订单真实成交量取决于订单执行类型
价格 价格,必须执行到达命令,交易品种的市场底单,它的执行类型是“市场执行”(SYMBOL_TRADE_EXECUTION_MARKET)TRADE_ACTION_DEAL 类型,不要求价格说明。
stoplimit 价格价值,当价格达到price值时(必要条件),Limit安置待办订单,直到待办订单部能安置。  
sl 在不利于价格活动的情况下的止损数值
tp 在优惠价格活动的情况下目标数值
偏差 最大价格偏差,指定在 points
类型 命令类型,可以是 ENUM_ORDER_TYPE项目值中的一个  
type_filling 命令执行类型,可以是 ENUM_ORDER_TYPE_FILLING 项目值中的一个
type_time 命令终结类型,可以是 ENUM_ORDER_TYPE_TIME 项目值中的一个
到期 命令终结期限( ORDER_TIME_SPECIFIED 命令类型)
注释 命令注解文本
当在锁仓系统更改持仓或平仓时,要确保指明其单号(MqlTradeRequest::position)。而在单边系统,虽然是通过交易品种名称来确定持仓,也可以指明单号。

发送执行命令 交易操作 需要使用 OrderSend() 函数。对于每个交易操作来说都需要指定强制域;也需要填满可选域。有7个可行情况发送交易命令:

请求执行

开仓交易命令在执行请求模式中(交易根据现行价格要求),需要指定如下9种域:

  • 执行
  • 交易品种
  • 交易量
  • 价格
  • 止损水平
  • 盈利水平
  • 误差
  • 类型
  • _filling类型

也有可能指定“magic”和“comment” 域值

立即执行

开仓交易命令在立即执行模式中(流动价格交易),要求如下9种域的规格:

  • 执行
  • 交易品种
  • 交易量
  • 价格
  • 止损水平
  • 盈利水平
  • 误差
  • 类型
  • _filling类型

有可能指定“magic” 和“comment”域值。

买卖执行

开仓交易命令在买卖执行方式中,要求指定如下5中域:

  • 执行
  • 交易品种
  • 交易量
  • 类型
  • _filling类型

也有可能指定“magic” 和“comment”域值。

交易执行

这是一个在交易执行模式下持仓的交易订单。它需要指定以下5个字段:

  • 执行
  • 交易品种
  • 交易量
  • 类型
  • _filling类型

也有可能指定“magic” 和“comment”域值。

打开买入持仓TRADE_ACTION_DEAL 交易操作的示例:

#define EXPERT_MAGIC 123456   // EA交易的幻数

//+------------------------------------------------------------------+

//| 打开买入持仓                                                       |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- 声明并初始化交易请求和交易请求结果

   MqlTradeRequest request={};

   MqlTradeResult  result={};

//--- 请求的参数

   request.action   =TRADE_ACTION_DEAL;                     // 交易操作类型

   request.symbol   =Symbol();                              // 交易品种

   request.volume   =0.1;                                   // 0.1手交易量 

   request.type     =ORDER_TYPE_BUY;                        // 订单类型

   request.price    =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // 持仓价格

   request.deviation=5;                                     // 允许价格偏差

   request.magic    =EXPERT_MAGIC;                          // 订单幻数

//--- 发送请求

   if(!OrderSend(request,result))

      PrintFormat("OrderSend error %d",GetLastError());     // 如果不能发送请求,输出错误代码

//--- 操作信息

   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

  }

//+------------------------------------------------------------------+

 
打开卖出持仓TRADE_ACTION_DEAL 交易操作的示例:

#define EXPERT_MAGIC 123456   // EA交易的幻数

//+------------------------------------------------------------------+

//| 打开卖出持仓                                                       |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- 声明并初始化交易请求和交易请求结果

   MqlTradeRequest request={};

   MqlTradeResult  result={};

//--- 请求参数

   request.action   =TRADE_ACTION_DEAL;                     // 交易操作类型

   request.symbol   =Symbol();                              // 交易品种

   request.volume   =0.2;                                   // 0.2 手交易量

   request.type     =ORDER_TYPE_SELL;                       // 订单类型

   request.price    =SymbolInfoDouble(Symbol(),SYMBOL_BID); // 持仓价格

   request.deviation=5;                                     // 允许价格偏差

   request.magic    =EXPERT_MAGIC;                          // 订单幻数

//--- 发送请求

   if(!OrderSend(request,result))

      PrintFormat("OrderSend error %d",GetLastError());     // 如果不能发送请求,输出错误代码

//--- 操作信息

   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

  }

//+------------------------------------------------------------------+

 
平仓TRADE_ACTION_DEAL 交易操作的示例:

#define EXPERT_MAGIC 123456   // EA交易的幻数

//+------------------------------------------------------------------+

//| 关闭全部持仓                                                       |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- 声明并初始化交易请求和交易请求结果

   MqlTradeRequest request;

   MqlTradeResult  result;

   int total=PositionsTotal(); // 持仓数   

//--- 重做所有持仓

   for(int i=total-1; i>=0; i--)

     {

      //--- 订单的参数

      ulong  position_ticket=PositionGetTicket(i);                                      // 持仓价格

      string position_symbol=PositionGetString(POSITION_SYMBOL);                        // 交易品种 

      int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS);              // 小数位数

      ulong  magic=PositionGetInteger(POSITION_MAGIC);                                  // 持仓的幻数

      double volume=PositionGetDouble(POSITION_VOLUME);                                 // 持仓交易量

      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);    // 持仓类型

      //--- 输出持仓信息

      PrintFormat("#%I64u %s  %s  %.2f  %s [%I64d]",

                  position_ticket,

                  position_symbol,

                  EnumToString(type),

                  volume,

                  DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),

                  magic);

      //--- 如果幻数匹配

      if(magic==EXPERT_MAGIC)

        {

         //--- 归零请求和结果值

         ZeroMemory(request);

         ZeroMemory(result);

         //--- 设置操作参数

         request.action   =TRADE_ACTION_DEAL;        // 交易操作类型

         request.position =position_ticket;          // 持仓价格

         request.symbol   =position_symbol;          // 交易品种 

         request.volume   =volume;                   // 持仓交易量

         request.deviation=5;                        // 允许价格偏差

         request.magic    =EXPERT_MAGIC;             // 持仓幻数

         //--- 根据持仓类型设置价格和订单类型 

         if(type==POSITION_TYPE_BUY)

           {

            request.price=SymbolInfoDouble(position_symbol,SYMBOL_BID);

            request.type =ORDER_TYPE_SELL;

           }

         else

           {

            request.price=SymbolInfoDouble(position_symbol,SYMBOL_ASK);

            request.type =ORDER_TYPE_BUY;

           }

         //--- 输出关闭信息

         PrintFormat("Close #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));

         //--- 发送请求

         if(!OrderSend(request,result))

            PrintFormat("OrderSend error %d",GetLastError());  // 如果不能发送请求,输出错误代码

         //--- 操作信息   

         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

         //---

        }

     }

  }

//+------------------------------------------------------------------+

 

SL & TP修正

交易命令在StopLoss 和/或 TakeProfit 价格水平上修改,要求指定如下4种域:

  • 执行
  • 交易品种
  • 止损水平
  • 盈利水平

更改持仓止损和止赢值的 TRADE_ACTION_SLTP 交易操作的示例:

#define EXPERT_MAGIC 123456  // EA交易的幻数

//+------------------------------------------------------------------+

//| 更改持仓的止损和止赢                                                |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- 声明并初始化交易请求和交易请求结果

   MqlTradeRequest request;

   MqlTradeResult  result;

   int total=PositionsTotal(); // 持仓数   

//--- 重做所有持仓

   for(int i=0; i<total; i++)

     {

      //--- 订单的参数

      ulong  position_ticket=PositionGetTicket(i);// 持仓价格

      string position_symbol=PositionGetString(POSITION_SYMBOL); // 交易品种 

      int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // 小数位数

      ulong  magic=PositionGetInteger(POSITION_MAGIC); // 持仓的幻数

      double volume=PositionGetDouble(POSITION_VOLUME);    // 持仓交易量

      double sl=PositionGetDouble(POSITION_SL);  // 持仓止损

      double tp=PositionGetDouble(POSITION_TP);  // 持仓止赢

      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);  // type of the position

      //--- 输出持仓信息

      PrintFormat("#%I64u %s  %s  %.2f  %s  sl: %s  tp: %s  [%I64d]",

                  position_ticket,

                  position_symbol,

                  EnumToString(type),

                  volume,

                  DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),

                  DoubleToString(sl,digits),

                  DoubleToString(tp,digits),

                  magic);

      //--- 如果幻数匹配,不定义止损和止赢

      if(magic==EXPERT_MAGIC && sl==0 && tp==0)

        {

         //--- 计算当前价格水平

         double price=PositionGetDouble(POSITION_PRICE_OPEN);

         double bid=SymbolInfoDouble(position_symbol,SYMBOL_BID);

         double ask=SymbolInfoDouble(position_symbol,SYMBOL_ASK);

         int    stop_level=(int)SymbolInfoInteger(position_symbol,SYMBOL_TRADE_STOPS_LEVEL);

         double price_level;

         //--- 如果最小值被接受,那么当前平仓价的点数偏距不设置

         if(stop_level<=0)

            stop_level=150; // 设置当前平仓价的150点偏距

         else

            stop_level+=50; // 为了可靠性而设置偏距到(SYMBOL_TRADE_STOPS_LEVEL + 50) 点

 

         //--- 计算并凑整止损和止赢值

         price_level=stop_level*SymbolInfoDouble(position_symbol,SYMBOL_POINT);

         if(type==POSITION_TYPE_BUY)

           {

            sl=NormalizeDouble(bid-price_level,digits);

            tp=NormalizeDouble(bid+price_level,digits);

           }

         else

           {

            sl=NormalizeDouble(ask+price_level,digits);

            tp=NormalizeDouble(ask-price_level,digits);

           }

         //--- 归零请求和结果值

         ZeroMemory(request);

         ZeroMemory(result);

         //--- 设置操作参数

         request.action  =TRADE_ACTION_SLTP; // 交易操作类型

         request.position=position_ticket;   // 持仓价格

         request.symbol=position_symbol;     // 交易品种 

         request.sl      =sl;                // 持仓止损

         request.tp      =tp;                // 持仓止赢

         request.magic=EXPERT_MAGIC;         // 持仓的幻数

         //--- 输出更改信息

         PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));

         //--- 发送请求

         if(!OrderSend(request,result))

            PrintFormat("OrderSend error %d",GetLastError());  // 如果不能发送请求,输出错误代码

         //--- 操作信息   

         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

        }

     }

  }

//+------------------------------------------------------------------+

 

待办订单

交易命令安置在待办订单中,要求指定如下11种域:

  • 行动
  • 交易品种
  • 交易量
  • 价格
  • 限制停止
  • 止损水平
  • 盈利水平
  • 类型
  • _filling 类型
  • _time 类型
  • 期满

也有可能指定“magic” 和“comment”域值。

下挂单 TRADE_ACTION_PENDING 交易操作的示例:

#property description "Example of placing pending orders"

#property script_show_inputs

#define EXPERT_MAGIC 123456                             // EA交易的幻数

input ENUM_ORDER_TYPE orderType=ORDER_TYPE_BUY_LIMIT;   // 订单类型

//+------------------------------------------------------------------+

//| 下挂单                                                            |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- 声明并初始化交易请求和交易请求结果

   MqlTradeRequest request={};

   MqlTradeResult  result={};

//--- 下挂单的参数

   request.action   =TRADE_ACTION_PENDING;                             // 交易操作类型

   request.symbol   =Symbol();                                         // 交易品种

   request.volume   =0.1;                                              //0.1手交易量

   request.deviation=2;                                                // 允许价格偏差

   request.magic    =EXPERT_MAGIC;                                     // 订单幻数

   int offset = 50;                                                    // 以点数从当前价抵消下单

   double price;                                                       // 订单触动价

   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);                // value of point

   int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);                // 小数位数 (精确度)

   //--- 检查操作类型

   if(orderType==ORDER_TYPE_BUY_LIMIT)

     {

      request.type     =ORDER_TYPE_BUY_LIMIT;                          // 订单类型

      price=SymbolInfoDouble(Symbol(),SYMBOL_ASK)-offset*point;        // 持仓价格 

      request.price    =NormalizeDouble(price,digits);                 //正常开盘价 

     }

   else if(orderType==ORDER_TYPE_SELL_LIMIT)

     {

      request.type     =ORDER_TYPE_SELL_LIMIT;                          // order type

      price=SymbolInfoDouble(Symbol(),SYMBOL_BID)+offset*point;         // 持仓价 

      request.price    =NormalizeDouble(price,digits);                  // 正常开盘价 

     }

   else if(orderType==ORDER_TYPE_BUY_STOP)

     {

      request.type =ORDER_TYPE_BUY_STOP;                                // 订单类型

      price        =SymbolInfoDouble(Symbol(),SYMBOL_ASK)+offset*point; // 开盘价 

      request.price=NormalizeDouble(price,digits);                      // 正常开盘价 

     }

   else if(orderType==ORDER_TYPE_SELL_STOP)

     {

      request.type     =ORDER_TYPE_SELL_STOP;                           // 订单类型

      price=SymbolInfoDouble(Symbol(),SYMBOL_BID)-offset*point;         // 开盘价 

      request.price    =NormalizeDouble(price,digits);                  // 正常开盘价 

     }

   else Alert("This example is only for placing pending orders");   // 如果没有挂单被选择

//--- 发送请求

   if(!OrderSend(request,result))

      PrintFormat("OrderSend error %d",GetLastError());                 // 如果不能发送请求,输出错误代码

//--- 操作信息

   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

  }

//+------------------------------------------------------------------+

 

修改待办订单

交易命令在待办订单价格中修改,它要求指定如下7种域:

  • 行动
  • 命令
  • 价格
  • 止损水平
  • 盈利水平
  • _time类型
  • 期满

更改挂单价格水平的 TRADE_ACTION_MODIFY 交易操作的示例:

#define EXPERT_MAGIC 123456  // EA交易的幻数

//+------------------------------------------------------------------+

//| 更改挂单                                                          |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- 声明并初始化交易请求和交易请求结果

   MqlTradeRequest request={};

   MqlTradeResult  result={};

   int total=OrdersTotal(); // 已下挂单的总数

//--- 重做所有已下的挂单

   for(int i=0; i<total; i++)

     {

      //--- 订单参数

      ulong  order_ticket=OrderGetTicket(i);                             // 订单价格

      string order_symbol=Symbol();                                      // 交易品种

      int    digits=(int)SymbolInfoInteger(order_symbol,SYMBOL_DIGITS);  // 小数位数

      ulong  magic=OrderGetInteger(ORDER_MAGIC);                         // 订单的幻数

      double volume=OrderGetDouble(ORDER_VOLUME_CURRENT);                // 订单的当前交易量

      double sl=OrderGetDouble(ORDER_SL);                                // 订单的当前止损

      double tp=OrderGetDouble(ORDER_TP);                                // 订单的当前止赢

      ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); // 订单类型

      int offset = 50;                                                   // 以点数从当前价抵消下单

      double price;                                                      // 订单触动价

      double point=SymbolInfoDouble(order_symbol,SYMBOL_POINT);          // 点值

      //--- 输出订单信息

      PrintFormat("#%I64u %s  %s  %.2f  %s  sl: %s  tp: %s  [%I64d]",

                  order_ticket,

                  order_symbol,

                  EnumToString(type),

                  volume,

                  DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),

                  DoubleToString(sl,digits),

                  DoubleToString(tp,digits),

                  magic);

      //--- 如果幻数匹配,不定义止损和止赢

      if(magic==EXPERT_MAGIC && sl==0 && tp==0)

        {

         request.action=TRADE_ACTION_MODIFY;                           // 交易操作类型

         request.order = OrderGetTicket(i);                            // 订单价格

         request.symbol   =Symbol();                                   // symbol

         request.deviation=5;                                          // 允许价格偏差

        //--- 根据持仓类型设置价格水平,订单的止损和止赢

         if(type==ORDER_TYPE_BUY_LIMIT)

           {

            price = SymbolInfoDouble(Symbol(),SYMBOL_ASK)-offset*point;

            request.tp = NormalizeDouble(price+offset*point,digits);

            request.sl = NormalizeDouble(price-offset*point,digits);

            request.price    =NormalizeDouble(price,digits);                // 正常开盘价

           }

         else if(type==ORDER_TYPE_SELL_LIMIT)

           {

           price = SymbolInfoDouble(Symbol(),SYMBOL_BID)+offset*point;

            request.tp = NormalizeDouble(price-offset*point,digits);

            request.sl = NormalizeDouble(price+offset*point,digits);

            request.price    =NormalizeDouble(price,digits);                 // 正常开盘价

           }

         else if(type==ORDER_TYPE_BUY_STOP)

           {

           price = SymbolInfoDouble(Symbol(),SYMBOL_ASK)+offset*point;

            request.tp = NormalizeDouble(price+offset*point,digits);

            request.sl = NormalizeDouble(price-offset*point,digits);

            request.price    =NormalizeDouble(price,digits);                 // 正常开盘价

           }

         else if(type==ORDER_TYPE_SELL_STOP)

           {

           price = SymbolInfoDouble(Symbol(),SYMBOL_BID)-offset*point;

            request.tp = NormalizeDouble(price-offset*point,digits);

            request.sl = NormalizeDouble(price+offset*point,digits);

            request.price    =NormalizeDouble(price,digits);                 // 正常开盘价

           }

         //--- 发送请求

         if(!OrderSend(request,result))

            PrintFormat("OrderSend error %d",GetLastError());  // 如果不能发送请求,输出错误代码

         //--- 操作信息   

         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

         //--- 归零请求和结果值

         ZeroMemory(request);

         ZeroMemory(result);

        }

     }

  }

//+------------------------------------------------------------------+

 

删除协办订单

交易命令删除一个待办订单,它要求指定如下2种域

  • 行动
  • 命令

删除挂单的TRADE_ACTION_REMOVE 交易操作的示例:

#define EXPERT_MAGIC 123456  // EA交易的幻数

//+------------------------------------------------------------------+

//| 删除挂单                                                          |

//+------------------------------------------------------------------+

void OnStart()

  {

//--- 声明并初始化交易请求和交易请求结果

   MqlTradeRequest request={};

   MqlTradeResult  result={};

   int total=OrdersTotal(); // 下挂单的总数

//--- 重做所有已下的挂单

   for(int i=total-1; i>=0; i--)

     {

      ulong  order_ticket=OrderGetTicket(i);                   // order ticket

      ulong  magic=OrderGetInteger(ORDER_MAGIC);               // 订单的幻数

      //--- 如果幻数匹配

      if(magic==EXPERT_MAGIC)

        {

         //--- 归零请求和结果值

         ZeroMemory(request);

         ZeroMemory(result);

         //--- 设置持仓参数     

         request.action=TRADE_ACTION_REMOVE;                   // 交易操作的类型

         request.order = order_ticket;                         // 订单价格

         //--- 发送请求

         if(!OrderSend(request,result))

            PrintFormat("OrderSend error %d",GetLastError());  // 如果不能发送请求,输出错误代码

         //--- 操作信息   

         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);

        }

     }

  }

//+------------------------------------------------------------------+

 

另见

结构和类交易函数订单属性