MQL5 Cookbook: 基于三重滤网策略开发交易系统框架·综合运用
📘

MQL5 Cookbook: 基于三重滤网策略开发交易系统框架·综合运用

第 3/3 篇

多周期信号筛选与初始化落点

这段逻辑把三个时间范围的指标状态做排列组合,只要其中两个或三个缓冲区出现「前一根低于次前一根」的上升形态,就返回买入指令。注意 Screen0xIndicatorPeriod<=0 代表该周期被关闭,所以代码用周期参数是否大于 0 来动态决定参与判断的因子数量。 具体看:当一、二周期开、三周期关时,比的是 indicator_buffer1[1]>buffer1[2] 且 buffer2 同构;一关二开三开则换 buffer2 与 buffer3;全开则三者都要满足。最后兜底 return(WRONG_VALUE) 表示无信号,调用方应把它当「不动作」处理。 OnInit 里先算 MinimumTimeframe,取三个屏中最小的非零周期作为新柱检测基准,这步直接决定 OnTick 里刷新频率——若你只开 M15 和 H1,最小帧就是 M15,EA 不会在每根 M1 上去空转。随后依次拿句柄、初始化新柱、读持仓属性、画面板。 外汇与贵金属杠杆高,这类多周期共振只提高信号出现的概率,不保证方向;开 MT5 把 Screen03IndicatorPeriod 设 0 跑一遍,能直接看到三因子变两因子后信号触发的频次变化。

MQL5 / C++
if(Screen01IndicatorPeriod>class="num">0 && Screen02IndicatorPeriod>class="num">0 && Screen03IndicatorPeriod<=class="num">0)
  {
    if(indicator_buffer1[class="num">1]>indicator_buffer1[class="num">2] &&
        indicator_buffer2[class="num">1]>indicator_buffer2[class="num">2])
        class="kw">return(ORDER_TYPE_BUY);
  }
if(Screen01IndicatorPeriod<=class="num">0 && Screen02IndicatorPeriod>class="num">0 && Screen03IndicatorPeriod>class="num">0)
  {
    if(indicator_buffer2[class="num">1]>indicator_buffer2[class="num">2] &&
        indicator_buffer3[class="num">1]>indicator_buffer3[class="num">2])
        class="kw">return(ORDER_TYPE_BUY);
  }
if(Screen01IndicatorPeriod>class="num">0 && Screen02IndicatorPeriod<=class="num">0 && Screen03IndicatorPeriod>class="num">0)
  {
    if(indicator_buffer1[class="num">1]>indicator_buffer1[class="num">2] &&
        indicator_buffer3[class="num">1]>indicator_buffer3[class="num">2])
        class="kw">return(ORDER_TYPE_BUY);
  }
class=class="str">"cmt">//--- 三个时间范围的条件
if(Screen01IndicatorPeriod>class="num">0 && Screen02IndicatorPeriod>class="num">0 && Screen03IndicatorPeriod>class="num">0)
  {
    if(indicator_buffer1[class="num">1]>indicator_buffer1[class="num">2] &&
        indicator_buffer2[class="num">1]>indicator_buffer2[class="num">2] &&
        indicator_buffer3[class="num">1]>indicator_buffer3[class="num">2]
        )
        class="kw">return(ORDER_TYPE_BUY);
  }

class=class="str">"cmt">//--- 没有信号
  class="kw">return(WRONG_VALUE);
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EA初始化函数                                                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- 为检查新柱确定最小时间范围
  MinimumTimeframe=GetMinimumTimeframe(Screen01TimeFrame,Screen01IndicatorPeriod,
                                       Screen02TimeFrame,Screen02IndicatorPeriod,
                                       Screen03TimeFrame,Screen03IndicatorPeriod);
class=class="str">"cmt">//--- 取得指标句柄
  GetIndicatorHandles();
class=class="str">"cmt">//--- 初始化新柱
  CheckNewBar();
class=class="str">"cmt">//--- 取得属性
  GetPositionProperties(P_ALL);
class=class="str">"cmt">//--- 设置信息面板
  SetInfoPanel();
class=class="str">"cmt">//---
  class="kw">return(class="num">0);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| EA去初始化函数                                                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(const class="type">int reason)
  {
class=class="str">"cmt">//--- 在日志中打印去初始化原因
  Print(GetDeinitReasonText(reason));
class=class="str">"cmt">//--- 当从图表上移除时

◍ 指标句柄在移除事件里必须手动释放

EA 或指标被从图表移除时,MetaTrader 5 不会自动回收你之前用 iCustom 之类函数拿到的子指标句柄。若只删面板对象而漏掉释放,终端运行久了可能出现句柄泄漏,表现为内存占用缓慢爬升、后续加载同类指标变慢。 上面这段处理的是 REASON_REMOVE 分支:先清掉信息面板所有图形对象,再把三个屏幕对应的句柄逐一交还给系统。Screen01 到 Screen03 的 IndicatorRelease 调用是硬必须,少一个就可能留下悬空句柄。 实操上,开 MT5 把这段塞进 OnDeinit 的移除判断里,挂上 EA 跑一晚再摘掉,用任务管理器看 terminal64.exe 的私有内存是否回落,就能验证释放是否生效。外汇与贵金属品种波动大、重加载频繁,句柄管理不当会放大终端不稳定风险。

MQL5 / C++
  if(reason==REASON_REMOVE)
    {
      class=class="str">"cmt">//--- 从图表上删除所有有关信息面板的对象
      DeleteInfoPanel();
      class=class="str">"cmt">//--- 删除指标句柄
      IndicatorRelease(Screen01IndicatorHandle);
      IndicatorRelease(Screen02IndicatorHandle);
      IndicatorRelease(Screen03IndicatorHandle);
    }

「双核跑完半小时的优化实测」

把策略测试器按三段时间范围的最小值指定好,EA 的参数里时间范围字段我习惯人工锁死,不丢给优化器去扫,避免过拟合到特定周期。 优化在双核处理器上实测约耗时 30 分钟,跑完出的参数曲面里,最大余额这一组比最大采收率那组回撤明显更小,所以演示账户直接选了最大余额结果落地。 外汇与贵金属品种杠杆高、跳空频繁,这套优化结果只是历史样本下的概率倾向,实盘前务必在 MT5 用同设置重跑一遍验证。

画得少,看得清

把信号区块和指标替换掉,EA 就能从一套逻辑变出另一套系统,附件里的 elderthreescreens.zip(20.02 KB)和设定文件(1.1 KB)可直接下到 MT5 里跑。评论区有人用 ECN 账户测过,回测表现和文中一致,但非 ECN 限仓 0.1 手的账户能否成交未被验证。 有读者指出原实现用三根普通 MA 比大小,并非长老真正的潮汐—波浪—涟漪结构,这说明模板只是骨架,策略内核得自己补。外汇和贵金属杠杆高,复制代码前先开策略测试器用历史数据证伪。 少堆指标、先把一屏信号看清,比凑齐三屏却看不懂更有用。

常见问题

先在日线或小时图用趋势指标过滤方向,再切到五分钟图等动量指标回踩转强时挂单,避免逆大周期操作。
会造成内存泄漏和句柄占用,长期跑多个品种可能让终端变卡甚至报错,必须在移除事件里显式释放。
可以,小布能按你设的大周期趋势和小周期触发条件做跨周期扫描,并把初始化落点直接标在盘面上省去手算。
多半是找到更稳的参数组合或剔除冗余计算,实测常能把信号延迟压到几秒内,具体看品种波动。
只保留关键滤网线和触发箭头,其余用背景色或提示音代替,看得清主次才不容易误判。