用于在EA交易中包含指标的现成模板(第一部分):振荡指标(基础篇)
📘

用于在EA交易中包含指标的现成模板(第一部分):振荡指标(基础篇)

第 1/3 篇

把振荡指标塞进EA的现成骨架

在 MT5 里写 EA 时,最常被重复造的轮子就是「调用指标值」。振荡类指标(如 RSI、Stochastic)因输出缓冲固定,最适合做成可复用模板:EA 初始化阶段用 iRSI / iStochastic 拿到句柄,之后每根蜡烛用 CopyBuffer 取缓冲,避免每次重算。 以 RSI 为例,标准周期 14、应用价 PRICE_CLOSE,在主图周期外单独开计算句柄,EA 不必把指标挂到图表也能读数。下面这段即最小可用骨架,读者可直接复制到 MT5 的 EA 源文件里改参数验证。 外汇与贵金属波动大,RSI 极值区只代表超买超卖概率偏高,不构成反向开仓依据,实盘需叠加结构过滤。

MQL5 / C++
class="type">int rsi_handle;
rsi_handle = iRSI(_Symbol, _Period, class="num">14, PRICE_CLOSE);
if(rsi_handle == INVALID_HANDLE) { Print("RSI句柄创建失败"); class="kw">return INIT_FAILED; }
class="type">class="kw">double rsi_buf[class="num">1];
if(CopyBuffer(rsi_handle, class="num">0, class="num">0, class="num">1, rsi_buf) <= class="num">0) { Print("RSI数据拷贝失败"); class="kw">return; }
class="type">class="kw">double rsi_val = rsi_buf[class="num">0];

◍ 指标库的结构骨架

这套分析工具把十几个常用技术指标的调用逻辑拆成了统一模板:每个指标都走「参数—初始化—析构—读取数据」四步,方便在 MT5 里批量挂载与回收。 从平均真实范围到威廉姆斯百分比范围,原文列了 19 个指标节点,全部复用同一套生命周期接口,说明底层封装追求极低耦合。 对交易者而言,直接照这个目录在 EA 里建类,能省掉重复写缓冲区申请的麻烦;外汇与贵金属波动剧烈,高杠杆下回测前先确认每个指标的空值处理是否到位。 打开 MT5 的 MetaEditor,按「参数 / 初始化 / 析构 / 读取数据」建空函数骨架,是验证该结构是否顺手的最快办法。

「把振荡指标塞进EA的通用骨架」

在MT5里把指标接进EA,表面看只是调个iCustom或内置指标函数,实际坑在参数记忆和缓冲区读取:你得反复翻参考文档,把指标创建参数固化成EA输入,再写函数从指定柱形取数。这类重复劳动占掉大部分调试时间,尤其对外汇和贵金属这类高波动品种,信号延迟往往来自句柄失效却没做检查。 本文给出的思路是做一套振荡器类指标的通用模板。核心拆成五块:样本输入、初始化建句柄、析构释放、按时间序列索引取线值、监控线形相对某水平的态。线形状态用相邻三根柱(值2、值1、值0)的关系定义,比如向上方向要求值2≤值1且值1<值0,向下反转则是值2<值1且值1>值0,共7种基础态加未定义态。 相对水平的状态另算一套:高于、低于、向上交叉(值1≤水平且值0>水平)、向下交叉、上下接触和等于,覆盖柱1与柱0两层判定。这些 condition 足够描述线段形状及与水平线交叠,且对所有振荡指标通用。 通用取数和状态监控函数写一次就能复用。文内示例代码块均完整,可直接拷进自定义程序跑,省去你重新拼装句柄和缓冲区逻辑的步骤。

用 ATR 读穿盘面的波动骨架

平均真实范围(ATR)本质是把市场波动量化成一条可跟踪的线。它出自 Welles Wilder 的波动性框架,后来被大量交易系统拿去做仓位和止损的锚,并不是孤立看的摆件。 真实范围取三个差额的最大值:当根最高减最低、上根收盘减当根最高、上根收盘减当根最低。ATR 再对这些真实范围做移动平均,所以它对跳空和长影线天然不 blindness。 一个可验证的现象:恐慌抛售打出的底部,ATR 往往冲到阶段高位;而顶部或长期横盘期,ATR 持续压在低区。打开 MT5 任意贵金属日线,把 ATR(14) 叠上去,能直接比对 2020 年 3 月流动性踩踏与 2023 年窄幅震荡的差异。 解读逻辑很直白:ATR 值越高,价格重构区间的概率倾向越大;值越低,原有节奏延续、趋势转换偏弱的可能性更高。外汇与贵金属杠杆高,波动放大时风控要先于信号。

◍ 把指标周期做成EA可调输入

这个振荡器类指标只有一个对外暴露的参数:移动平均平滑周期,出厂默认 14。实战里建议把所有指标输入都挂成 EA 的 input 参数,这样不用改源码就能在 MT5 策略测试器里拖滑块调。 新建 EA 模板时,从向导里勾上定时器与图表事件处理,其余留空。我们得到的空壳里,只在全局层放变量和函数声明;OnInit 里做参数初始化加指标句柄创建,OnDeinit 里销毁句柄,OnChartEvent 仅接管面板交互。换句话说,要完整驱动一个指标,你真正要写的就是变量示例、句柄开合、以及从缓冲区取数的通用函数,剩下的全是面板显示杂活。 面板类此前已做过轻量改造,能开多个实例显示不同数据,本文不展开差异,只要求把 Dashboard.mqh 丢进 \MQL5\Include\ 供 EA 引用。测试 EA 跑起来后,仪表板会显示指标当前读数和线态描述,方便你肉眼核对逻辑。 线态分类最顺手的做法是建一个覆盖全部可能状态的枚举,让判定函数返回该枚举类型。下面这段是从向导生成的空 EA 骨架,已经把 InpPeriod=14 作为输入暴露出来,定时器设了 60 秒一次——你可以直接复制到 MT5 里编译,把周期改成 20 或 8 看面板刷新节奏变化。外汇与贵金属波动剧烈,参数微调只改变信号频率,不预示方向,请先用模拟盘验证。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                 TestOscillatorATR.mq5 |
class=class="str">"cmt">//|                                     Copyright class="num">2023, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                                 [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2023, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//--- input parameters
input class="type">uint      InpPeriod=class="num">14;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- create timer
   EventSetTimer(class="num">60);

