组合趋势和盘整策略·进阶篇
🧩

组合趋势和盘整策略·进阶篇

(2/3)·趋势之后必盘整,但多数 EA 只会二选一;本文演示如何把跟随与区间算法装进同一个交易系统

实战向 第 2/3 篇
很多交易者手动切换趋势和盘整策略,却漏掉两者共存的窗口期。把两套逻辑硬塞进一个 EA 不等于组合,信号冲突时反而互相拖后腿。先想清楚切换条件,再谈代码实现。

把两个 ADX 策略塞进一个 EA 的三种拼法

演示用的底子是两套都靠 ADX 判趋势的策略:一套抓趋势(策略1),一套做盘整(策略6)。优化窗口固定在 2017.01.01–2018.01.08,按优化结果定参,两者都只在信号出现且无持仓时开单,靠预设止损获利平仓,不挂跟踪模块,逻辑刻意保持原样以便观察「组合方式」本身的影响。 方法一是顺序巡检:OnTick 里先查有无持仓,空仓才刷指标、依次看趋势和盘整信号,谁给信号谁开仓。由于互斥,账户里同时最多 1 单,风险暴露偏小;代价是另一策略有信号却被占仓挡住时会漏掉机会,不过两套策略本就分属不同市况,这种损耗理论上有限。 方法二在方法一基础上造了「联合信号」:趋势策略用 ADX 云看 DI+/DI- 差值不卡强度,盘整策略开仓前用 ADX 阈值滤强度,相当于给趋势信号后接了一道强弱门槛;趋势侧靠 RSI 排序,可屏蔽与 RSI 反向的盘整开仓,压缩亏损单。代码见 Combination2 项目。 方法三面向锁仓账户,两策略各自独立跑、用不同幻数标记,不论对方有无持仓都照常开单,等于把两个 EA 硬模拟进一个文件,优点缺点全保留,最大隐患是可能同屏双开、风险叠加。OnTick 中分别按 Trend 与 Flat 幻数独立检查。 下面这段是组合 EA 的公用输入参数头部,手数 0.01、幻数 1111、偏差 2 点,趋势子策略止损 25 点 / 获利 90 点,RSI 周期 28、超买 70 / 超卖 30,ADX 周期 11、alpha1=0.25,直接照抄就能在 MT5 里编译验证。

MQL5 / C++
class=class="str">"cmt">//--- 公用参数
class="kw">input class="type">class="kw">double                Inp_Lot=class="num">0.01;                                        class=class="str">"cmt">//手数
class="kw">input MarginMode             Inp_MMode=LOT;                                      class=class="str">"cmt">//资金管理
class="kw">input class="type">int                   Inp_MagicNum=class="num">1111;                                   class=class="str">"cmt">//幻数
class="kw">input class="type">int                   Inp_Deviation = class="num">2;                                   class=class="str">"cmt">//偏差(点数)
class=class="str">"cmt">//---
class="kw">input class="type">class="kw">string                Trend_EaComment="Trend Strategy";                     class=class="str">"cmt">//策略的注释
class="kw">input class="type">int                   Trend_StopLoss=class="num">25;                                   class=class="str">"cmt">//止损(点数)
class="kw">input class="type">int                   Trend_TakeProfit=class="num">90;                                 class=class="str">"cmt">//获利(点数)
class=class="str">"cmt">//--- RSI_Color 指标参数
class="kw">input class="type">int                   Trend_RSIPeriod=class="num">28;                                  class=class="str">"cmt">//RSI 周期数
class="kw">input class="type">class="kw">double                Trend_Overbuying=class="num">70;                                 class=class="str">"cmt">//超买区域
class="kw">input class="type">class="kw">double                Trend_Overselling=class="num">30;                                class=class="str">"cmt">//超卖区域
class=class="str">"cmt">//--- ADX_Cloud 指标参数
class="kw">input class="type">int                   Trend_ADXPeriod=class="num">11;                                  class=class="str">"cmt">//ADX 周期数
class="kw">input class="type">class="kw">double                Trend_alpha1 = class="num">0.25;                                 class=class="str">"cmt">//alpha1

◍ 双模 EA 的参数与下单分支

这套 EA 把行情切成趋势与盘整两套逻辑,输入参数先定死边界:趋势分支用 alpha2=0.25 做平滑系数,盘整分支的止损止盈都锁在 50 点,WPR 周期 7、ADX 周期 11、平盘阈值 40。外汇与贵金属杠杆高,固定点数止损在跳空时可能直接穿损,参数只是起点不是护身符。 OnTick 里先查当前符号有无自己魔数开的仓,没有才取指标值并顺着信号链走:趋势买→趋势卖→盘整买→盘整卖,四个分支互斥,一 tick 最多开一单。 TrendBuySignal 要求 trend_adx 走高、trend_rsi1 连续两柱等于 1 且 flat_adx 不低于 40,倾向只在强趋势段介入;FlatBuySignal 则反过来,要 flat_wpr 跌破 -80、flat_adx 低于 40 且 trend_rsi2 不为 1,抓的是弱势超卖反弹。开 MT5 把这两段布尔函数挂进策略测试器,改 Flat_FlatLevel 从 40 调到 30,能直接看出盘整单频率的变化。

