交易请求结构
交易请求结构 (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);
}
}
}
//+------------------------------------------------------------------+