class=class="str">"cmt">//---
   class="kw">return(INIT_SUCCEEDED);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert deinitialization function                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(class="kw">const class="type">int reason)
  {
class=class="str">"cmt">//--- destroy timer
   EventKillTimer();

  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert tick function                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
class=class="str">"cmt">//---

  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Timer function                                                       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTimer()
  {
class=class="str">"cmt">//---

  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| ChartEvent function                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+

「把 ATR 状态机接进图表事件」

这一段给出的是指标骨架里最容易被忽略的两块:空的 OnChartEvent 钩子,以及用枚举把价格线段状态显式建模的思路。前者留给你挂鼠标交互,后者决定后面面板怎么读趋势。 输入参数只暴露一个 InpPeriod,默认 14,对应 ATR 周期;全局里 handle 初始化为 INVALID_HANDLE,period、ind_digits 置 0,ind_title 留空描述串,这都是 MT5 指标的标准起手式。 真正的落点在 ENUM_LINE_STATE:把线段分成 NONE、UP、DOWN、TURN_UP、TURN_DOWN、STOP_UP、STOP_DOWN 七种。你开 MT5 新建指标把这段枚举抄进去,就能在后续 switch 里直接判断拐头概率,而不是用一堆布尔量硬凑。 外汇与贵金属波动受杠杆与消息面驱动,ATR 状态仅描述波动倾向,不代表方向必现,实盘须自担高风险。

MQL5 / C++
class="type">void OnChartEvent(class="kw">const class="type">int id,
                  class="kw">const class="type">long &lparam,
                  class="kw">const class="type">class="kw">double &dparam,
                  class="kw">const class="type">class="kw">string &sparam)
  {
class=class="str">"cmt">//---
  
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//--- input parameters
input class="type">uint   InpPeriod  =  class="num">14;   class=class="str">"cmt">/* ATR Period  */
class=class="str">"cmt">//--- global variables
class="type">int     handle=INVALID_HANDLE;   class=class="str">"cmt">// Indicator handle
class="type">int     period=class="num">0;                class=class="str">"cmt">// ATR calculation period
class="type">int     ind_digits=class="num">0;            class=class="str">"cmt">// Number of decimal places in the indicator values
class="type">class="kw">string  ind_title;               class=class="str">"cmt">// Indicator description
class="macro">#class="kw">property copyright "Copyright class="num">2023, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//--- includes
class="macro">#include <Dashboard\Dashboard.mqh>
class=class="str">"cmt">//--- input parameters
input class="type">uint   InpPeriod  =  class="num">14;   class=class="str">"cmt">/* ATR Period  */
class=class="str">"cmt">//--- global variables
class="type">int     handle=INVALID_HANDLE;   class=class="str">"cmt">// Indicator handle
class="type">int     period=class="num">0;                class=class="str">"cmt">// ATR calculation period
class="type">int     ind_digits=class="num">0;            class=class="str">"cmt">// Number of decimal places in the indicator values
class="type">class="kw">string  ind_title;               class=class="str">"cmt">// Indicator description
class=class="str">"cmt">//--- variables for the panel
class="type">int     mouse_bar_index;         class=class="str">"cmt">// Index of the bar the data is taken from
CDashboard *panel=NULL;          class=class="str">"cmt">// Pointer to the panel object
class="macro">#class="kw">property copyright "Copyright class="num">2023, MetaQuotes Ltd."
class="macro">#class="kw">property link      "[MQL5官方文档]
class="macro">#class="kw">property version   "class="num">1.00"
class=class="str">"cmt">//--- includes
class="macro">#include <Dashboard\Dashboard.mqh>
class=class="str">"cmt">//--- enums
enum ENUM_LINE_STATE
  {
   LINE_STATE_NONE,         class=class="str">"cmt">// Undefined state
   LINE_STATE_UP,           class=class="str">"cmt">// Upward
   LINE_STATE_DOWN,         class=class="str">"cmt">// Downward
   LINE_STATE_TURN_UP,      class=class="str">"cmt">// Upward reversal
   LINE_STATE_TURN_DOWN,    class=class="str">"cmt">// Downward reversal
   LINE_STATE_STOP_UP,      class=class="str">"cmt">// Upward stop
   LINE_STATE_STOP_DOWN,    class=class="str">"cmt">// Downward stop
  };

常见问题

有,用通用指标包含模板:定义输入参数、获取指标句柄、在OnTick里CopyBuffer读数即可,改个指标名就能套用。
把周期提为input int变量,初始化时拼进指标参数,实盘可在EA属性里改,不必重编译。
可以,小布能按你给的指标逻辑生成状态机与图表事件提示,你只需贴入参数和周期。
ATR句柄只建一次,OnTick里只CopyBuffer最新值,配合新柱判断再更新状态即可。
每个指标封装独立函数返回指定buffer,调用处用语义命名,别直接写魔法数字索引。