用于在EA交易中包含指标的现成模板(第一部分):振荡指标(基础篇)
把振荡指标塞进EA的现成骨架
在 MT5 里写 EA 时,最常被重复造的轮子就是「调用指标值」。振荡类指标(如 RSI、Stochastic)因输出缓冲固定,最适合做成可复用模板:EA 初始化阶段用 iRSI / iStochastic 拿到句柄,之后每根蜡烛用 CopyBuffer 取缓冲,避免每次重算。 以 RSI 为例,标准周期 14、应用价 PRICE_CLOSE,在主图周期外单独开计算句柄,EA 不必把指标挂到图表也能读数。下面这段即最小可用骨架,读者可直接复制到 MT5 的 EA 源文件里改参数验证。 外汇与贵金属波动大,RSI 极值区只代表超买超卖概率偏高,不构成反向开仓依据,实盘需叠加结构过滤。
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 看面板刷新节奏变化。外汇与贵金属波动剧烈,参数微调只改变信号频率,不预示方向,请先用模拟盘验证。
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 状态仅描述波动倾向,不代表方向必现,实盘须自担高风险。
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 };