MQL5 Wizard 是一个强大的工具,可以帮助我们自动生成交易顾问的代码。如果你想要深入了解如何使用它创建现成的交易顾问,可以查看 在MQL5 Wizard中创建现成的交易顾问。
本策略的交易信号基于两条移动平均线的交叉,详细信息可以参考 MQL5 Wizard - 基于两条EMA交叉的交易信号。通常情况下,移动平均线在趋势明显时效果较好,而在震荡市场中则可能提供许多虚假信号。为了改善策略的效果,我们可以引入时间过滤器(例如,在外汇的欧洲交易时段内开新仓)。
接下来,我们将讨论一种基于快速和慢速EMA交叉的策略,结合日内时间过滤器。这一策略被称为 “基于EMA交叉的日内时间过滤信号”(在MQL5 Wizard中创建EA时选择该策略)。
交易信号:
- 开多头仓位:快速EMA向上穿越慢速EMA,并且日内时间过滤条件未满足。
- 开空头仓位:快速EMA向下穿越慢速EMA,并且日内时间过滤条件未满足。
该策略在CSignal2EMA_ITF类中实现。
该交易系统基于挂单,价格水平的计算依赖于移动平均的数值,并使用ATR(平均真实波幅)单位。

图1. 基于EMA交叉及日内时间过滤的交易信号
交易信号
该交易策略实现于 CSignal2EMA_ITF 类中,具备一些保护方法以简化对指标值的访问:
double FastEMA(int ind) // 返回指定条的快速EMA值 double SlowEMA(int ind) // 返回指定条的慢速EMA值 double StateFastEMA(int ind) // 返回快速EMA的正负值 double StateSlowEMA(int ind) // 返回慢速EMA的正负值 double StateEMA(int ind) // 返回快速与慢速EMA的差值 double ATR(int ind) // 返回指定条的ATR值
- Limit>0。在价格回调时进入,即当移动平均线发生虚假突破时,价格优于市场价格(将根据交易信号设置买入限价和卖出限价订单)。
- Limit<0。将跟随价格运动方向(将根据交易信号设置买入止损和卖出止损订单)。
- Limit=0。这种情况下将使用市场价格进行交易。
1. 开多头仓位
检查开多头仓位的条件:如果最后一根完成的K线中,快速EMA和慢速EMA的差值从负变为正(StateEMA(1)>0 && StateEMA(2)<0)。
接着,通过调用CSignalITF类的CheckOpenLong()方法检查日内时间过滤条件。如果允许交易,将计算基础价格水平(移动平均值)和最后一根K线的ATR范围值。
根据Limit输入参数的符号,将放置买入挂单。订单价格、止损和止盈水平的计算相对于基础价格水平(以ATR单位为准)。订单的到期时间由Expiration输入参数(以K线为单位)定义。
//+------------------------------------------------------------------+ //| 检查开多头仓位的条件(买入) | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckOpenLong(double& price,double& sl,double& tp,datetime& expiration) { if(!(StateEMA(1)>0 && StateEMA(2)<0)) return(false); if(!m_time_filter.CheckOpenLong(price,sl,tp,expiration)) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); double spread=m_symbol.Ask()-m_symbol.Bid(); //--- price=m_symbol.NormalizePrice(ema-m_limit*atr+spread); sl =m_symbol.NormalizePrice(price+m_stop_loss*atr); tp =m_symbol.NormalizePrice(price-m_take_profit*atr); expiration+=m_expiration*PeriodSeconds(m_period); //--- return(true); }
2. 平仓多头仓位
在我们这个策略中,检查平仓多头仓位的函数始终返回false,即假设多头仓位将通过止盈或止损平仓。如果需要,你可以自行编写代码来实现该方法。
//+------------------------------------------------------------------+ //| 检查平仓多头仓位的条件 | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckCloseLong(double& price) { return(false); }
3. 开空头仓位
检查开空头仓位的条件:如果最后一根完成的K线中,快速EMA和慢速EMA的差值从正变为负(StateEMA(1)<0 && StateEMA(2)>0)。
接着,通过调用CSignalITF类的CheckOpenLong()方法检查日内时间过滤条件。如果允许交易,将计算基础价格水平(移动平均值)和最后一根K线的ATR范围值。
根据Limit输入参数的符号,将放置卖出挂单。订单价格、止损和止盈水平的计算相对于基础价格水平(以ATR单位为准)。订单的到期时间由Expiration输入参数(以K线为单位)定义。
//+------------------------------------------------------------------+ //| 检查开空头仓位的条件(卖出) | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckOpenShort(double& price,double& sl,double& tp,datetime& expiration) { if(!(StateEMA(1)<0 && StateEMA(2)>0)) return(false); if(!m_time_filter.CheckOpenShort(price,sl,tp,expiration)) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); //--- price =m_symbol.NormalizePrice(ema+m_limit*atr); sl =m_symbol.NormalizePrice(price+m_stop_loss*atr); tp =m_symbol.NormalizePrice(price-m_take_profit*atr); expiration+=m_expiration*PeriodSeconds(m_period); //--- return(true); }
4. 平仓空头仓位
在我们这个策略中,检查平仓空头仓位的函数始终返回false,即假设空头仓位将通过止盈或止损平仓。如果需要,你可以自行编写代码来实现该方法。
//+------------------------------------------------------------------+ //| 检查平仓空头仓位的条件 | //+------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckCloseShort(double& price) { return(false); }
5. 买入挂单的跟踪止损
该交易顾问将根据当前的移动平均值和ATR对挂单进行跟踪止损。
//+--------------------------------------------------------------------+ //| 检查修改买入挂单的条件 | //+--------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckTrailingOrderLong(COrderInfo* order,double& price) { //--- check if(order==NULL) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); double spread=m_symbol.Ask()-m_symbol.Bid(); //--- price=m_symbol.NormalizePrice(ema-m_limit*atr+spread); //--- return(true); }
6. 卖出挂单的跟踪止损
该交易顾问将根据当前的移动平均值和ATR对挂单进行跟踪止损。
当市场价格达到订单价格时,订单将被执行。
//+--------------------------------------------------------------------+ //| 检查修改卖出挂单的条件 | //+--------------------------------------------------------------------+ bool CSignal2EMA_ITF::CheckTrailingOrderShort(COrderInfo* order,double& price) { //--- check if(order==NULL) return(false); //--- double ema=SlowEMA(1); double atr=ATR(1); //--- price=m_symbol.NormalizePrice(ema+m_limit*atr); //--- return(true); }
使用MQL5 Wizard创建交易顾问
要基于该策略创建交易机器人,你需要在 MQL5 Wizard 的“创建现成的交易顾问”选项中选择信号属性为 “基于EMA交叉的日内时间过滤信号”:

