组合趋势和盘整策略·进阶篇
(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 里编译验证。
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,能直接看出盘整单频率的变化。
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 数据重标一遍再跑。
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 时段的胜率衰减。
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); } }