|
|
EA调用TradeTransaction事件发生的OnTradeTransaction()函数较少在本网站述及,在此记录学习过程。
void OnTradeTransaction()
const MqlTradeTransaction& trans, // trade transaction structure
const MqlTradeRequest& request, // request structure
const MqlTradeResult& result // response structure
);
该函数有三个参数:
1. trans[in] MqlTradeTransaction 类型变量,它主要用来描述交易类型。
2. request[in] MqlTradeRequest 类型变量 ,描述启动一个交易的请求,它包含TRADE_TRANSACTION_REQUEST 类型的值。它是个ENUM_TRADE_REQUEST_ACTIONS 枚举变量,主要描述请求动作:deal,pending,sltp,modify,remove,closeby.
3. result[in] MqlTradeResult 类型变量,包含了发出请求交易的执行结果。它包含TRADE_TRANSACTION_RESULT类型的值,描述服务器对应收到的交易请求的返回结果:return code,deal ticket,order ticket(针对pending order),volume,deal price,bid,ask,comment(经纪商对操作的注释),request ID(发出交易请求时终端设定),code of error(外部交易系统返回的)
OnTradeTransaction() 在如下4种情况下被调用(总记录最近的),用来处理交易服务器发给终端的 TradeTransaction 事件:1. 从MQL5程序使用OrderSend()或OrderSendAsync()函数发出的交易请求和随后的执行;
2. 人工通过GUI发出的交易请求和随后的执行;
3. 在服务器上激活挂单;
4. 在服务器上执行操作;
MqlTradeTransaction 类型变量包括嗯呢trans变量,交易类型有枚举变量ENUM_TRADE_TRANSACTION_TYPE 描述,主要是Order_Add,Order_update(变更一个现存的order),Order_delete,deal_add(增加一个deal进入历史),deal_update,deal_delete,history_add(由于执行或取消而在交易历史中增加订单order),history_update(order历史中改变一个order),history_delete,position(与交易执行无关的开仓变化),request (服务器发出的交易请求已经被处理的通知以及处理结果已收到)。
在分析TradeTransaction时,为了收集必要的信息是有必要分析第二、三个参数(request和result)。例如:发出开仓请求将导致:1. 请求已被服务去收到进行处理;2. 开仓订单在账户里创建;3. 订单被执行;4. 执行的订单将被从活动状态移除;5.到订单历史中 ;6. 随后的交易将被增加的历史中;7. 在账户中新的仓位被创建。 所有这些过程都是 TradeTransaction 事件。
EA的OnTradeTransaction函数句柄将用来处理交易。终端不断处理进来的交易,所以交易账户状态也会随着OnTradeTransaction函数的运行而不断变化,程序会被通知所有这些交易事件。
交易队列长度了1024个单元,OnTradeTransaction会由于队列过长,新的交易会取代在队列中前面的交易。
不要与OnTrade函数混淆,OnTrade是用来处理订单、仓位和交易清单的改变,它只能由EA调用。OnTrade()函数句柄是在适当的 OnTradeTransaction() 函数调用后才被调用。一般来说, 函数OnTrade () 和 OnTradeTransaction () 调用数目并无精确的相关性。一个OnTrade() 调用对应了一个或几个OnTradeTransaction的调用.
以下是一个官网给出的例子:
//+------------------------------------------------------------------+
//| TradeTransaction function |
//+------------------------------------------------------------------+
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(); //自从系统开始所过去多少milliseconds,不关机会overfilled49.7天后
//--- if the last transaction was performed more than 1 second ago,
if(time-lasttime>1000)
{
counter=0; // then this is a new trade operation, an the counter can be reset
if(IS_DEBUG_MODE)
Print(" New trade operation");
}
lasttime=time;
counter++;
Print(counter,". ",__FUNCTION__);
//--- result of trade request execution
ulong lastOrderID =trans.order;
ENUM_ORDER_TYPE lastOrderType =trans.order_type;
ENUM_ORDER_STATE lastOrderState=trans.order_state;
//--- the name of the symbol, for which a transaction was performed
string trans_symbol=trans.symbol;
//--- type of transaction 这个是比较经典的使用方法从type入手
ENUM_TRADE_TRANSACTION_TYPE trans_type=trans.type;
switch(trans.type)
{
case TRADE_TRANSACTION_POSITION: // position modification
{
ulong pos_ID=trans.position;
PrintFormat("MqlTradeTransaction: Position #%d %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: // adding a trade
{
ulong lastDealID =trans.deal;
ENUM_DEAL_TYPE lastDealType =trans.deal_type;
double lastDealVolume=trans.volume;
//--- Trade ID in an external system - a ticket assigned by an exchange
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 #%d %s %s %.2f lot %s",EnumToString(trans_type),
lastDealID,EnumToString(lastDealType),trans_symbol,lastDealVolume,Exchange_ticket);
}
break;
case TRADE_TRANSACTION_HISTORY_ADD: // adding an order to the history
{
//--- order ID in an external system - a ticket assigned by an Exchange
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 #%d %s %s %s %s",EnumToString(trans_type),
lastOrderID,EnumToString(lastOrderType),trans_symbol,EnumToString(lastOrderState),Exchange_ticket);
}
break;
default: // other transactions
{
//--- order ID in an external system - a ticket assigned by 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 #%d %s %s %s",EnumToString(trans_type),
lastOrderID,EnumToString(lastOrderType),EnumToString(lastOrderState),Exchange_ticket);
}
break;
}
//--- order ticket
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);
//---
} 复制代码
以下是在N根K线后开单的使用OnTransactionTrade的虚拟程序的例子:-------One deal in N bars---------
#property version "1.00"
//--- input parameters
input uchar InpBars = 10; // 10根K线后下单
input ulong InpDeviation = 1000; // 偏差点数, in points (1.09123-1.08123=1000 points)
input ulong InpMagic = 2; // 幻数
//---
datetime m_last_deal_IN = 0; // "0" -> D'1970.01.01 00:00';
void OnTick()
{
//--- 在这写的入场或其他信号
if(PositionsTotal()==0)
{
datetime time[];
ArraySetAsSeries(time,true);
int start_pos=0; // 拷贝时间的开始位置
int count=InpBars+1; // 拷贝多少根K线
if(CopyTime(Symbol(),Period(),start_pos,count,time)!=count)
return;
//--- check
if(time[InpBars]>m_last_deal_IN)// 前第10根K线的开始时间已经大于最近一次开仓时间
{
//--- 开仓
}
}
}
void OnTradeTransaction(const MqlTradeTransaction &trans,
const MqlTradeRequest &request,
const MqlTradeResult &result)
{
ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
if(type==TRADE_TRANSACTION_DEAL_ADD)
{
long deal_ticket =0;
long deal_order =0;
long deal_time =0;
long deal_time_msc =0;
long deal_type =-1;
long deal_entry =-1;
long deal_magic =0;
long deal_reason =-1;
long deal_position_id =0;
double deal_volume =0.0;
double deal_price =0.0;
double deal_commission =0.0;
double deal_swap =0.0;
double deal_profit =0.0;
string deal_symbol ="";
string deal_comment ="";
string deal_external_id ="";
if(HistoryDealSelect(trans.deal))
{
deal_ticket =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
deal_order =HistoryDealGetInteger(trans.deal,DEAL_ORDER);
deal_time =HistoryDealGetInteger(trans.deal,DEAL_TIME);
deal_time_msc =HistoryDealGetInteger(trans.deal,DEAL_TIME_MSC);
deal_type =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
deal_entry =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
deal_magic =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
deal_reason =HistoryDealGetInteger(trans.deal,DEAL_REASON);
deal_position_id =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);
deal_volume =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
deal_price =HistoryDealGetDouble(trans.deal,DEAL_PRICE);
deal_commission =HistoryDealGetDouble(trans.deal,DEAL_COMMISSION);
deal_swap =HistoryDealGetDouble(trans.deal,DEAL_SWAP);
deal_profit =HistoryDealGetDouble(trans.deal,DEAL_PROFIT);
deal_symbol =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
deal_comment =HistoryDealGetString(trans.deal,DEAL_COMMENT);
deal_external_id =HistoryDealGetString(trans.deal,DEAL_EXTERNAL_ID);
}
else
return;
ENUM_DEAL_ENTRY enum_deal_entry=(ENUM_DEAL_ENTRY)deal_entry;
if(deal_symbol==Symbol() && deal_magic==InpMagic)
{
if(deal_type==DEAL_TYPE_BUY || deal_type==DEAL_TYPE_SELL)
{
if(deal_entry==DEAL_ENTRY_IN)
{
m_last_deal_IN=iTime(Symbol(),Period(),0);
}
}
}
}
}复制代码 |
|