MQL5 简介(第 11 部分):MQL5 中使用内置指标的初学者指南(二)(基础篇)
📘

MQL5 简介(第 11 部分):MQL5 中使用内置指标的初学者指南(二)(基础篇)

第 1/3 篇

「用 iMA 把均线请进 EA」

MQL5 里调用内置指标不走硬编码,而是用以 i 开头的函数族,比如均线对应 iMA。它返回的是指标句柄,真正取值要靠 CopyBuffer,这套机制让指标和图表解耦,EA 重载时不会卡在重算上。 以 24 十一月 2025 发布的初学者指南数据看,该文在站内获得 1 010 次浏览、4 条互动,说明用内置函数接指标仍是新手最高频的痛点。外汇与贵金属杠杆高,指标信号只代表概率倾向,实盘前务必在 MT5 策略测试器跑历史。 下面这段是 20 周期收盘价均线的标准接法,句柄建一次即可反复用。

MQL5 / C++
class="type">int ma_handle = iMA(_Symbol, _Period, class="num">20, class="num">0, MODE_SMA, PRICE_CLOSE);
class="type">class="kw">double ma_buffer[class="num">1];
CopyBuffer(ma_handle, class="num">0, class="num">0, class="num">1, ma_buffer);

从单指标到三指标:隐藏背离项目要做什么

上一章只用了 RSI 做内置指标演示,这一章直接把 RSI、随机振荡器(Stochastic)和移动平均线(MA)三个指标打包进同一个 EA 项目。核心不再是单纯看指标数值,而是让程序自动抓「隐藏背离」——也就是价格没破前高/前低、但指标却破了,这种结构常被视为趋势延续的概率信号。 本项目纯教学向,目标就两个:一是练你在 MQL5 里写多指标协同的胆量,二是搞懂怎么用代码识别隐藏看涨/看跌背离。外汇和贵金属杠杆高、滑点跳空频繁,真跑实盘前务必先上 MT5 策略测试器用历史数据验逻辑。 具体落地四件事:比对 RSI 拐点与对应价格走势判定隐藏背离;用 RSI+MA+Stochastic 拼一个 EA 骨架;在图表上把隐藏背离画出来;按美元风险算手数、用不一致烛台尺寸定止损,再依预设风险回报比(RRR)自动下单。打开 MT5 新建 EA,先把这三个指标的 handle 建出来,就能照这个清单一步步填代码。

◍ EA 怎么靠背离抓隐藏动能

这套 EA 的核心是用均线定趋势、RSI 找隐藏背离、随机指标做二次确认,而不是靠随机指标本身去发现背离。RSI 负责比对自身摆动与价格的错位,200 EMA 只用来过滤方向,信号有效性先看结构再看随机突破。 隐藏看涨背离出现在 RSI 走更低的低点、但价格却踩出更高的低点之时,说明表面弱势下买盘承接更强,后续上涨动量可能发酵。隐藏看跌背离则反过来:RSI 更高的高点配价格更低的高点,下行惯性倾向延续。 卖单逻辑里,价格必须低于 200 EMA 确认偏空。系统先定位一根看涨烛形后的最新 RSI 高点,紧跟连续 3 根看跌烛形,在 RSI 与折线图价格对应位各画一条水平线;当 RSI 再破该线且对应价格高点更低,隐藏看跌背离成立。最后等随机指标突破超买(如 80)后 11 根柱内再度破线,超时不开仓,SL 取末次波动高点,TP 由 RRR 参数算。 买入对称处理:价格高于 200 EMA,找看跌烛形后的 RSI 低点加 3 根看涨烛形,画线后等 RSI 新低点低于水平线且价格低点更高,随机跌破超卖(如 20)后 11 根柱内再破方触发,SL 为末次波动低点。外汇与贵金属杠杆高,这类结构信号失效时回撤可能很快,参数上线前建议 MT5 策略测试器先跑历史段。

「给三件工具在 MT5 里发“工牌”」

