10 种横盘交易策略的比较分析

Alexander Fedosov | 17 八月, 2018

内容目录

综述

趋势跟踪策略非常受欢迎且易于运用,尤其适合初学者。 然而,当前行情变得更加动荡,而趋势走势则不那么明显 (在范围和持续时间这两项上)。 如果不利用横盘或窄幅振荡行情进行交易的可能性,我们就会失去潜在的盈利。 遵循交易规则的趋势很简单: 识别趋势的迹象并尝试利用它。 横盘时交易与此则有很大不同。 在窄幅振荡走势期间,价格处于很小的范围内,并且可能在相当长的时间内保持不变。 行情没有方向性走势,流动性低。

在创建横盘交易策略时定义任务

之前的文章 中,我定义了三个任务,这些任务是创建趋势跟踪策略所必需的。 创建横盘交易策略所需的任务极其相似。

图例 1. 窄幅/横盘走势的示例。

任务 1. 辨别横盘的存在

横盘没有一般性和详尽的定义 (实际上也没有对趋势概念的正确论述)。 然而,有一些迹象可以表明行情目前处于横盘状态。 这种走势也被称为窄幅振荡走势,因为没有明显的上行和下行的纵向走势。 价格在一个范围内运动,接近波浪的下边界和上边界。 横盘的另一个迹象就是行情交易量很低,或行情参与者的士气低落。 从弱势价格的变化,以及小额分笔交易量的变化可以看出这一点。

任务 2. 一笔持仓的目标。

横盘交易技术通常运用通道交易。 这是在窄幅振荡走势中赢利的主要运用方法。 依据一些虚拟边界可以判断横盘通道。 进而,交易策略是基于价格和通道边界之间的关系来构建的。 大多数情况下,策略意味着当价格从通道边界反弹时买入或卖出 (图例 2)。


图例 2. 当价格从通道边界反弹时进行交易。

当于通道的上半部分进行卖出时,我们假设价格将向下边界移动。 其位置将作为止盈价位。 止损可以设置某个点数值,或根据通道边界而定。 买入操作使用逆向策略: 在较低的通道边界买入,并在上边界附近设置止盈价位。

横盘交易策略

我在选择横盘交易策略时运用了上述原则。

策略 #1,附带基于 MFI 滤波器的轨道线指标

 通道边界基于轨道线指标判断。 MFI 指标还用于过滤信号。

指标参数 描述
所用指标 轨道线
所用指标 MFI
时间帧 H1
买入条件 价格触及通道边界低轨,MFI 处于超卖区域 (低于 20)
卖出条件 价格触及通道边界高轨,MFI 处于超买区域 (高于 80)
离场条件   价格到达反方向的通道边界

图例. 3 根据策略 #1 示意入场条件。

图例 3. 交易策略 #1 的入场条件。

