MQL5 中如何调用指标(基础篇)
「在 MQL5 里把指标请进来」
MQL5 里调用指标不走 EA 主循环硬算,而是用 iCustom 或内置的 iMACD、iRSI 这类函数先拿到指标句柄,再靠 CopyBuffer 取数据。这套机制从 MT5 诞生起就是标准做法,官方示例在 2013-09-27 那篇基础帖里被查看过 6712 次、收到 15 条讨论,说明新手卡这儿的概率不低。 下面这段是取 MACD 指标两个缓冲区的极简骨架,句柄拿不到就别谈后续信号。外汇与贵金属杠杆高,指标失效时亏损可能迅速扩大,任何调用都先在策略测试器里跑通再上真仓。 调用核心是先建句柄、再拷缓冲、最后判空。句柄为负数基本等于指标名写错或周期不对,这时候 CopyBuffer 会直接返回 -1,硬读数组只会喂给 EA 一堆垃圾值。
class="type">int macd_handle = iMACD(_Symbol, PERIOD_CURRENT, class="num">12, class="num">26, class="num">9, PRICE_CLOSE); if(macd_handle == INVALID_HANDLE) class="kw">return; class="type">class="kw">double macd_main[class="num">1], macd_signal[class="num">1]; CopyBuffer(macd_handle, class="num">0, class="num">0, class="num">1, macd_main); CopyBuffer(macd_handle, class="num">1, class="num">0, class="num">1, macd_signal);
EA源文件怎么从零建起来
在 MQL5 里调指标基本绕不开 IndicatorCreate() 和 iCustom(),两者都只吐出一个指标句柄(handle),后续取值、计算全靠这个整数句柄去索引。句柄不是数据本身,更像 MT5 内核里那块指标缓冲区的门牌号,搞错这一步后面全白忙。 新建 EA 最顺手的办法是开 MetaEditor,走 File -> New 调出 MQL5 Wizard。第一步选「EA 交易」点 Next;第二步填 EA 名称(必填)和作者,输入参数可以先留空,后面直接在代码里补。 点 Finish 后向导会生成一份最小可编译骨架,里面只包含 OnInit、OnDeinit、OnTick 三个空函数。下面这段就是默认产出的源码,注意版权行里的作者名会直接写成你刚填的字段。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| SampleMQL5.mq5 | class=class="str">"cmt">//| Copyright KlimMalgin | class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "KlimMalgin" class="macro">#class="kw">property link "" class="macro">#class="kw">property version "class="num">1.00" class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| EA初始化函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- 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">//--- } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| EA tick函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class=class="str">"cmt">//--- } class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| SampleMQL5.mq5 | class=class="str">"cmt">//| Copyright KlimMalgin | class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "KlimMalgin" class="macro">#class="kw">property link "" class="macro">#class="kw">property version "class="num">1.00" class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| EA初始化函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- 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">//--- } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| EA tick函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { class=class="str">"cmt">//--- } class=class="str">"cmt">//+------------------------------------------------------------------+
◍ 拆开 EA 源文件看骨架
打开任意 MT5 的 EA 源码,最顶端是一段头注释,写清文件名和作者;紧跟着是 #property 区块,用来声明程序属性。这里有个坑:属性必须写在主 mql5 文件里,被 include 进来的文件就算写了 #property 也会被编译器直接忽略。 头文件和属性之后是输入参数区(初期可留空)与全局变量声明。再往下才是真正跑逻辑的三个事件函数。OnInit() 在 EA 加载、品种属性变更或周期切换时触发一次,负责初始化;OnDeinit(const int reason) 同样只跑一次,在 EA 停止或重初始化时执行,reason 里带着退出的原因代码;OnTick() 最频繁,所在图表每来一个新报价就调用一次。 想在 MT5 里验证很简单:新建一个空白 EA,把 OnInit/OnDeinit/OnTick 各打印一行 Comment,挂上 EURUSD 图表,切换周期就能看到前两个函数各跑一次,而报价跳动会刷屏 OnTick。外汇与贵金属杠杆高,实盘前务必先在策略测试器跑历史数据。
「从 iCustom 到句柄:MQL5 取数逻辑变了」
老 MQL4 玩家刚切到 MQL5 最容易踩的坑,就是还想着用 iCustom() 按柱索引直接掏指标缓冲区。MQL5 改了路数:先拿句柄(handle),再用 CopyBuffer() 按区间把值拷出来,柱索引变成 CopyBuffer 的参数而非指标调用的参数。 句柄本质就是一个 int 型整数,是某个指标实例的唯一标识。拿到它之前,你跟指标之间根本没有通信通道。MQL5 给句柄提供了两条等价路径:IndicatorCreate() 成功返回句柄、失败返回 -1;或者直接调具体技术指标函数(如 iMA、iRSI),返回值同样是句柄或 -1。 两种写法在 MT5 里跑出来的结果没有优劣之分,选哪个纯看你是想动态建指标还是直接调现成技术函数。开 MT5 按 F4 建个空 EA,分别用两种方式取一下 EURUSD 的 MA 句柄,Print 出来对比整数返回值,比看文档直观得多。外汇与贵金属杠杆高,实盘前务必先在策略测试器验证句柄失效(返回 -1)的异常处理。