EA开发系列--交易以及交易相关的回调函数
# 概要 EA在绝大多数场景下被用作自动化交易,因此,交易也就是EA的核心内容,这一节,介绍如何交易以及与交易相关的回调函数。这里包括两部分内容: 1、交易订单处理:挂单,现价单,止盈,止损等设定 2、OnTradeTransaction函数 3、历史订单处理
交易订单处理
在EA中,所有的订单处理都统一到OrderSend函数中完成,包括:现价,限价,止盈/止损设置等动作。它的原型如下:
bool OrderSend(
MqlTradeRequest& request, // 订单请求 MqlTradeResult& result // 处理结果);
与MQL4不同,OrderSend在MQL5中所有的订单参数都需要你构造一个MqlTradeRequest结构,具体处理结果可以在MqlTradeResult结构中查询(由系统填写),是否成功则通过返回的bool(布尔)类型来表示。 注意:每一次交易都涉及金额,因此下单后,我建议大家严格判断下单动作是否成功。
下面来解释一下MqlTradeRequest这个结构体,他的原型如下:
struct MqlTradeRequest
{
ENUM_TRADE_REQUEST_ACTIONS action; // 交易操作类型 ulong magic; // EA交易魔数字,多用于标识订单 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; // 订单终止期 string comment; // 订单注释 ulong position; // 持仓编号 ulong position_by; // 反向持仓编号 };
这个下单请求的结构体中包含了很多的内容,在我的工作范围内,有很多字段都是非必要不必填写的。 以下分享两个例子,它展示如何挂一个做多的单子和如何现价开仓:
//挂单做多bool openBuyLimitOrder(string input_symbol, ulong input_magic, double input_shares,
double order_price, double sl_price, double tp_price) {
MqlTradeRequest request = {};//初始化下单请求结构体,由代码填写 MqlTradeResult result = {};//初始化请求返回结构体,由系统填写后返回
request.action = TRADE_ACTION_PENDING;//挂单 request.type = ORDER_TYPE_BUY_LIMIT;//挂单做多, 限价做空用ORDER_TYPE_SELL_LIMIT request.expiration = ORDER_TIME_GTC;
request.symbol = input_symbol;//品种 request.volume = input_shares;//数量 request.magic = input_magic;//标识,魔数 request.deviation = 5;//支持的滑点 request.price = order_price;//挂单价格 if(sl_price > 0) {
request.sl = sl_price;//设置止损价格 }
if(tp_price > 0) {
request.tp = tp_price;//设置止盈价格 }
//发送请求 bool is_success = OrderSend(request, result);
if(is_success == false) {
PrintFormat("openBuyLimitOrder::OrderSend error %d", GetLastError());
PrintFormat("openBuyLimitOrder::retcode=%u deal=%I64u order=%I64u",
result.retcode, result.deal, result.order);
}
return is_success;
}//现价做多 bool openBuyOrder(string input_symbol, ulong input_magic,
double input_shares, double sl_price, double tp_price) {
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;//实时成交 request.type = ORDER_TYPE_BUY;//做多,做空用ORDER_TYPE_SELL request.symbol = input_symbol;
request.volume = input_shares;
request.magic = input_magic;
request.deviation = 5;
//做多用ASK(卖出价)入场,做空用BID(买入价)入场 request.price = SymbolInfoDouble(input_symbol, SYMBOL_ASK);
if(sl_price > 0) {
request.sl = sl_price;
}
if(tp_price > 0) {
request.tp = tp_price;
}
bool is_success = OrderSend(request, result);
if(is_success == false) {
PrintFormat("openBuyOrder::OrderSend error %d", GetLastError());
PrintFormat("openBuyOrder::retcode=%u deal=%I64u order=%I64u", result.retcode, result.deal, result.order);
}
return is_success;
}
上面两个函数展示了4种比较常见的交易场景,其中魔数等字段是可以不填写的。它们的区别也就体现在“action”和“type”两个字段的不同。
OrderSend执行以后,你就会通过其布尔返回值得到下单是否成功,但是无论是否成功MqlTradeResult结构体中都会被填充数据,它展示了执行的细节。那么MqlTradeResult结构体包含的内容有:
struct MqlTradeResult
{
uint retcode; // 操作返回代码 ulong deal; // 交易订单号,如果完成的话 ulong order; // 订单号,如果下订单的话 double volume; // 交易交易量,经纪人确认的 double price; // 交易的真实价格 double bid; // 当前买入价 double ask; // 当前卖出价 string comment; // 注释 (默认填充操作描述) uint request_id; // 分派期间通过程序端设置Request ID
uint retcode_external; // 返回外部交易系统代码 };
在这个结构体里你可以找到本次交易中涉及的返回结果细节信息。其中“request_id”是由MT5交易系统分配的。“retcode”标识当前操作的结果码,这个结果码由MT5内部定义。
交易订单处理流程回调函数(OnTradeTransaction)
当你执行了“OrderSend”函数以后,你的请求就会交由MT5处理,MT5出了的过程会通过这个函数通知EA来处理。如果你关心这个中间过程,你就需要在EA中实现这个函数。它的原型如下:
void OnTradeTransaction(
const MqlTradeTransaction& trans, // 交易动作结构
const MqlTradeRequest& request, // 交易请求结构
const MqlTradeResult& result // 请求结果结构
);
以下是一个交易流程的日志:
OnTradeTransaction::Begin=======================Transaction:[TRADE_TRANSACTION_ORDER_ADD, Symbol: EURCHF, Deal ticket: 0, Deal type: DEAL_TYPE_BUY, Order ticket: 1100221132, Order type: ORDER_TYPE_BUY_LIMIT, Order state: ORDER_STATE_STARTED, Order time type: ORDER_TIME_GTC, Order expiration: 1970.01.01 00:00, Price: 1.07145, Price trigger: 0, Stop Loss: 1.06994, Take Profit: 1.07557, Volume: 0.3]Request:[ENUM_TRADE_REQUEST_ACTIONS::0, Symbol: , Magic Number: 0, Order ticket: 0, Order type: ORDER_TYPE_BUY, Order filling: ORDER_FILLING_FOK, Order time type: ORDER_TIME_GTC, Order expiration: 1970.01.01 00:00, Price: 0, Deviation points: 0, Stop Loss: 0, Take Profit: 0, Stop Limit: 0, Volume: 0, Comment: ]Result:[Retcode 0, Request ID: 0, Order ticket: 0, Deal ticket: 0, Volume: 0, Price: 0, Ask: 0, Bid: 0, Comment: ]OnTradeTransaction::End=========================OnTradeTransaction::Begin=======================Transaction:[TRADE_TRANSACTION_ORDER_UPDATE, Symbol: EURCHF, Deal ticket: 0, Deal type: DEAL_TYPE_BUY, Order ticket: 1100221132, Order type: ORDER_TYPE_BUY_LIMIT, Order state: ORDER_STATE_PLACED, Order time type: ORDER_TIME_GTC, Order expiration: 1970.01.01 00:00, Price: 1.07145, Price trigger: 0, Stop Loss: 1.06994, Take Profit: 1.07557, Volume: 0.3]Request:[ENUM_TRADE_REQUEST_ACTIONS::0, Symbol: , Magic Number: 0, Order ticket: 0, Order type: ORDER_TYPE_BUY, Order filling: ORDER_FILLING_FOK, Order time type: ORDER_TIME_GTC, Order expiration: 1970.01.01 00:00, Price: 0, Deviation points: 0, Stop Loss: 0, Take Profit: 0, Stop Limit: 0, Volume: 0, Comment: ]Result:[Retcode 0, Request ID: 0, Order ticket: 0, Deal ticket: 0, Volume: 0, Price: 0, Ask: 0, Bid: 0, Comment: ]OnTradeTransaction::End=========================Transaction:[TRADE_TRANSACTION_REQUEST, Symbol: , Deal ticket: 0, Deal type: DEAL_TYPE_BUY, Order ticket: 0, Order type: ORDER_TYPE_BUY, Order state: ORDER_STATE_STARTED, Order time type: ORDER_TIME_GTC, Order expiration: 1970.01.01 00:00, Price: 0, Price trigger: 0, Stop Loss: 0, Take Profit: 0, Volume: 0]Request:[TRADE_ACTION_PENDING, Symbol: EURCHF, Magic Number: 20210801, Order ticket: 1100221132, Order type: ORDER_TYPE_BUY_LIMIT, Order filling: ORDER_FILLING_RETURN, Order time type: ORDER_TIME_GTC, Order expiration: 1970.01.01 00:00, Price: 1.07145, Deviation points: 5, Stop Loss: 1.06994, Take Profit: 1.07557, Stop Limit: 0, Volume: 0.3, Comment: ]Result:[Retcode 10009, Request ID: 1, Order ticket: 1100221132, Deal ticket: 0, Volume: 0.3, Price: 0, Ask: 0, Bid: 0, Comment: ]OnTradeTransaction::End=========================
由此可见,“OrderSend”以后,发生了三个步骤,每一个步骤包含了三个内容,分别是:交易信息,交易请求,请求结果。这三个步骤分别是: 1、新增新的持仓订单(TRADE_TRANSACTION_ORDER_ADD) 2、更新订单状态(TRADE_TRANSACTION_ORDER_ADD) 3、收到交易服务器的结果(TRADE_TRANSACTION_REQUEST)