MQL5 / C++
class="kw">input class="type">class="kw">double Trend_alpha2 = class="num">0.25; class=class="str">"cmt">//alpha2
class=class="str">"cmt">//---
class="kw">input class="type">class="kw">string Flat_EaComment="Flat Strategy"; class=class="str">"cmt">//策略注释
class="kw">input class="type">int Flat_StopLoss=class="num">50; class=class="str">"cmt">//止损(点数)
class="kw">input class="type">int Flat_TakeProfit=class="num">50; class=class="str">"cmt">//获利(点数)
class=class="str">"cmt">//--- WPR 指标参数
class="kw">input class="type">int Flat_WPRPeriod=class="num">7; class=class="str">"cmt">//WPR 周期数
class=class="str">"cmt">//--- ADX 指标参数
class="kw">input class="type">int Flat_ADXPeriod=class="num">11; class=class="str">"cmt">//ADX 周期数
class="kw">input class="type">int Flat_FlatLevel=class="num">40; class=class="str">"cmt">//ADX 平盘水平
class="type">void OnTick()
  {
class=class="str">"cmt">//--- 检查由 EA 在早前开启的仓位
   if(!Trade.IsOpenedBySymbol(_Symbol,Inp_MagicNum))
     {
class=class="str">"cmt">//--- 取得用于计算的数据
      if(!GetIndValue())
        class="kw">return;
class=class="str">"cmt">//--- 根据趋势算法开启订单
class=class="str">"cmt">//--- 如果有买入信号,开启订单
      if(TrendBuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Inp_MagicNum,Trend_EaComment);
      else
class=class="str">"cmt">//--- 如果有卖出信号,开启订单
      if(TrendSellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Inp_MagicNum,Trend_EaComment);
      else
class=class="str">"cmt">//--- 根据盘整算法开启订单
class=class="str">"cmt">//--- 如果有买入信号,开启订单
      if(FlatBuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Inp_MagicNum,Flat_EaComment);
      else
class=class="str">"cmt">//--- 如果有卖出信号,开启订单
      if(FlatSellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Inp_MagicNum,Flat_EaComment);
     }
  }
class="type">bool TrendBuySignal()
  {
   class="kw">return(trend_adx[class="num">0]>trend_adx[class="num">1] && trend_rsi1[class="num">0]==class="num">1 && trend_rsi1[class="num">1]==class="num">1 &&  flat_adx[class="num">0]>=Flat_FlatLevel)?true:class="kw">false;
  }
class="type">bool FlatBuySignal()
  {
   class="kw">return(flat_wpr[class="num">0]<-class="num">80 && flat_adx[class="num">0]<Flat_FlatLevel && trend_rsi2[class="num">0]!=class="num">1)?true:class="kw">false;
  }

「趋势与震荡双模的参数骨架」

这套 EA 把交易拆成 Trend 和 Flat 两套逻辑,各自带独立的注释、止损与幻数,方便在 MT5 策略测试器里分策略统计胜率与回撤。 公用层先定手数 0.01、偏差 2 点、资金管理走 LOT 模式;Trend 模默认止损 25 点、止盈 90 点,盈亏比约 1:3.6,幻数 1111 用于隔离订单。 Trend 模的信号层用 RSI(28) 配超买 70 / 超卖 30,再叠 ADX(11) 与两组 alpha=0.25 的云带滤波,避免在弱趋势里频繁假突破。 Flat 模仅露出注释 "Flat Strategy" 与止损 50 点,说明震荡段更看重容错宽度;外汇与贵金属杠杆高,实盘前务必用历史数据验证两套参数的夏普比。 别把默认数字当圣旨 参数里 RSI 周期 28、ADX 周期 11 都是原作者的样本偏好,换到 XAUUSD 的 M15 上可能钝化,自己拉近三个月 tick 数据重标一遍再跑。

MQL5 / C++
class=class="str">"cmt">//--- 公用参数
class="kw">input class="type">class="kw">double            Inp_Lot=class="num">0.01;                                        class=class="str">"cmt">//手数
class="kw">input MarginMode        Inp_MMode=LOT;                                       class=class="str">"cmt">//资金管理
class="kw">input class="type">int               Inp_Deviation = class="num">2;                                   class=class="str">"cmt">//偏差(点数)
class=class="str">"cmt">//---
class="kw">input class="type">class="kw">string            Trend_EaComment="Trend Strategy";                    class=class="str">"cmt">//策略的注释
class="kw">input class="type">int               Trend_StopLoss=class="num">25;                                   class=class="str">"cmt">//止损(点数)
class="kw">input class="type">int               Trend_TakeProfit=class="num">90;                                 class=class="str">"cmt">//获利(点数)
class="kw">input class="type">int               Trend_MagicNum=class="num">1111;                                 class=class="str">"cmt">//幻数
class=class="str">"cmt">//--- RSI_Color 指标参数
class="kw">input class="type">int               Trend_RSIPeriod=class="num">28;                                  class=class="str">"cmt">//RSI 周期数
class="kw">input class="type">class="kw">double            Trend_Overbuying=class="num">70;                                 class=class="str">"cmt">//超买区域
class="kw">input class="type">class="kw">double            Trend_Overselling=class="num">30;                                class=class="str">"cmt">//超卖区域
class=class="str">"cmt">//--- ADX_Cloud 指标参数
class="kw">input class="type">int               Trend_ADXPeriod=class="num">11;                                  class=class="str">"cmt">//ADX 周期数
class="kw">input class="type">class="kw">double            Trend_alpha1 = class="num">0.25;                                 class=class="str">"cmt">//alpha1
class="kw">input class="type">class="kw">double            Trend_alpha2 = class="num">0.25;                                 class=class="str">"cmt">//alpha2
class=class="str">"cmt">//---
class="kw">input class="type">class="kw">string            Flat_EaComment="Flat Strategy";                       class=class="str">"cmt">//策略注释
class="kw">input class="type">int               Flat_StopLoss=class="num">50;                                    class=class="str">"cmt">//止损(点数)

