从基础到中级:指标(四)(基础篇)
◍ MT5 示例文章的冷启动数据
MetaTrader 5 客户端里有一类面向指标教学的示例文章,定位在从基础到中级的过渡带,用具体代码带读者理解指标运行机制。 这类内容在平台内的初始曝光并不高:一篇发布于 4 月 7 日 10:12 的示例帖,截至统计时仅 295 次浏览、0 条评论,说明纯代码型教学在没有社区推送的情况下,自然流量相当有限。 对外汇与贵金属交易者而言,这类材料的高风险属性不变——指标只是概率工具,任何从历史 K 线跑出的逻辑都不能直接等同于未来胜率,开 MT5 自己复跑才是验证的第一步。
「静态实现的边界与动态需求」
上一节里我们用编译指令把指标类型写死在代码里,这在 MQL5 里叫静态实现:编译后用户没法切换渲染方式。对多数常规盯盘场景,写死一种画法已经够用,但外汇和贵金属的高波动环境里,分析视角经常要换,硬改代码重编译太低效。 实际交易中,沟通观点或跑自动形态识别时,往往需要在同一个窗口里切到不同指标。本文要做的,是抽出一个简单概念,让你不重编译就能派生出多种指标——MT5 打开任意品种右键添加指标时,这种灵活度直接决定复盘速度。 外汇与贵金属属高风险品种,指标只是概率辅助,切来切去不代表信号更准。先从最基础、也最容易忽略的一个思路说起:用统一接口封装指标创建,后面几种变体都从这一根上长出来。
内含线指标的缓冲区顺序坑
内含线是指完全落在前一根 K 线高低点范围内的烛形,但不少交易者会把「未突破某根更老 K 线边界」的连续多根 K 线都算作内含线。新手常想给这类形态做颜色标记,却在 MT5 里卡在指标声明这一步。 最典型的坑是指缓冲区顺序写错。下面这段代码声明了 5 个缓冲区、用 DRAW_COLOR_CANDLES 画彩色 K 线,但把 High 放在索引 0、Open 放在 1、Close 在 2、Low 在 3。编译能通过,可图表上 K 线颜色变了,实体格式也跟着畸变——因为 MT5 按特定顺序消费缓冲区,顺序不对就画出非预期形态。 [CODE] //+------------------------------------------------------------------+
| // | 代码 01:错误缓冲区顺序示例 |
|---|
//+------------------------------------------------------------------+ #property copyright "Daniel Jose" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrRed, clrRoyalBlue, clrGreen #property indicator_buffers 5 #property indicator_plots 1 double gl_Buff_High[], gl_Buff_Open[], gl_Buff_Close[], gl_Buff_Low[], gl_Buff_Color[]; int OnInit() { SetIndexBuffer(0, gl_Buff_High, INDICATOR_DATA); 修正只需把索引顺次改成 Open=0、High=1、Low=2、Close=3,颜色缓冲放最后。改动后 MT5 才能正确识别每根蜡烛的绘制方式,颜色模式不再破坏 K 线结构。 循环从第 29 行起扫历史柱,到第 38 行定期查内含线条件。注意:只能在 K 线收盘后判定内含线,盘中若出现又消失的结构,会在下一tick因条件失效而不再标示。若想支持「多根 K 线同处一个老 K 线边界内」的宽定义,可在 OnCalculate 里加静态变量记录边界,第 42–44 行查高低突破、第 45 行在无内含线时清边界重搜。外汇与贵金属波动快,这种形态识别失效概率不低,实盘前务必在 MT5 历史数据里验证。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 代码 class="num">01:错误缓冲区顺序示例 class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose" class="macro">#class="kw">property indicator_type1 DRAW_COLOR_CANDLES class="macro">#class="kw">property indicator_color1 clrRed, clrRoyalBlue, clrGreen class="macro">#class="kw">property indicator_buffers class="num">5 class="macro">#class="kw">property indicator_plots class="num">1 class="type">class="kw">double gl_Buff_High[], gl_Buff_Open[], gl_Buff_Close[], gl_Buff_Low[], gl_Buff_Color[]; class="type">int OnInit() { SetIndexBuffer(class="num">0, gl_Buff_High, INDICATOR_DATA);
◍ 缓冲区绑定与K线重绘的颜色判定
指标初始化收尾要把四个价格序列和一个颜色索引绑到图表缓冲区。SetIndexBuffer 的第二个参数接全局数组,第三个参数用 INDICATOR_DATA 标价格、INDICATOR_COLOR_INDEX 标调色板序号,漏掉颜色索引那根线就不会跟着涨跌变色。 OnCalculate 里只跑增量:prev_calculated 大于 0 时从上一根减 1 的位置接着写,避免每 tick 重算全历史。High/Low/Open/Close 直接搬进自定义缓冲,方便后续做形态比对而不是读原数组。 颜色赋值先看当根开收:Open 大于 Close 给 0 号色(通常指阴线),否则给 2 号色。若前一根存在且 High[c-1] > High[c] 同时 Low[c-1] < Low[c],说明价格被前一根完全包住,就把该根改成 1 号色标成包含关系——这是价格行为里看多空博弈压缩的直接可视信号,外汇与贵金属波动下这种包含棒出现频率可能偏高,杠杆品种风险大,仅作结构参考。 返回 rates_total 告诉终端算到哪根,终端依此决定下次从哪起步。复制下面片段到 MT5 指标工程,改调色板 0/1/2 对应的具体 RGB 就能立刻看出包含棒分布。
SetIndexBuffer(class="num">1, gl_Buff_Open, INDICATOR_DATA); SetIndexBuffer(class="num">2, gl_Buff_Close, INDICATOR_DATA); SetIndexBuffer(class="num">3, gl_Buff_Low, INDICATOR_DATA); SetIndexBuffer(class="num">4, gl_Buff_Color, INDICATOR_COLOR_INDEX); class="kw">return INIT_SUCCEEDED; class="type">int OnCalculate(const class="type">int rates_total, const class="type">int prev_calculated, const class="type">class="kw">datetime &Time[], const class="type">class="kw">double &Open[], const class="type">class="kw">double &High[], const class="type">class="kw">double &Low[], const class="type">class="kw">double &Close[], const class="type">long &TickVolume[], const class="type">long &Volume[], const class="type">int &Spread[]) { for (class="type">int c = (prev_calculated > class="num">0 ? prev_calculated - class="num">1 : class="num">0); c < rates_total; c++) { gl_Buff_High[c] = High[c]; gl_Buff_Open[c] = Open[c]; gl_Buff_Close[c] = Close[c]; gl_Buff_Low[c] = Low[c]; gl_Buff_Color[c] = (Open[c] > Close[c] ? class="num">0 : class="num">2); if ((c - class="num">1) > class="num">0) gl_Buff_Color[c] = ((High[c - class="num">1] > High[c]) && (Low[c - class="num">1] < Low[c]) ? class="num">1 : gl_Buff_Color[c]); } class="kw">return rates_total; }