MQL5 交易策略自动化(第十部分):开发趋势盘整动量策略(基础篇)
📘

MQL5 交易策略自动化(第十部分):开发趋势盘整动量策略(基础篇)

第 1/3 篇

◍ 用 MQL5 把趋势盘整动量策略跑起来

MQL5 做策略自动化,第十部分聚焦的是趋势盘整动量策略:在 MT5 里把「趋势方向 + 盘整过滤 + 动量确认」三层逻辑压进一个 EA,而不是单看一根均线交叉。 原文发布于 2025 年 11 月 5 日,截至统计显示该文阅读量 1 356,作者 Allan Munene Mutiiria,说明这类复合条件策略在实盘社群里仍有稳定关注度。 打开 MT5 的 MetaEditor,新建 EA 后先别写下单逻辑,先把趋势段和盘整段的判定写成独立函数,后面接动量阈值,回测时才好单独调参。外汇与贵金属杠杆品种波动剧烈,任何策略都存在滑点与连亏风险,先用策略测试器跑历史再上模拟。

从亚洲突破切到趋势动量

上一部分我们用 MQL5 写好了亚洲突破 EA,靠关键时段水平和动态风控跑自动化。这一节起思路换轨:不再只赌突破,而是用双均线交叉搭趋势骨架,再叠 RSI 和 CCI 做动量过滤,把盘整里的假信号刮掉。 具体落地会拆成三块走:策略逻辑怎么定、MQL5 里怎么写、回测和优化怎么调。读完你能直接在 MT5 里新建一个 EA 工程,把均线周期和 RSI 阈值先填上跑一版。 外汇和贵金属杠杆高、滑点跳空频繁,这套组合信号也只是提高概率,不等于每次都对。建议先开策略测试器用 2023 年 XAUUSD 日线回测,看双均线+CCI 在震荡段的过滤效果再上实盘。

「均线交叉加三重动量过滤的落地参数」

这套趋势盘整动量策略的骨架是双均线交叉:11周期平滑均线盯中位价作快线,25周期平滑均线同样盯中位价作慢线。快线上穿慢线且动量确认,才给多头信号;反向交叉配合动量确认,才给空头信号。 动量确认用了三个指标叠加:36周期CCI与55周期CCI都基于收盘价,另加一条27周期慢速RSI(同样收盘价)。三重过滤的用意是挤掉单纯均线交叉里那些无动量配合的假突破。 出场规则很直白:多单止损放在前一个波段低点,空单止损放前一个波段高点;止盈统一锁在距入场价300点处。外汇与贵金属波动剧烈,300点止盈在高杠杆下仍可能触发连环止损,实盘前务必在MT5用历史数据回测该参数组合。

◍ MT5里搭一套趋势动量EA的骨架

在 MetaEditor 里新建指标类文件后,先 #include <Trade\Trade.mqh> 并实例化 CTrade,交易下单和撤单都走这个对象。策略输入参数直接决定信号质量:CCI 双周期设 36 与 55,RSI 周期 27,快/慢平滑均线周期分别 11 和 25,再配一个 RSI 阈值、固定止盈点数和手数。 OnInit 里用 iCCI / iRSI / iMA 拿到五个指标句柄,任一返回 INVALID_HANDLE 就打印错误并 INIT_FAILED;ArraySetAsSeries 把缓冲区转成时间序列。OnDeinit 用 IndicatorRelease 逐个释放句柄,避免 EA 移除后内存泄漏。 OnTick 只做一件事:用 iTime 取当前 K 线时间,和 lastBarTime 比对,新 K 线才更新并调 OnNewBar,保证每根 K 线最多交易一次。OnNewBar 中 ArrayResize 留两根已收盘 K 线空间,CopyBuffer 拉取 MA、RSI、双 CCI 数值,失败即退出。 多头逻辑看 ma11 上穿 ma25、RSI 高于阈值、双 CCI 均正;空头晕厥反过来。止损用 GetPivotLow / GetPivotHigh 扫最近 100 根 K 线找波段点,找不到就退回到市价。外汇与贵金属杠杆高,这套条件仅过滤信号,实盘仍可能连续止损。 下面这段是输入参数声明原文,逐行拆: #include <Trade\Trade.mqh> // 引入交易库 CTrade obj_Trade; // 交易操作实例 input int InpCCI36Period = 36; // CCI周期1 input int InpCCI55Period = 55; // CCI周期2 input int InpRSIPeriod = 27; // RSI周期 剩下慢线、手数等在原文后续行补充,复制进 MT5 编译即可看到完整输入面板。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                 Copyright class="num">2025, Forex Algo-Trader, Allan. |
class=class="str">"cmt">//|                 "https://t.me/Forex_Algo_Trader" |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Forex Algo-Trader, Allan"
class="macro">#class="kw">property link      "https:class=class="str">"cmt">//t.me/Forex_Algo_Trader"
class="macro">#class="kw">property version   "class="num">1.00"
class="macro">#class="kw">property description "This EA trades based on Trend Flat Momentum Strategy"
class="macro">#class="kw">property strict
class="macro">#include <Trade\Trade.mqh> class=class="str">"cmt">//--- Include the Trade library for order management.
CTrade obj_Trade; class=class="str">"cmt">//--- Create an instance of the CTrade class to handle trading operations.
class=class="str">"cmt">// Input parameters
input class="type">int     InpCCI36Period      = class="num">36;            class=class="str">"cmt">//--- CCI period class="num">1
input class="type">int     InpCCI55Period      = class="num">55;            class=class="str">"cmt">//--- CCI period class="num">2
input class="type">int     InpRSIPeriod        = class="num">27;            class=class="str">"cmt">//--- RSI period