此策略的智能交易系统代码如下所示:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;
      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(mfi[0]<20 && env_low[0]>close[0])
     {
      tp=env_high[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(mfi[0]>80 && env_high[0]<close[0])
     {
      tp=env_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                  |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,mfi)<=0  ||
          CopyBuffer(InpInd_Handle2,1,0,2,env_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,env_high)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

止盈根据设定条件自动设置,而止损则根据时间帧手工设定。

策略 #2,布林带加两条移动均线

使用 布林带确定通道边界,并根据慢速和快速均线的相对位置过滤信号。

指标参数 描述
所用指标 布林带
所用指标 移动均线
时间帧 H1
买入条件 价格触及通道边界低轨,快速均线高于慢速均线
卖出条件 价格触及通道边界高轨,快速均线低于慢速均线
离场条件   价格到达反方向的通道边界

图例 4 示意入场条件。 两条 SMA 的默认周期均很小: 4 和 8。 周期值和平滑方法是可调的,因此您可以更改布林带信号的滤波灵敏度。

图例 4. 交易策略 #2 的入场条件。

除入场条件外,策略 #2 与策略 #1 非常相似。 

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;
      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(ma_slow[0]>ma_fast[0] && bb_low[0]>close[0])
     {
      tp=bb_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(ma_slow[0]<ma_fast[0] && bb_up[0]<close[0])
     {
      tp=bb_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,1,0,2,bb_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,bb_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,ma_slow)<=0 ||
          CopyBuffer(InpInd_Handle3,0,0,2,ma_fast)<=0 ||
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

策略 #3. WSO & WRO 通道和埃勒斯 (Ehlers) 分形维度

主要信号指标是 WSO 和 WRO通道,它们基于两个振荡器的通道: WSO (Widner 支撑振荡器) 和 WRO (Widner 阻力振荡器)。 该指标的思路则基于 Mel Widner 的文章 "自动支撑和阻力"。 为了过滤信号,我们将使用分形维数指标,该指标在 John F. Ehlers 和 Ric Way 的文章 "分形维度作为行情模式传感器" 中有所描述。 

指标参数 描述
所用指标 WSO & WRO 通道
所用指标 埃勒斯分形维度
时间帧 任意
买入条件 价格触及通道边界低轨,分形维度值低于阈值
卖出条件 价格触及通道边界高轨,分形维度值低于阈值
离场条件   价格到达反方向的通道边界

图例 5 示意入场条件。 与之前的策略类似,当价格从通道边界反弹时执行交易操作。 当行情无趋势时,滤波器有助于找到入场点。


图例 5. 交易策略 #3 的入场条件。

此策略的智能交易系统代码如下所示:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;
      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(wwc_low[0]>close[0] && fdi[0]<Inp_FdiThreshold)
     {
      tp=wwc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(wwc_up[0]<close[0] && fdi[0]<Inp_FdiThreshold)
     {
      tp=wwc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,3,0,2,wwc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,wwc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,fdi)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

策略 #4, 通道交叉百分比指标并基于趋势范围滤波器

在这种情况下,通道边界建立在突破级别达到某个百分比的位置。 我们需要一个指标来构建通道,搜索价格从通道边界反弹的点位以及信号滤波器。 我们将使用趋势范围指标,它显示趋势和横盘状态。 这些状态将用于过滤信号。

指标参数 描述
所用指标 通道交叉百分比
所用指标 趋势范围
时间帧 任意
买入条件 价格抵达通道边界低轨,趋势范围直方图为灰色
卖出条件 价格抵达通道边界高轨,趋势范围直方图为灰色
离场条件   价格到达反方向的通道边界

入场条件如图例 6 所示。 通道交叉百分比指标具有许多特殊功能。 参数 Percent 限制距离,在突破之后开始构造新的级别,并且参数与时间帧相关。 应在较低的时间帧内设置较小的百分比。 例如,在小时时间帧内的建议值为 20 - 30。 数值越高,指标的选择性则过滥。

图例 6. 交易策略 #4 的入场条件。

策略代码如下所示:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;
      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(pcc_low[0]>close[0] && tr_flat[0]>tr_range[0])
     {
      tp=pcc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(pcc_up[0]<close[0] && tr_flat[0]>tr_range[0])
     {
      tp=pcc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,pcc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,pcc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,1,0,2,tr_flat)<=0 ||
          CopyBuffer(InpInd_Handle2,2,0,2,tr_range)<=0 ||
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

策略 #5, 价格通道指标和基于 RBVI 的滤波器

由价格通道指标构建通道,其上下边界由该期间的最高价和最低价决定。 RBVI 将过滤掉假信号,这可判定行情中是否存在横盘期。 

指标参数 描述
所用指标 价格通道
所用指标 RBVI
时间帧 任意
买入条件 价格触及通道边界低轨,RBVI 值低于阈值
卖出条件 价格触及通道边界高轨,RBVI 值低于阈值
离场条件   价格到达反方向的通道边界

入场条件如图例 7 所示。 RBVI 阈值为 40。 可以在只能交易系统参数中更改该值。

图例 7. 交易策略 #5 的入场条件。

这是策略的代码:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;

      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(pc_low[0]>close[0] && rbvi[0]<=Inp_level)
     {
      tp=pc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(pc_up[0]<close[0] && rbvi[0]<=Inp_level)
     {
      tp=pc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,pc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,1,0,2,pc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,rbvi)<=0 ||
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

策略 #6, 威廉姆斯百分比范围指标和基于 ADX 的滤波器

威廉姆斯的百分比范围判断超买/超卖状态,用于寻找入场点。 由于我们的目的是在横盘期间交易,或当价格应回撤一定范围时,我们采用趋势指标 ADX 来判断有无方向性走势。 

指标参数 描述
所用指标 威廉姆斯百分比范围
所用指标 ADX
时间帧 任意
买入条件 WPR 指标处于超卖区域 (低于 -80) 且 ADX 值低于阈值。
卖出条件 WPR 指标处于超买区域 (高于 -80) 且 ADX 值低于阈值。
离场条件   止盈/止损

从图例 8 中可以看出,ADX 的默认横盘区域设置为 30。 可以在智能交易系统代码中自定义该值。

图例 8. 交易策略 #6 的入场条件。

策略实现在下面的清单中提供。 此处的 Inp_FlatLevel 变量设置上述 ADX 阈值。

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;

      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(wpr[0]<-80 && adx[0]<Inp_FlatLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(wpr[0]>=-20 && adx[0]<Inp_FlatLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,wpr)<=0  ||
          CopyBuffer(InpInd_Handle2,0,0,2,adx)<=0)?false:true;
  }
//+------------------------------------------------------------------+

策略 #7, 改编的 Keltner 通道和基于魔幻趋势的滤波器

使用魔幻趋势指标检查价格从 Keltner 通道反弹,该指标可识别横盘区域。

指标参数 描述
所用指标 改编的 Keltner 通道
所用指标 魔幻趋势
时间帧 任意
买入条件 价格抵达通道边界低轨,魔幻趋势线为灰色
卖出条件 价格抵达通道边界高轨,魔幻趋势线为灰色
离场条件   价格到达反方向的通道边界

可视化交易策略在图例 9 中。 在横盘期间魔幻趋势值无变化,即它显示为灰色水平线。 因此,除了价格到达通道边界外,我们还会检查魔幻趋势的状态,该状态应稳定在横盘状态一段时间。 实现的检查将比较当前柱线和前一根柱线的值 - 它们应该相同。

图例 9. 交易策略 #7 的入场条件。

该代码包含检查买入/出卖条件的函数:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;

      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(kc_low[0]>close[0] && mt[0]==mt[1])
     {
      tp=kc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(kc_up[0]<close[0] && mt[0]==mt[1])
     {
      tp=kc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,kc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,kc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,mt)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

策略 #8, 唐奇安 (Donchian) 通道,由三位一体脉动 (Trinity Impulse) 确认

在这种情况下,我们尝试捕捉价格从唐奇安通道边界反弹的时刻,而三位一体脉动指标处于窄幅震荡走势状态。 

指标参数 描述
所用指标 唐奇安通道
所用指标 三位一体脉动
时间帧 低时间帧
买入条件 价格触及通道边界低轨,三位一体脉动值为零
卖出条件 价格触及通道边界高轨,三位一体脉动值为零
离场条件   价格到达反方向的通道边界

入场如图例 10 所示。 建议不要在较高时间帧内使用该策略,因为三位一体脉动滤波器曲线会表现出锯齿行为,而显示的横盘区域则滞后。 它们的宽度非常小,这令策略选择性过多。 最优为 5 到 30 分钟的时间帧。

图例 10. 交易策略 #8 的入场条件。

基于上述策略实现的智能交易系统:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;
         
      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(dc_low[0]>close[0] && ti[0]==0)
     {
      tp=dc_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(dc_up[0]<close[0] && ti[0]==0)
     {
      tp=dc_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,dc_up)<=0  ||
          CopyBuffer(InpInd_Handle1,1,0,2,dc_low)<=0 || 
          CopyBuffer(InpInd_Handle2,0,0,2,ti)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

策略 #9, ATR 通道指标和基于 CCI 色阶的滤波器

ATR 通道基于 ATR 与移动平均线的偏差。 CCI 色阶是一个 CCI 指标,显示为阈值的直方图,表示价格变动。 我们使用此指标来过滤通道的横盘状态 (当 CCI 介于阈值之间时)。

指标参数 描述
所用指标 ATR 通道
所用指标 CCI 色阶
时间帧 任意
买入条件 价格触及通道边界低轨,CCI 色阶值在阈值之间
卖出条件 价格触及通道边界高轨,CCI 色阶值在阈值之间
离场条件   价格到达反方向的通道边界

图例. 11 示意入场。 在某些情况下,价格可能脱离通道,但指定范围内基于 CCI 的滤波器表明价格可能会返回到通道,并抵达设定的止盈价位。


图例 11. 交易策略 #9 的入场条件。

此交易策略的智能交易系统代码:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;

      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,close[0]-Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,close[0]+Inp_StopLoss*_Point,tp,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   if(atr_low[0]>close[0] && cci[0]<Inp_CCI_LevelUP && cci[0]>Inp_CCI_LevelDOWN)
     {
      tp=atr_up[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   if(atr_up[0]<close[0] && cci[0]<Inp_CCI_LevelUP && cci[0]>Inp_CCI_LevelDOWN)
     {
      tp=atr_low[0];
      return true;
     }
   else
      return false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,1,0,2,atr_up)<=0  ||
          CopyBuffer(InpInd_Handle1,2,0,2,atr_low)<=0 || 
          CopyBuffer(InpInd_Handle2,2,0,2,cci)<=0 || 
          CopyClose(Symbol(),PERIOD_CURRENT,0,2,close)<=0
          )?false:true;
  }
//+------------------------------------------------------------------+

策略 #10, RSI 直方图和基于横盘指标的滤波器

直方图形式的 RSI 提供了更直观,因为主要入场信号是在其超买/超卖区域中生成的。 横盘用于过滤掉假信号。 

指标参数 描述
所用指标 RSI_Histogram
所用指标 横盘
时间帧 任意
买入条件 RSI 处于超卖区域 (低于阈值),横盘处于横盘区域。
卖出条件 RSI 处于超买区域 (高于阈值),横盘处于横盘区域。
离场条件   止盈/止损

入场点如图例 12 所示。 直方图形式的 RSI 可更容易地跟踪超买/超卖区域,以及横盘滤波器的横盘区域。

图例 12. 交易策略 #10 的入场条件。

基于上述策略的智能交易系统实现提供在以下代码中:

void OnTick()
  {
//--- 检查以前由该 EA 开立的订单
   if(!Trade.IsOpenedByMagic(Inp_MagicNum))
     {
      //--- 获取数据进行计算
      if(!GetIndValue())
         return;

      //--- 如果有买入信号,则开单
      if(BuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);

      //--- 如果有卖出信号,则开单
      if(SellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment);
     }
  }
//+------------------------------------------------------------------+
//| 买入条件                                                          |
//+------------------------------------------------------------------+
bool BuySignal()
  {
   return(rsi[0]<Inp_LowLevel && fl[0]<Inp_FLowLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| 卖出条件                                                          |
//+------------------------------------------------------------------+
bool SellSignal()
  {
   return(rsi[0]>Inp_HighLevel && fl[0]<Inp_FLowLevel)?true:false;
  }
//+------------------------------------------------------------------+
//| 获取指标的当前值                                                    |
//+------------------------------------------------------------------+
bool GetIndValue()
  {
   return(CopyBuffer(InpInd_Handle1,0,0,2,rsi)<=0  ||
          CopyBuffer(InpInd_Handle2,0,0,2,fl)<=0)?false:true;
  }
//+------------------------------------------------------------------+

测试

现在,我们已经定义了 10 个横盘交易策略,并在代码中实现了它们,我们来选择常见的测试条件。

策略 #1 测试 (附带基于 MFI 滤波器的轨道线指标)

预测试:

input int                  Inp_StopLoss=500;                            //止损(点数)

//--- MFI 指标参数
input ENUM_APPLIED_VOLUME  Inp_applied_volume=VOLUME_TICK;              // MFI 交易量类型
input int                  Inp_MFI_period=10;                           // MFI 周期
//--- 轨道线指标参数
input int                  Inp_ma_period=10;                            // 轨道线均线周期
input ENUM_MA_METHOD       Inp_ma_method=MODE_SMA;                      // 轨道线平滑类型
input double               Inp_deviation=0.1;                           // 自轨道线均线的边界偏离

测试结果:

图例 13. 横盘策略 #1. 测试结果。

策略 #2 测试 (布林带和移动均线)

预测试:

input int                  Inp_StopLoss=450;                            //止损(点数)

//--- 布林带参数
input int                  Inp_BBPeriod=14;                             //BB 周期
input double               Inp_deviation=2.0;                           //偏离
//--- 慢速均线参数
input int                  Inp_ma_period1=12;                           //慢速均线周期
input ENUM_MA_METHOD       Inp_ma_method1=MODE_SMMA;                    //慢速均线平滑方法
//--- 快速均线参数
input int                  Inp_ma_period2=2;                            //快速均线周期
input ENUM_MA_METHOD       Inp_ma_method2=MODE_LWMA;                    //快速均线平滑方法

测试结果:

图例 14. 横盘策略 #2. 测试结果。

策略 #3 测试 (基于埃勒斯分形维度滤波器的 WSO & WRO 通道)

预测试:

input int                  Inp_StopLoss=500;                            //止损(点数)

//--- WSO & WRO 通道参数
input int                  Inp_WsoWroPeriod=16;                         //Wso & Wro 通道周期
//--- 埃勒斯分形维度参数
input int                  Inp_FdiPeriod    =  18;                      //分形维度周期
input double               Inp_FdiThreshold =  1.4;                     //分形维度阈值
input ENUM_APPLIED_PRICE   Inp_Price        = PRICE_CLOSE;              //价格类型

测试结果:

图例 15. 横盘策略 #3. 测试结果。

策略 #4 测试 (通道交叉百分比指标并基于趋势范围滤波器)

预测试:

input int                  Inp_StopLoss=500;                            //止损(点数)

//--- Percentage_Crossover_Channel 参数
input double               Inp_Percent=26.0;                            //限定距离百分比
input ENUM_APPLIED_PRICE   Inp_Price=PRICE_CLOSE;                       //价格类型
//--- 趋势范围指标参数
input uint                 Inp_PeriodTR    =  14;                       //趋势范围指标周期
input ENUM_MA_METHOD       Inp_Method      =  MODE_EMA;                 //平滑方法
input double               Inp_Deviation   =  1.0;                      //偏离

测试结果:

图例16. 横盘策略 #4. 测试结果。

策略 #5 测试 (价格通道指标和基于 RBVI 的滤波器)

预测试:

input int                  Inp_StopLoss=450;                            //止损(点数)

//--- 价格通道指标参数
input int                  Inp_ChannelPeriod=12;                        //周期
//--- RBVI 指标参数
input int                  Inp_RBVIPeriod=5;                            //RBVI 周期
input ENUM_APPLIED_VOLUME  Inp_VolumeType=VOLUME_TICK;                  //交易量
input double               Inp_level=40;                                //横盘级别

测试结果:

图例 17. 横盘策略 #5. 测试结果。

策略 #6 测试 (威廉姆斯百分比范围指标和基于 ADX 的滤波器)

预测试:

input int                  Inp_StopLoss=50;                             //止损(点数)
input int                  Inp_TakeProfit=50;                           //止盈(点数)

//--- WPR 指标参数
input int                  Inp_WPRPeriod=10;                            // WPR 周期
//--- ADX 指标参数
input int                  Inp_ADXPeriod=14;                            //ADX 周期
input int                  Inp_FlatLevel=40;                            //ADX 的横盘级别

测试结果:

图例 18. 横盘策略 #6. 测试结果。

策略 #7 测试 (改编的 Keltner 通道和基于魔幻趋势的滤波器)

预测试:

input int                     Inp_SmoothCenter      =  11;              // 平滑中心线的周期数字
input int                     Inp_SmoothDeviation   =  12;              // 平滑偏差的周期数字
input double                  Inp_F                 =  1.0;             // 作用于偏差的因子
input ENUM_APPLIED_PRICE      Inp_AppliedPrice      =  PRICE_CLOSE;     // 中心线应用价格:
input ENUM_MA_METHOD          Inp_MethodSmoothing   =  MODE_SMA;        // 中心线平滑方法
input ENUM_METHOD_VARIATION   Inp_MethodVariation   =  METHOD_HL;       // 变异方法
//--- 魔幻趋势指标参数
input uint                    Inp_PeriodCCI   =  60;                    // CCI 周期
input uint                    Inp_PeriodATR   =  5;                     // ATR 周期

测试结果:

图例 19. 横盘策略 #7. 测试结果。

策略 #8 测试 (唐奇安通道,由三位一体脉动确认)

预测试:

input int                  Inp_StopLoss=500;                            //止损(点数)

//--- 唐奇安通道参数
input int                  Inp_ChannelPeriod=12;                        //唐奇安周期
//--- 三位一体脉动指标参数
input int                  Inp_Period= 5;                               //指标周期
input int                  Inp_Level= 34;                               //平滑级别
input ENUM_MA_METHOD       Inp_Type=MODE_LWMA;                          //均化类型
input ENUM_APPLIED_PRICE   Inp_Price=PRICE_WEIGHTED;                    //价格类型
input ENUM_APPLIED_VOLUME  Inp_Volume=VOLUME_TICK;                      //成交量类型

测试结果:

图例 20. 横盘策略 #8. 测试结果。

策略 #9 测试 (TR 通道指标和基于 CCI 色阶的滤波器)

预测试:

//--- ATR 通道参数
input ENUM_MA_METHOD       Inp_MA_Method=MODE_SMA;                      //均线平滑方法
input uint                 Inp_MA_Period=10;                            //均线周期
input uint                 Inp_ATR_Period=12;                           //ATR 周期
input double               Inp_Factor=1.5;                              //偏离数字
input ENUM_APPLIED_PRICE   Inp_IPC=PRICE_LOW;                           //价格类型
input int                  Inp_Shift=0;                                 //指标平移的柱线数
//--- CCI 色阶参数
input int                  Inp_CCI_ma_period = 14;                      // 均化周期 
input double               Inp_CCI_LevelUP   = 90;                      // 向上级别
input double               Inp_CCI_LevelDOWN =-90;                      // 向下级别

测试结果:

图例 21. 横盘策略 #9. 测试结果。

策略 #10 测试 (RSI 直方图和基于横盘指标的滤波器)

预测试:

//--- RSI 直方图参数
input uint                 Inp_RSIPeriod=12;                            // 指标周期
input ENUM_APPLIED_PRICE   Inp_RSIPrice=PRICE_CLOSE;                    // 价格类型
input uint                 Inp_HighLevel=60;                            // 超买级别
input uint                 Inp_LowLevel=40;                             // 超卖级别
input int                  Inp_Shift=0;                                 // 指标平移的柱线数
//--- 横盘指标参数
input uint                 Inp_Smooth=10;                               // 平滑周期
input ENUM_MA_METHOD       Inp_ma_method=MODE_SMA;                      // 平滑类型
input ENUM_APPLIED_PRICE   Inp_applied_price=PRICE_CLOSE;               // 价格类型
input uint                 Inp_HLRef=100;
input int                  Inp_FShift=0;                                // 指标平移的柱线数
input uint                 Inp_ExtraHighLevel=70;                       // 最大趋势级别
input uint                 Inp_FHighLevel=50;                           // 强趋势级别
input uint                 Inp_FLowLevel=30;                            // 弱趋势级别

测试结果:

图例 22. 横盘策略 #10. 测试结果。

研究成果

对于窄幅震荡行情交易策略的分析、测试和优化得出以下成果。

因此,我们可以得出主要结论: 虽然我们选择了不同的同奥构建技术和滤波器,但所有策略的优缺点都是可比的。 

结束语

以下是本文开发和使用的智能交易系统名称汇总表,以及上述策略中使用的辅助类和指标列表。 下面附带的存档包含所有描述的文件,并正确排列到文件夹中。 若要正常操作,您只需将 MQL5 文件夹保存到终端文件夹中。

本文中使用的程序:

#
 名称
类型
描述
1
Strategy_1.mq5
智能交易系统
 策略 #1. 附带基于 MFI 滤波器的轨道线指标
2
Strategy_2.mql5
智能交易系统
 策略 #2. 布林带加两条移动均线
3
Strategy_3.mq5
智能交易系统  策略 #3. 基于埃勒斯分形维度滤波器的 WSO & WRO 通道
4
Strategy_4.mq5
智能交易系统
 策略 #4, 通道交叉百分比指标并基于趋势范围滤波器 
5
Strategy_5.mq5 智能交易系统  策略 #5, 价格通道指标和基于 RBVI 的滤波器
6
Strategy_6.mq5
智能交易系统
 策略 #6, 威廉姆斯百分比范围指标和基于 ADX 的滤波器
7 Strategy_7.mq5 
智能交易系统
 策略 #7, 改编的 Keltner 通道和基于魔幻趋势的滤波器
 8 Strategy_8.mq5 智能交易系统  策略 #8, 唐奇安 (Donchian) 通道,由三位一体脉动 (Trinity Impulse) 确认
 9 Strategy_9.mq5 智能交易系统  策略 #9, ATR 通道指标和基于 CCI 色阶的滤波器
 10 Strategy_10.mq5 智能交易系统  策略 #10, RSI 直方图和基于横盘指标的滤波器 
 11 Trade.mqh 函数库  交易函数类
 13 wwc.mq5 指标  用在策略 #3
 14 fdi.mq5 指标  用在策略 #3
 15 pcc.mq5 指标  用在策略 #4
 16 trend_range.mq5  指标  用在策略 #4
 17 price_channel.mq5 指标  用在策略 #5
 18 rbvi.mq5 指标  用在策略 #5
 19 customizable _keltner.mq5 指标  用在策略 #7
 20 magic_trend.mq5 指标  用在策略 #7
 21 donchian_channel.mq5 指标  用在策略 #8
 22 trinity_impulse.mq5 指标  用在策略 #8
 23 atr_channel.mq5 指标   用在策略 #9
 24 cci_color_levels.mq5 指标  用在策略 #9
 25 rsi_histogram.mq5 指标  用在策略 #10
 26 flat.mq5 指标  用在策略 #10