做 EA 第一步不是写逻辑,而是先让终端认识你要用的指标。MA、RSI、Stochastic 各自需要一个 handle(句柄),本质就是给工具在内存里留个柜子,后面取数全靠它。 具体参数直接决定指标性格:iMA 用 200 周期、MODE_EMA、PRICE_CLOSE,相当于用指数均线看大尺度趋势,对价格反应比 SMA 快;iRSI 周期设 14,是经典的放大倍数,专门抓背离;iStochastic 的 5/3/3 分别代表 %K 周期、%D 平滑、减速平滑,MODE_SMA + STO_LOWHIGH 表示用高低价范围算随机值,灵敏度偏短线。 下面这段代码在 OnInit 里一次性把三个句柄建出来。外汇和贵金属波动大,句柄若返回 INVALID_HANDLE,后续取数会直接崩 EA,实盘前务必在策略测试器里跑一遍确认初始化成功。

MQL5 / C++
class=class="str">"cmt">//DECLEAR INDICATOR HANDLES
class="type">int ma_handle;
class="type">int rsi_handle;
class="type">int stoch_handle;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//INDICATOR PROPERTIES
   ma_handle = iMA(_Symbol,PERIOD_CURRENT,class="num">200,class="num">0,MODE_EMA,PRICE_CLOSE);
   rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,class="num">14,PRICE_CLOSE);
   stoch_handle = iStochastic(_Symbol,PERIOD_CURRENT,class="num">5,class="num">3,class="num">3,MODE_SMA,STO_LOWHIGH);
   class="kw">return(INIT_SUCCEEDED);
  }
class="type">int ma_handle;
class="type">int rsi_handle;
class="type">int stoch_handle;
ma_handle = iMA(_Symbol,PERIOD_CURRENT,class="num">200,class="num">0,MODE_EMA,PRICE_CLOSE);
rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,class="num">14,PRICE_CLOSE);
stoch_handle = iStochastic(_Symbol,PERIOD_CURRENT,class="num">5,class="num">3,class="num">3,MODE_SMA,STO_LOWHIGH);

把指标和烛形数据拉进EA内存

EA要下单,先得知道盘面给了什么信号。从已建好的指标句柄里取数,是后续所有条件判断的前提:随机振荡、RSI、MA三条线的值若不进数组,程序根本无从比较。 声明双精度数组是第一步。ma_buffer[] 装移动平均,rsi_buffer[] 装RSI,stoch_buffer_k[] 与 stoch_buffer_d[] 分别装随机指标的%K和%D;烛形侧则开 open[]、close[]、high[]、low[]、time[] 存OHLC及时间。数组初始为空,等着被填充。 默认数组从最旧数据填起,但交易只看最新。ArraySetAsSeries(..., true) 把最新柱推到索引0,指标与烛形数组都这么处理,两边结构才对齐。 真正取数靠 CopyBuffer() 与 CopyOpen/CopyClose 等系列函数。示例里从倒数第2根柱抓最近30根:指标传参30和1(代码中实际用CopyBuffer时第3参为1、第4参为30),烛形同理,确保价格背景和指标值一一对应。外汇与贵金属波动剧烈,这套取数逻辑若错位,信号会整体偏移,实盘风险偏高。 下面这段初始化代码可直接贴进 MT5 的 EA 模板验证句柄与数组声明:

MQL5 / C++
class=class="str">"cmt">//DECLEAR INDICATOR HANDLES
class="type">int ma_handle;
class="type">int rsi_handle;
class="type">int stoch_handle;
class=class="str">"cmt">//DECLEAR DOUBLE VARIABLES THAT STORES INDICATORS DATA
class="type">class="kw">double ma_buffer[];
class="type">class="kw">double rsi_buffer[];
class="type">class="kw">double stoch_buffer_k[], stoch_buffer_d[];
class=class="str">"cmt">//DECLEAR VARIABLES TO STORE CANDLE DATA
class="type">class="kw">double open[];
class="type">class="kw">double close[];
class="type">class="kw">double high[];
class="type">class="kw">double low[];
class="type">class="kw">datetime time[];
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//INDICATOR PROPERTIES
   ma_handle = iMA(_Symbol,PERIOD_CURRENT,class="num">200,class="num">0,MODE_EMA,PRICE_CLOSE);
   rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,class="num">14,PRICE_CLOSE);
   stoch_handle = iStochastic(_Symbol,PERIOD_CURRENT,class="num">5,class="num">3,class="num">3,MODE_SMA,STO_LOWHIGH);
