高手来说说,如何实现平仓后就触发另一个函数的执行?
OnTradeTransaction()这函数我用的不太明白
无论平仓,开仓,修改,挂单,OnTradeTransaction()都会被触发,此函数本身就是一个交易事件,和它最象的就是OnTrade()
我对这个函数也有不同的地方,但是你这个问题可以这样,不排除还有其他更简洁办法
先用 trans.type 判断事件,找到 TRADE_TRANSACTION_DEAL_ADD 这个事件 属于是在历史中添加了成交单的事件
然后用 trans.deal 作为基准,获取 DEAL_ENTRY 的类型,属于 DEAL_ENTRY_OUT的就是平仓单了
ulong lastDealID = trans.deal; if(trans.type == TRADE_TRANSACTION_DEAL_ADD) { if(HistoryDealSelect(lastDealID)) //选中成交单 { ENUM_DEAL_ENTRY entry = ENUM_DEAL_ENTRY(HistoryDealGetInteger(lastDealID,DEAL_ENTRY)); if( entry == DEAL_ENTRY_OUT ) { //相关操作 } } }
但是要注意,这个 OnTradeTransaction() 的特殊地方,如果在其他函数中,有对交易操作过多次(例如开仓,挂单,平仓,修改止损止盈),这个 OnTradeTransaction()会在其他操作全部完成后才会进来
换句话说就是,如果Ontick() 里面连续开两单,那么开了两单后才会进入 OnTradeTransaction() 并且会进入2次,并不会开一单进入一次 OnTradeTransaction()
我对这个函数也有不同的地方,但是你这个问题可以这样,不排除还有其他更简洁办法
先用 trans.type 判断事件,找到 TRADE_TRANSACTION_DEAL_ADD 这个事件 属于是在历史中添加了成交单的事件
然后用 trans.deal 作为基准,获取 DEAL_ENTRY 的类型,属于 DEAL_ENTRY_OUT的就是平仓单了
但是要注意,这个 OnTradeTransaction() 的特殊地方,如果在其他函数中,有对交易操作过多次(例如开仓,挂单,平仓,修改止损止盈),这个 OnTradeTransaction()会在其他操作全部完成后才会进来
换句话说就是,如果Ontick() 里面连续开两单,那么开了两单后才会进入 OnTradeTransaction() 并且会进入2次,并不会开一单进入一次 OnTradeTransaction()
很好,试了可以。实际我最终目的是要在检测到出场订单后,要获取这个出场订单对应的in入场订单的comment注释,如何实现?
出场订单的 comment都是空的,所以过滤掉空的,往前遍历就能找到 入场订单的comment注释,但如果同一标的前后入场不同的多个机会, 再往前遍历到入场订单的comment注释就可能与出场订单不是一一对应了,所以如何获取这个出场订单相对应的in入场订单的comment注释?或者如何实现让out出场单子的 comment注释与in 入场订单的 comment注释一致,而不是空?
很好,试了可以。实际我最终目的是要在检测到出场订单后,要获取这个出场订单对应的in入场订单的comment注释,如何实现?
出场订单的 comment都是空的,所以过滤掉空的,往前遍历就能找到 入场订单的comment注释,但如果同一标的前后入场不同的多个机会, 再往前遍历到入场订单的comment注释就可能与出场订单不是一一对应了,所以如何获取这个出场订单相对应的in入场订单的comment注释?或者如何实现让out出场单子的 comment注释与in 入场订单的 comment注释一致,而不是空?
可能你们把问题想复杂了,如果你只是单纯的想获取out(平仓)类型单子和它对应in(开仓)类型单子的注释, 那么这个就比较简单,无需用到 OnTradeTransaction() 或者 OnTrade()函数了。
首先,你先要知道你将要平仓的执仓订单编号,进行平仓操作(具体如何获取,这里就不详细说明了,我相信方法你应该会)
不喜勿喷^_^
//+------------------------------------------------------------------+ //| Test1.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> CTrade m_trade; CDealInfo m_deal; CSymbolInfo m_symbol; CPositionInfo m_pos; //+------------------------------------------------------------------+ //| EA交易初始化函数 | //+------------------------------------------------------------------+ int OnInit() { //--- EventSetMillisecondTimer(1); if(!m_symbol.Name(_Symbol)) // sets symbol name return(INIT_FAILED); RefreshRates(); m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(m_symbol.Name()); m_trade.SetDeviationInPoints(INT_MAX); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); } //+------------------------------------------------------------------+ //| EA报价函数 | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool RefreshRates(void) { //--- refresh rates if(!m_symbol.RefreshRates()) { Print("RefreshRates error"); return(false); } //--- protection against the return value of "zero" if(m_symbol.Ask() == 0 || m_symbol.Bid() == 0) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| 平仓并获取对应in入场的单子的注释 | //+------------------------------------------------------------------+ string ClosePosition(const long ticket, const long magic) { if(!m_pos.SelectByTicket(ticket)) // 如果单子不存在,返回空字符串 return(NULL); datetime open_time = m_pos.Time(); // 将被平仓单子的入场时间 m_trade.SetExpertMagicNumber(magic); // 设置被平仓单子的魔术编号 if(m_trade.PositionClose(ticket)) // 执行平仓 { HistorySelect(open_time, TimeTradeServer()); // 从被平仓单子的入场时间开始搜索 int total = HistoryDealsTotal(); // 获取历史成交总数 for(int i = 0; i < total; i++) // 按顺序搜索历史 { if(!m_deal.SelectByIndex(i)) // 如果选中失败,继续 continue; if(m_deal.Symbol() != m_symbol.Name()) // 如果是当前货币名称,继续 continue; if(m_deal.Entry() != DEAL_ENTRY_IN) // 如果是in类型单子,继续 continue; if(m_deal.Order() != ticket) // 如果订单编号匹配,继续 continue; return(m_deal.Comment()); // 返回注释并退出搜索 } } return(NULL); // 平仓失败,返回空字符串 } //+------------------------------------------------------------------+
可能你把问题想复杂了,如果你只是单纯的想获取out(平仓)类型单子和它对应in(开仓)类型单子的注释, 那么这个就比较简单,无需用到 OnTradeTransaction() 或者 OnTrade()函数了。
首先,你先要知道你将要平仓的订单编号,进行平仓操作(具体如何获取,这里就不详细说明了,我相信方法你应该会)
不喜勿喷^_^
//+------------------------------------------------------------------+ //| ProjectName | //| Copyright 2020, CompanyName | //| http://www.companyname.net | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> CTrade m_trade; CDealInfo m_deal; CSymbolInfo m_symbol; CPositionInfo m_pos; //+------------------------------------------------------------------+ //| EA交易初始化函数 | //+------------------------------------------------------------------+ int OnInit() { //--- EventSetMillisecondTimer(1); if(!m_symbol.Name(_Symbol)) // sets symbol name return(INIT_FAILED); RefreshRates(); m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(m_symbol.Name()); m_trade.SetDeviationInPoints(INT_MAX); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTick() { if(HistorySelect(0,TimeCurrent())) { int ht=HistoryDealsTotal(); for(int j=ht-1; j>=0; j--) { if(HistoryDealGetTicket(j)>0 && HistoryDealGetString(HistoryDealGetTicket(j),DEAL_SYMBOL)==Symbol()) { string com= ClosePosition(HistoryDealGetTicket(j),NULL); Print(com); } } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer() { } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool RefreshRates(void) { //--- refresh rates if(!m_symbol.RefreshRates()) { Print("RefreshRates error"); return(false); } //--- protection against the return value of "zero" if(m_symbol.Ask() == 0 || m_symbol.Bid() == 0) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| 平仓并获取对应in入场的单子的注释 | //+------------------------------------------------------------------+ string ClosePosition(const long ticket, const long magic) { if(!m_pos.SelectByTicket(ticket)) // 如果单子不存在,返回空字符串 return(NULL); datetime open_time = m_pos.Time(); // 将被平仓单子的入场时间 m_trade.SetExpertMagicNumber(magic); // 设置被平仓单子的魔术编号 if(m_trade.PositionClose(ticket)) // 执行平仓 { HistorySelect(open_time, TimeTradeServer()); // 从被平仓单子的入场时间开始搜索 int total = HistoryDealsTotal(); // 获取历史成交总数 for(int i = 0; i < total; i++) // 按顺序搜索历史 { if(!m_deal.SelectByIndex(i)) // 如果选中失败,继续 continue; if(m_deal.Symbol() != m_symbol.Name()) // 如果是当前货币名称,继续 continue; if(m_deal.Entry() != DEAL_ENTRY_IN) // 如果是in类型单子,继续 continue; if(m_deal.Order() != ticket) // 如果订单编号匹配,继续 continue; return(m_deal.Comment()); // 返回注释并退出搜索 } } return(NULL); // 平仓失败,返回空字符串 } //+------------------------------------------------------------------+ 以上手动平了一个带comment注释的单子,但没有把comment获取打印出来,问题出在哪?
以上手动平了一个带comment注释的单子,但没有把comment获取打印出来,问题出在哪?
你搞错了,这里的 ticket 指的是正在交易中执仓的订单编号(即你想要平仓的订单编号,具体如何在EA中用代码获取,我就不写了)
string ClosePosition(const long ticket, const long magic)
例如,我想平仓订单编号为 15338917的单子
void OnTick() { //--- Print(ClosePosition(15338917, 0)); }
这样可以获取和它对应in的注释
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
如果你的目的是手动平仓,那么此时我们就需要用到这个系统函数了,即交易事件发生时
void OnTrade(void)
具体方法代码如下:
//+------------------------------------------------------------------+ //| Test1.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #include <Trade\Trade.mqh> #include <Trade\SymbolInfo.mqh> CTrade m_trade; CDealInfo m_deal; CSymbolInfo m_symbol; CPositionInfo m_pos; //+------------------------------------------------------------------+ //| EA交易初始化函数 | //+------------------------------------------------------------------+ int OnInit() { //--- EventSetMillisecondTimer(1); if(!m_symbol.Name(_Symbol)) // sets symbol name return(INIT_FAILED); RefreshRates(); m_trade.SetMarginMode(); m_trade.SetTypeFillingBySymbol(m_symbol.Name()); m_trade.SetDeviationInPoints(INT_MAX); IsLastOutTicket(); // 初始化检查一次 //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); } //+------------------------------------------------------------------+ //| EA报价函数 | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer() { //--- } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTrade(void) { //--- long pos_id = IsLastOutTicket(); if(pos_id > 0) { HistorySelect(0, TimeTradeServer()); int total_deal = HistoryDealsTotal(); for(int i = total_deal - 1; i >= 0; i--) if(m_deal.SelectByIndex(i)) if(m_deal.Entry() == DEAL_ENTRY_IN) if(m_deal.Order() == pos_id) { printf("有新的平仓交易, 它的入场注释 = %s", m_deal.Comment()); break; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool RefreshRates(void) { //--- refresh rates if(!m_symbol.RefreshRates()) { Print("RefreshRates error"); return(false); } //--- protection against the return value of "zero" if(m_symbol.Ask() == 0 || m_symbol.Bid() == 0) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| 在历史中检查新平仓的交易,如果有返回它的订单ID | //+------------------------------------------------------------------+ long IsLastOutTicket(void) { static datetime last_deal_time = 0; static long last_position_id = 0; if(!::HistorySelect(last_deal_time, UINT_MAX)) // 如果没有得到历史,就退出 return(WRONG_VALUE); int total_deals = ::HistoryDealsTotal(); // 在取得的列表中得到交易的数量 for(int i = total_deals - 1; i >= 0; i--) // 遍历在获得的列表中的全部交易,从最新的到最开始的 { if(!m_deal.SelectByIndex(i)) // 取得交易编号 continue; if(m_deal.Symbol() != m_symbol.Name()) // 如果货币名称匹配,继续 continue; if(m_deal.PositionId() == last_position_id) // 如果订单ID匹配,就退出 return(WRONG_VALUE); else // 如果单号没有匹配,就进行通知 if(m_deal.Entry() == DEAL_ENTRY_OUT) // 记住最新平仓交易的时间和订单ID { last_deal_time = m_deal.Time(); last_position_id = m_deal.PositionId(); return(last_position_id); } } return(WRONG_VALUE); }这些都是很简单的方式方法,没必要搞复杂了。如果你看不懂我也没办法,我的目的不是教人,我只是帮忙你解决问题,不喜勿喷。。。
你搞错了,这里的 ticket 指的是正在交易中执仓的订单编号(即你想要平仓的订单编号,具体如何在EA中用代码获取,我就不写了)
例如,我想平仓订单编号为 15338917的单子
这样可以获取和它对应in的注释
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
如果你的目的是手动平仓,那么此时我们就需要用到这个系统函数了,即交易事件发生时
具体方法代码如下:
这些都是很简单的方式方法,没必要搞复杂了。如果你看不懂我也没办法,我的目的不是教人,我只是帮忙你解决问题,不喜勿喷。。。棒棒哒
MT提供的消息 只是一般的交易活动,且优先级不高,大致和计时消息相当,即不是一个消息产生必须响应处理完 才发下各消息, 即发生消息和处理响应消息是异步的、不同步、不必然有序。
因此如果你需要通过comment分析单子之间的关系,应自己 保留 、查找、管理有关关系信息。当然这对编程能力要求较高
- www.mql5.com
高手来说说,如何实现平仓后就触发另一个函数的执行?
OnTradeTransaction()这函数我用的不太明白