您应当知道的 MQL5 向导技术(第 42 部分):ADX 振荡器(基础篇)
「用向导搓一个 ADX 振荡器系统」
MT5 的 MQL5 向导能跳过手写框架,直接把 ADX 振荡器拼成可跑的 EA。对不想从头写交易逻辑的成熟交易者,这是条省时间的路,但底层信号质量仍取决于指标本身。 ADX 振荡器把传统 ADX 的趋向强度转成围绕零轴摆动的量能差,默认周期 14。向导生成后,EA 会在 +DI 上穿 -DI 且振荡值转正时倾向做多,反向则倾向做空;外汇与贵金属杠杆高,这类信号失效时回撤可能很快。 实测在 EURUSD 的 H1 上,2024 年样本内该向导基础版年化交易次数约 110 次,最大回撤概率偏高,说明原样跑并不稳。建议生成后先调 ADX 周期与阈值,再上策略测试器验证。
◍ 用 ADX 给趋势强度称个重
ADX 本质是一个振荡器,只回答一件事:当前品种的趋势到底有多强,而不判断方向。把它挂到 MT5 上,你会看到一条在 0–100 之间游走的线,经验上 25 以下算无趋势区间,25 以上才谈得上趋势在发力。 这篇里我们沿用之前拆 RSI、布林带、SAR 时的办法:先把 ADX 在自定义信号类里能跑出的形态一个一个单拆开验证,最后再打包做一次总测试,看哪些形态在历史样本里权重更高、更值得进信号组合。 顺带一提,抛物线 SAR 的系列还没收尾,这一节会先从它的收官章节切入,再正式进 ADX。外汇和贵金属杠杆高、跳空频繁,ADX 只度量强度,方向错配照样可能扩大回撤,验证时请用历史数据先跑一遍。
弱翻折叠加波动性收缩的延续陷阱
抛物线 SAR 在图表上吐出的点线,本质是价格可能翻面的临界位:上升趋势里它贴着低点下方走,下降趋势里趴在高点上方,一旦价格刺穿,点线就翻到另一侧。把它当尾随止损没问题,但别真信每个翻折都是反转。 外汇圈谈“成交量背离”得打折扣——经纪商分散、跨平台量能不可比,实际可用价格柱线范围(波动性)代替。价格朝某方向挪,但柱线范围连续缩小,往往不是转势,而是趋势中途换气。 具体看 SAR 弱翻折:若 SAR 从价下方翻到上方(偏空信号),同时柱线范围递减,这更像是原多头趋势的延续预兆,而非真跌破。确认“弱”的办法是翻折后柱线范围连跌超 3 根,参数 3 可改,回测先锁死。 反过来,价格碰 SAR 点线时波动性放大,才算翻折的有效确认,那种形态近似早期讲的顺势突破,只是多查了柱线范围扩张。这段没写码,但逻辑自洽,可自行补。 持仓管理上,弱翻折+波动性降能标出主支撑/阻力区。空头就把止损搁这些区上方,多头略下方,随主导趋势移。SAR 在震荡市假信号多,波动性检查能帮你少挨刺穿。 EURUSD 2022 日线测了形态 7(位图整数 0x80=128,EA 只跑这形):弱翻折续涨/续跌判定靠连续 3 根范围收缩,下面代码即核心。 [CODE] //+------------------------------------------------------------------+
| // | Check for Pattern 7. |
|---|
//+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_7(ENUM_POSITION_TYPE T) { m_sar.Refresh(-1); m_sar_alt.Refresh(-1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + 1) < Low(StartIndex() + 1) && Base(StartIndex()) > High(StartIndex())) { return(Range(StartIndex()) < Range(StartIndex() + 1) && Range(StartIndex() + 1) < Range(StartIndex() + 2)); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) > High(StartIndex() + 1) && Base(StartIndex()) < Low(StartIndex())) { return(Range(StartIndex()) < Range(StartIndex() + 1) && Range(StartIndex() + 1) < Range(StartIndex() + 2)); } return(false); } [/CODE] 逐行拆:函数收 ENUM_POSITION_TYPE 仓位方向 T;先刷新主 SAR 与备选 SAR 缓冲。 买权分支:前一根 SAR 基值低于那根最低价(SAR 在下方),当前根 SAR 基值高于最高价(已翻上),满足则查当前范围<前范围<再前范围,三段缩柱确认弱翻折续多。 卖权分支镜像:前根 SAR 在价上,当前翻下,同样三段范围递减返回 true,否则 false。外汇贵金属高杠杆,此形仅过滤假转,实盘仍可能吃区间反复。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">7. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalSAR::IsPattern_7(class="type">ENUM_POSITION_TYPE T) { m_sar.Refresh(-class="num">1); m_sar_alt.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + class="num">1) < Low(StartIndex() + class="num">1) && Base(StartIndex()) > High(StartIndex())) { class="kw">return(Range(StartIndex()) < Range(StartIndex() + class="num">1) && Range(StartIndex() + class="num">1) < Range(StartIndex() + class="num">2)); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + class="num">1) > High(StartIndex() + class="num">1) && Base(StartIndex()) < Low(StartIndex())) { class="kw">return(Range(StartIndex()) < Range(StartIndex() + class="num">1) && Range(StartIndex() + class="num">1) < Range(StartIndex() + class="num">2)); } class="kw">return(false); }
「用周线 SAR 给小周期交易降噪」
把抛物线 SAR 放到周线这类更高时间帧上,能拿到更宽的趋势视角,顺手滤掉 4 小时或更低周期里那些假翻折噪音。比如周线 SAR 明确给出强劲上升信号时,4 小时交易者就该优先做多,把小周期里的卖出提示当成噪音或短期回调,而不是反向操作。 两个时间帧信号共振时,可信度会明显抬升。4 小时看涨、且 15 分钟 SAR 点下破价格区间示意翻折,这种交叉确认不光信号强,入场位也更干净。逆势摸顶抄底不是不能做,但多数时候‘趋势是朋友’更管用,多周期 SAR 确认能帮你避开不可靠的逆势坑。 SAR 不止用于进场,也能当离场尺子。用 MT5 向导汇编的智能系统加自带类,靠开平仓阈值就能跑起来,不用补写额外代码;文末附的 MQ5 扩展文件只是展示向导产出长什么样、引用时缺哪些依赖。多盯一个时间帧,离场就能更精准,回测纸面上性能通常更好。 实盘里可以在小周期开仓,把高周期 SAR 价位直接设为止损位。这样止损落在显要价位上,被短期毛刺扫掉的概率更低。高周期 SAR 管大方向,低周期抓入场点,两者配合能少做违背大趋势的废单。 回测用了和形态 7 类似的设置,只是把备用时间帧换成周线,输入位图 256 对应形态-8。结果看,高周期 SAR 确实帮交易者看清大盘局,再按低周期信号动手,过度交易会少很多。 下面这段 MQL5 是形态 8 的判定函数,逻辑很直白:买权看前一根 Base 在高位上方、当前根跌破低位,且 Alt 周期 SAR 低于当前低位;卖权对称反转。 //+------------------------------------------------------------------+
| // | Check for Pattern 8. |
|---|
//+------------------------------------------------------------------+ bool CSignalSAR::IsPattern_8(ENUM_POSITION_TYPE T) { m_sar.Refresh(-1); m_sar_alt.Refresh(-1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + 1) > High(StartIndex() + 1) && Base(StartIndex()) < Low(StartIndex())) { return(Alt(StartIndex()) < LowAlt(StartIndex())); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) < Low(StartIndex() + 1) && Base(StartIndex()) > High(StartIndex())) { return(Alt(StartIndex()) > HighAlt(StartIndex())); } return(false); } 逐行拆一下:先刷新主周期与备用周期 SAR 数据;买权分支要求上一根基准价高于上一根最高价、当前基准价低于当前最低价,再确认备用周期 SAR 低于当前备用低位才返回真;卖权把高低关系反过来;都不满足就返回假。外汇和贵金属波动大、杠杆高,这套多周期过滤只降低噪音,不消除趋势反转风险。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">8. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalSAR::IsPattern_8(class="type">ENUM_POSITION_TYPE T) { m_sar.Refresh(-class="num">1); m_sar_alt.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + class="num">1) > High(StartIndex() + class="num">1) && Base(StartIndex()) < Low(StartIndex())) { class="kw">return(Alt(StartIndex()) < LowAlt(StartIndex())); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + class="num">1) < Low(StartIndex() + class="num">1) && Base(StartIndex()) > High(StartIndex())) { class="kw">return(Alt(StartIndex()) > HighAlt(StartIndex())); } class="kw">return(false); }
◍ SAR 与 RSI 的互补和代码落地
RSI 在 0–100 区间摆动,70 以上算超买、30 以下算超卖;抛物线 SAR 负责标趋势和反转点,但在震荡市容易假突破。把两者叠起来,等于给 SAR 的趋势判断加了一层动量确认:SAR 在价下方且 RSI 贴近 30,上升趋势反转的可信度会高一些。 不过 SAR+RSI 不是只有一种用法。RSI 本质是动量计,突发行情里动量可能延续,所以也有人把 SAR 的点距缩放来看敞口变化,而不只拿它确认超买超卖。本文走的是传统路线,用 MQL5 写了判定函数。 在日线周期跑前面的清单,成交很少,这正是去试 SAR-RSI 第二种组合的理由。优化测试里给每种形态挑了自定义阈值,下面对应 SAR 的类似结果。个人看法:那些阈值若没经过窄区间前向检验就直接优化出来,不如按预设值用,或自己评估实盘表现再动。 贴一段形态 9 的判定代码,逻辑很直接:多头看 SAR 基准低于最低价且 RSI≤30,空头看基准高于最高价且 RSI≥70,否则不触发。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">9. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalSAR::IsPattern_9(class="type">ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Base(StartIndex()) < Low(StartIndex())) { class="kw">return(RSI(StartIndex()) <= class="num">30.0); } else if(T == POSITION_TYPE_SELL && Base(StartIndex()) > High(StartIndex())) { class="kw">return(RSI(StartIndex()) >= class="num">70.0); } class="kw">return(false); }