class=class="str">"cmt">//START FROM THE LATEST CANDLE ON THE CHART
   ArraySetAsSeries(ma_buffer,true);
   ArraySetAsSeries(rsi_buffer,true);
   ArraySetAsSeries(stoch_buffer_k,true);
   ArraySetAsSeries(stoch_buffer_d,true);
class=class="str">"cmt">//START FROM THE LATEST CANDLE ON THE CHART
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(time,true);
   class="kw">return(INIT_SUCCEEDED);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert deinitialization function                               |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnDeinit(const class="type">int reason)
  {
class=class="str">"cmt">//---
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 把指标和K线缓存一次性拉进数组

在 OnTick 里把多品种数据同步到本地数组,是后续做信号判定的前提。下面这段逻辑直接从图表第 2 根 K 线(索引 1)向后取 30 根,把均线、随机指标 K/D、RSI 以及 OHLC 和时间全部拷进缓冲区。 注意 CopyBuffer 的第三、四参数:起点 1、长度 30,意味着你拿到的是 bar[1] 到 bar[30] 的窗口,最新一根 bar[0] 故意不取,避免 Tick 中途价格跳动造成信号抖动。外汇与贵金属杠杆高,这种错位取数能降低假触发概率。 数组声明后必须调 ArraySetAsSeries(..., true),否则默认正序会导致你用 buffer[1] 时指向最老一根而非次新一根。代码里 OnTick 外又重复拷了一次 OHLC,实盘里若已在 tick 内拷贝,这层冗余可以删掉以省开销。 开 MT5 新建 EA 把下面代码贴进去,编译后挂 EURUSD 十五分钟图,用 Print(open[0]) 验证取到的确是次新蜡烛开盘价,就能确认窗口错位符合预期。

MQL5 / C++
class=class="str">"cmt">//| Expert tick function                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnTick()
  {
class=class="str">"cmt">//COPY INDICATOR&class="macro">#x27;S DATA FROM THE SECOND BAR ON THE CHART TO THE LAST 31st BAR ON THE CHART
   CopyBuffer(ma_handle,class="num">0,class="num">1,class="num">30,ma_buffer);
   CopyBuffer(stoch_handle,class="num">0,class="num">1,class="num">30,stoch_buffer_k);
   CopyBuffer(stoch_handle,class="num">1,class="num">1,class="num">30,stoch_buffer_d);
   CopyBuffer(rsi_handle,class="num">0,class="num">1,class="num">30,rsi_buffer);

class=class="str">"cmt">//COPY CANDLE&class="macro">#x27;S DATA FROM THE SECOND BAR ON THE CHART TO THE LAST 31st BAR ON THE CHART
   CopyOpen(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,open);
   CopyClose(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,close);
   CopyHigh(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,high);
   CopyLow(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,low);
   CopyTime(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,time);
   }
class="type">class="kw">double open[];
class="type">class="kw">double close[];
class="type">class="kw">double high[];
class="type">class="kw">double low[];
class="type">class="kw">datetime time[];
ArraySetAsSeries(open,true);
ArraySetAsSeries(close,true);
ArraySetAsSeries(high,true);
ArraySetAsSeries(low,true);
ArraySetAsSeries(time,true);
CopyOpen(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,open);
CopyClose(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,close);
CopyHigh(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,high);
CopyLow(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,low);
CopyTime(_Symbol,PERIOD_CURRENT,class="num">1,class="num">30,time);

常见问题

用iMA获取均线句柄,再用CopyBuffer把数值拷进数组;周期和偏移按品种习惯设,别写死在代码里。
通常再接一个振荡类指标(如RSI)和成交量类指标;三者在EA里分别建句柄,再统一比对价格与指标峰谷。
小布可在对应品种页直接标出均线、振荡、量能三者背离区域,省去你手写指标比对的重复劳动。
就是先调用iMA/iRSI等函数拿到指标句柄(handle),后面所有读取都靠这个句柄,相当于给工具发访问凭证。
用CopyRates拉烛形结构数组,用CopyBuffer拉各指标缓冲;一次拷贝足够长度,循环中直接下标访问,别每根K都重读。