盘整分支的参数与双策略下单逻辑

盘整策略这组输入参数和趋势分支是平行挂载的:获利目标设 50 点,幻数 1112 用于和趋势单(1111 类)隔离;WPR 周期 7、ADX 周期 11、平盘阈值 40,意味着 ADX 跌破 40 才判定市场进入区间。 OnTick 里先查趋势幻数订单是否持仓,若空仓且指标函数 GetIndValue 取数成功,就按 TrendBuySignal / TrendSellSignal 开趋势单;随后用同样结构查 Flat_MagicNum 订单,空仓则走 FlatBuySignal / FlatSellSignal 开盘整单。两套逻辑互不阻塞,同一品种可能同时跑趋势和震荡仓。 外汇与贵金属杠杆高,双策略同开会放大敞口,实盘前务必在 MT5 策略测试器用 2020—2023 年 XAUUSD 数据回测,观察 Flat_TakeProfit=50 在 ADX<40 时段的胜率衰减。

MQL5 / C++
class="kw">input class="type">int                 Flat_TakeProfit=class="num">50;                class=class="str">"cmt">//获利(点数)
class="kw">input class="type">int                 Flat_MagicNum=class="num">1112;                class=class="str">"cmt">//幻数
class=class="str">"cmt">//--- WPR 指标参数
class="kw">input class="type">int                 Flat_WPRPeriod=class="num">7;                 class=class="str">"cmt">//WPR 周期数
class=class="str">"cmt">//--- ADX 指标参数
class="kw">input class="type">int                 Flat_ADXPeriod=class="num">11;                class=class="str">"cmt">//ADX 周期数
class="kw">input class="type">int                 Flat_FlatLevel=class="num">40;                class=class="str">"cmt">//ADX 平盘水平
class="type">void OnTick()
  {
class=class="str">"cmt">//--- 检查之前由 EA 开启的趋势策略的订单
   if(!Trade.IsOpenedBySymbol(_Symbol,Trend_MagicNum))
     {
      class=class="str">"cmt">//--- 取得用于计算的数据
      if(!GetIndValue())
         class="kw">return;
      class=class="str">"cmt">//--- 如果有买入信号,开启订单
      if(TrendBuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Trend_MagicNum,Trend_EaComment);
      else
      class=class="str">"cmt">//--- 如果有卖出信号,开启订单
      if(TrendSellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Trend_StopLoss,Trend_TakeProfit,Trend_MagicNum,Trend_EaComment);
     }
class=class="str">"cmt">//--- 检查之前由EA 开启的盘整策略的订单
   if(!Trade.IsOpenedBySymbol(_Symbol,Flat_MagicNum))
     {
      class=class="str">"cmt">//--- 取得用于计算的数据
      if(!GetIndValue())
         class="kw">return;
      class=class="str">"cmt">//--- 如果有买入信号,开启订单
      if(FlatBuySignal())
         Trade.BuyPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Flat_MagicNum,Flat_EaComment);
      else
      class=class="str">"cmt">//--- 如果有卖出信号,开启订单
      if(FlatSellSignal())
         Trade.SellPositionOpen(Symbol(),Inp_Lot,Flat_StopLoss,Flat_TakeProfit,Flat_MagicNum,Flat_EaComment);
     }
  }
把回测比对交给小布
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到趋势与盘整区段的概率分布,你只需专注策略参数的取舍。

常见问题

常见做法以 ADX 低于 20–25 视为盘整、高于 25–30 视为趋势,但需结合品种波动特性回测,没有统一标准值。
取决于组合方法。按市场状态切换的方法通常互斥;用振荡指标确认趋势入场的方法可能允许共存,但要控总敞口。
可能延迟入场错过部分行情,但往往减小回撤、提高胜率,属于用效率换稳健的取舍。
小布目前提供品种状态识别与历史区段标注,EA 编译与 MT5 回测仍需本地终端,但可把小布的输出作为策略过滤参考。
建议先分别固化单策略参数再只调组合开关与仓位权重,避免维度爆炸,外汇贵金属属高风险市场须防过拟合。