首页 / 交易学院 / 小布知识库 / 指标句柄进阶:IndicatorCreate 与 iCustom
指标句柄进阶:IndicatorCreate 与 iCustom
🎯

指标句柄进阶:IndicatorCreate 与 iCustom

两种拿指标句柄的方式与 CopyBuffer 取数正确姿势

MQL5 编程 难度 · 入门 2026-07-15 11 分钟阅读
#MQL5#指标句柄#IndicatorCreate#iCustom#CopyBuffer

MQL5 不再像 MT4 那样直接取某根 K 的指标值,而是先拿指标句柄(一个整数),再用 CopyBuffer 按区间复制数据。句柄由 IndicatorCreate 或技术指标函数返回,失败返回 -1。

一、句柄是什么

句柄是搭配特定指标使用的唯一标识符,存为 int。拿到句柄后,用 CopyBuffer 按给定间隔取指标值,而不是逐根传柱索引。

二、两种拿句柄的方式

三、用 MqlParam 给指标传参

调 IndicatorCreate 前填 MqlParam 数组,每个元素用 type 字段指明 integer_value / double_value / string_value;MA 用 TYPE_INT,SAR 用 TYPE_DOUBLE。数组大小用 ArrayResize 设成参数个数。

✦ 句柄只建一次
指标句柄只要在 OnInit 里创建一次,别在 OnTick 里反复建——每 tick 重建既浪费又可能因计算未完成而取不到数据。

四、iCustom 调用自定义指标

五、用 CopyBuffer 取数据

设 ArraySetAsSeries(数组, true) 让索引 0 = 最新柱;CopyBuffer(句柄, 缓冲区号, 起始柱, 柱数, 数组);失败返回 -1,用 GetLastError 打印排查。

⚠ 务必检查返回值
忽略 CopyBuffer 返回值,会让 EA 在取不到数据时用陈旧/空数组做决策,这类 bug 很难肉眼发现。

六、iCustom 与 IndicatorCreate 的区别

iCustom 适合「调用现成指标文件」,你只给文件名加参数就拿句柄,简单直接,但拿不到指标内部中间缓冲。IndicatorCreate 则能在代码里动态创建指标实例、指定缓冲数量与类型,灵活度更高,适合自己拼装复杂指标。

选型:读别人的指标用 iCustom;要运行时按条件生成不同配置的指标,用 IndicatorCreate。两者拿到的都是 handle,后续一律用 CopyBuffer 取数,思路一致。

七、CopyBuffer 实战与返回校验

句柄不是数据,CopyBuffer(handle, buf_idx, start, count, array) 才是取数。它的返回值是「实际拷到的元素个数」,必须和期望的 count 比较,少于说明数据未就绪,此时用数组值会拿到脏数。

double buf[];
int h = iCustom(_Symbol, PERIOD_M15, "MyIndi", 14);
int n = CopyBuffer(h, 0, 0, 3, buf);
if(n < 3) return;            // 数据未就绪,跳过本 tick
double v = buf[0];
✦ 返回值是个数不是布尔
CopyBuffer 返回拷贝到的元素数。不校验就直接用 buf[0],遇到未就绪会拿到 0 或残留值,信号随之失真。

八、句柄失效与重连

句柄可能因品种下架、图表周期关闭、指标文件被删而失效,此后 CopyBuffer 持续返回 0。稳健做法是在连续失败时重建句柄,或至少在日志报警,而不是静默用空数据交易。

一个易忽略点:切换品种或周期后旧句柄作废,必须在新环境重新 iCustom / IndicatorCreate。把句柄获取收进「按需 lazily 获取 + 失败重试」的小函数,能省掉大量重复判断。

九、小结

✦ 小结
句柄是指标数据的钥匙,不是数据本身:iCustom 调现成、IndicatorCreate 动态造,取数统一走 CopyBuffer 且必校验返回个数。句柄会失效,要 lazily 获取加重试,别拿空数据去发信号。

常见问题

用类库、做大型项目用 IndicatorCreate 更整齐;快速写 EA 测想法用 iCustom 更省事。两者拿到的句柄用法完全一致。
指标会收到错误的参数类型,句柄可能创建失败(返回 -1)或算出错误数值;整数参数用 TYPE_INT,小数用 TYPE_DOUBLE。
让缓冲数组和 K 线时间序列一致:索引 0 是最新柱,写策略判断上穿/下穿时不用倒着数。
说明指标创建失败,先用 Print(GetLastError()) 看原因(参数错、品种不存在、指标未编译等),再在 OnInit 里早返回。
单缓冲指标填 0;多缓冲(如 MACD 有主线/信号线/柱)按文档顺序 0/1/2 分别对应,填错会取到别的线。