图2. 在MQL5 Wizard中选择基于EMA交叉的日内时间过滤信号
接下来,你需要指定所需的 跟踪止损 算法以及 资金和风险管理 系统。交易顾问的代码将会自动生成,你可以编译并在 MetaTrader 5 客户端终端的策略测试器 中进行测试。
测试结果
让我们来看一下在历史数据上对交易顾问的回测(EUenSD H1,测试周期:2010年1月1日至2011年1月5日,PeriodFastEMA=5,PeriodSlowEMA=30,PeriodATR=7,Limit=1.2,StopLoss=5,TakeProfit=8,Expiration=4,GoodMinuteOfHour=-1,BadMinutesOfHour=0,GoodHourOfDay=-1,BadHoursOfDay=0,GoodDayOfWeek=-1,BadDaysOfWeek=0)。
在创建交易顾问时,我们使用了固定交易量(固定手数交易,0.1),未使用跟踪止损算法(未使用跟踪)。

图3. 基于EMA交叉的交易信号的交易顾问测试结果(未使用ITF过滤)
由于未使用日内过滤器,因此出现了许多虚假信号。如果我们分析交易时间段的结果,可以改善交易信号。
在我们的案例中,我们发现从6:00到23:59的EMA交叉提供了许多虚假信号。我们可以通过设置过滤参数来指定日内时间过滤器。
例如,我们可以设置时间过滤器,只允许在0:00到5:59之间开仓。可以通过设置BadHoursOfDay=16777152=111111111111111111000000b来实现。所有其他交易时间均为“坏”的,因此最好禁止从6:00开始到当天结束开新仓。
如果我们设置BadHoursOfDay=16777152,我们将能过滤掉许多虚假信号:

图4. 基于EMA交叉的交易信号的交易顾问测试结果(使用时间过滤器)
CSignalITF 提供了许多其他时间过滤功能(只需指定小时内的“好”和“坏”分钟,天内的小时,周内的天)。
附录: Signal2EMA-ITF.mqh 文件中包含 CSignal2EMA_ITF 类,需放置于 terminal_data_folder\MQL5\Include\Expert\Signal 文件夹中。
expert_2ema_itf.mq5 文件包含使用MQL5 Wizard创建的交易顾问代码。
评论 0