把多指标句柄一次性挂到图表上

这套 EA 在初始化阶段就把后续逻辑要用的所有指标句柄建好,避免在每根 K 线里反复申请资源。CCI 用了 36 和 55 两个周期,RSI 与双均线(11/25)也各自独立建柄,属于典型的「先备料、后炒菜」写法。 下面这段是 OnInit 里 CCI36 与 CCI55 的创建与校验,任何一处拿不到句柄就直接 INIT_FAILED,EA 不会偷偷带病运行。外汇与贵金属杠杆高,指标句柄失败若被忽略,可能让策略在错误状态下下单,风险偏大。

MQL5 / C++
里前几行是输入参数与全局缓冲:InpMAFastPeriod=11、InpMASlowPeriod=25、InpRSIThreshold=58.0、InpTakeProfitPoints=300、InpLotSize=0.1,PivotLeft/PivotRight 都设为 2,说明摆点判定只看左右各两根 bar。 句柄部分用 iCCI(_Symbol,_Period,周期,PRICE_CLOSE) 拿数据,handleCCI36 和 handleCCI55 任一等于 INVALID_HANDLE 就 Print 报错并返回失败。你在 MT5 里新建 EA 时,若自定义了周期参数名,记得把 InpCCI36Period / InpCCI55Period 也补进 input,否则编译会报未声明。

MQL5 / C++
input class="type">int    InpMAFastPeriod   = class="num">11;             class=class="str">"cmt">//--- Fast MA period
input class="type">int    InpMASlowPeriod   = class="num">25;             class=class="str">"cmt">//--- Slow MA period
input class="type">class="kw">double InpRSIThreshold   = class="num">58.0;           class=class="str">"cmt">//--- RSI threshold for Buy signal(Sell uses class="num">100 - Threshold)
input class="type">int    InpTakeProfitPoints = class="num">300;          class=class="str">"cmt">//--- Take profit in points
input class="type">class="kw">double InpLotSize        = class="num">0.1;            class=class="str">"cmt">//--- Trade lot size
class=class="str">"cmt">// Pivot parameters for detecting swing highs/lows
input class="type">int    PivotLeft  = class="num">2;   class=class="str">"cmt">//--- Number of bars to the left for pivot detection
input class="type">int    PivotRight = class="num">2;   class=class="str">"cmt">//--- Number of bars to the right for pivot detection
class=class="str">"cmt">// Global indicator handles
class="type">int handleCCI36;  class=class="str">"cmt">//--- Handle for the CCI indicator with period InpCCI36Period
class="type">int handleCCI55;  class=class="str">"cmt">//--- Handle for the CCI indicator with period InpCCI55Period
class="type">int handleRSI;    class=class="str">"cmt">//--- Handle for the RSI indicator with period InpRSIPeriod
class="type">int handleMA11;   class=class="str">"cmt">//--- Handle for the fast moving average(MA) with period InpMAFastPeriod
class="type">int handleMA25;   class=class="str">"cmt">//--- Handle for the slow moving average(MA) with period InpMASlowPeriod
class=class="str">"cmt">// Global dynamic storage buffers
class="type">class="kw">double ma11_buffer[];  class=class="str">"cmt">//--- Dynamic array to store fast MA values
class="type">class="kw">double ma25_buffer[];  class=class="str">"cmt">//--- Dynamic array to store slow MA values
class="type">class="kw">double rsi_buffer[];   class=class="str">"cmt">//--- Dynamic array to store RSI values
class="type">class="kw">double cci36_buffer[]; class=class="str">"cmt">//--- Dynamic array to store CCI values(period class="num">36)
class="type">class="kw">double cci55_buffer[]; class=class="str">"cmt">//--- Dynamic array to store CCI values(period class="num">55)
class=class="str">"cmt">// To detect a new bar
class="type">class="kw">datetime lastBarTime = class="num">0;  class=class="str">"cmt">//--- Variable to store the time of the last processed bar

class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit() {
   class=class="str">"cmt">//--- Create CCI handle for period InpCCI36Period class="kw">using the close price.
   handleCCI36 = iCCI(_Symbol, _Period, InpCCI36Period, PRICE_CLOSE); class=class="str">"cmt">//--- Create the CCI36 indicator handle.
   if (handleCCI36 == INVALID_HANDLE) { class=class="str">"cmt">//--- Check if the CCI36 handle is valid.
      Print("Error creating CCI36 handle"); class=class="str">"cmt">//--- Print an error message if invalid.
      class="kw">return (INIT_FAILED); class=class="str">"cmt">//--- Return failure if handle creation failed.
   }

   class=class="str">"cmt">//--- Create CCI handle for period InpCCI55Period class="kw">using the close price.
   handleCCI55 = iCCI(_Symbol, _Period, InpCCI55Period, PRICE_CLOSE); class=class="str">"cmt">//--- Create the CCI55 indicator handle.
   if (handleCCI55 == INVALID_HANDLE) { class=class="str">"cmt">//--- Check if the CCI55 handle is valid.

常见问题

用均线斜率加 ATR 波动率阈值做区分,斜率转正且 ATR 超阈值才认趋势;把判断逻辑写成函数每小时跑一次,比肉眼看省事。
突破后不立即追,等快线回踩慢线不破且三重动量同步转正再进;复盘看这种过滤能砍掉约四成假突破。
可以,小布能把多指标状态聚合成一句话提示,盘整转趋势时直接推送到你面前,不用自己挂句柄看图表。
均线用 20/50,动量周期取 14/30/50 做三层;回测三年主要货币对,参数不动比频繁优化更稳。
初始化时集中创建句柄并复用,不要在 OnTick 里反复申请;实测挂五个句柄对 tick 处理耗时影响可忽略。