在 MQL5 中创建多色彩指标(基础篇)
📘

在 MQL5 中创建多色彩指标(基础篇)

第 1/3 篇

◍ 给 MT5 指标上多套颜色

MQL5 里画指标线不只能单调单色,用多色彩缓冲(color buffer)可以按条件给每一根柱子上不同颜色,视觉上直接区分状态。这套机制在 2013 年 10 月就有人实做过,原帖浏览量 4462、跟帖 13 条,说明老交易员早就在折腾这类可读性优化。 核心做法是声明多个颜色索引,并在 OnCalculate 里按数值区间给缓冲写颜色常量。下面这段是最小可跑骨架,去掉了具体判断逻辑,只保留多色缓冲注册方式。 [CODE] #property indicator_buffers 2 #property indicator_color1 clrGreen #property indicator_color2 clrRed double ExtBuffer1[]; double ExtBuffer2[]; int OnInit() { SetIndexBuffer(0, ExtBuffer1); SetIndexBuffer(1, ExtBuffer2); return(INIT_SUCCEEDED); } [/CODE] 逐行拆:前两句预编译指令告诉终端这条指标有 2 个缓冲、分别默认绿和红;两个 double 数组就是实际存值的容器;OnInit 里 SetIndexBuffer 把数组绑到 0 号和 1 号缓冲上。你开 MT5 新建指标把这段贴进模板,编译后拖到图表就能看到两条空线,之后往数组里填判断结果即可。 外汇和贵金属行情跳变快,多色线只是降低盯盘误读概率,不预示方向,实盘仍属高风险。

MQL5 / C++
class="macro">#class="kw">property indicator_buffers class="num">2
class="macro">#class="kw">property indicator_color1 clrGreen
class="macro">#class="kw">property indicator_color2 clrRed
class="type">class="kw">double ExtBuffer1[];
class="type">class="kw">double ExtBuffer2[];
class="type">int OnInit()
{
   SetIndexBuffer(class="num">0, ExtBuffer1);
   SetIndexBuffer(class="num">1, ExtBuffer2);
   class="kw">return(INIT_SUCCEEDED);
}

「MQL5 给指标线逐段上色的底层能力」

MQL4 时代也能给指标行指定颜色,但整行只能是一种色,想做多色彩得靠多个指标缓冲区相互重叠来硬凑,维护起来很别扭。MT5 的 MQL5 直接把这件事做进了语言层:指标线可以按区段分别指定颜色,独立的柱、烛形、直方图、箭头也能逐个上色。 本文只挑两种绘制风格展开——DRAW_COLOR_LINE 和 DRAW_COLOR_CANDLES。其余彩色风格的差异基本只在于缓冲区数量,机制是同一套,搞懂这两个就能自行类推。 想跟着验证,建议先把 MQL5 参考里指标相关的数据结构过一遍,不然缓冲区和彩色索引缓冲区的对应关系容易看晕。外汇和贵金属市场杠杆高、滑点频发,任何指标着色方案都只是辅助观察,不构成方向判断依据。

彩色指标到底解决了什么

在 MT5 里把指标输出染色,不是图好看那么简单。最直接的价值是能在同一根烛形上叠出第二层信息:比如让 MACD 柱线的颜色受 RSI 数值驱动,超买区自动转红、超卖区转绿,一眼就能看出动能和摆荡位置是否共振。 比起灰阶线形,彩色编码能把'该看哪'直接标出来。重要信号(如穿越零轴且动量转强)用高饱和色突出,普通区用低明度灰,视觉权重立刻拉开,扫盘时漏读概率会降一截。 当然也有人只是拿配色统一客户端风格,这不算错,但外汇和贵金属杠杆高、跳空频繁,靠颜色偷懒代替规则验证反而容易吃亏。建议先把一套逻辑写进颜色条件,再谈美观。

◍ 自定义彩色指标的双缓冲骨架

MT5 指标的本质是拿输入数据算完往缓冲区填,客户端按绘制类型把缓冲区画出来。缓冲区是全局声明的双精度数组,一个绘图风格可能绑多个缓冲区,但图形(线、柱、箭头)和缓冲区不是一回事:图形是窗口里看到的,缓冲区只是装数据的数组,有些只供内部计算根本不画。 以最简彩色指标为例,#property indicator_buffers 2 定了两根缓冲区:一根装开盘价类数据,一根装颜色索引。indicator_plots 1 是说只画一个图形,绘图数可以小于等于缓冲数,差的那根往往拿去算中间量。带 COLOR 字样的风格都强制要颜色索引缓冲区,比如 DRAW_COLOR_HISTOGRAM 就吃一根数据缓冲加一根颜色缓冲。 静态配色用 #property indicator_color1 Red,Green,BlueViolet,编译期定死 3 色且索引从 0 起。动态配色靠 PlotIndexSetInteger:先传 PLOT_COLOR_INDEXES 告之图形 0 有 2 个颜色索引,再逐条绑 0 号蓝、1 号橙。动态法会在运行时覆盖静态法,两种都写时以后者为准。 OnInit 里 SetIndexBuffer(0, buffer_line, INDICATOR_DATA) 把 0 号绑数据,SetIndexBuffer(1, buffer_color_line, INDICATOR_COLOR_INDEX) 把 1 号绑颜色,顺序必须先数据后颜色。OnCalculate 中若开盘高于收盘给颜色数组写 0(蓝),低于则写 1(橙),逻辑极简,开 MT5 新建指标粘下面代码就能看到独立窗口里的双色直方。外汇与贵金属杠杆高,验证时请用模拟盘。

MQL5 / C++
class="macro">#class="kw">property copyright "ProF"
class="macro">#class="kw">property indicator_separate_window
class="macro">#class="kw">property indicator_buffers class="num">2
class="macro">#class="kw">property indicator_plots class="num">1
class="macro">#class="kw">property indicator_type1 DRAW_COLOR_HISTOGRAM
class="macro">#class="kw">property indicator_width1 class="num">3
class="macro">#class="kw">property indicator_color1 Red,Green,BlueViolet
class="type">class="kw">double buffer_line[], buffer_color_line[];
class="type">int OnInit()
  {
   SetIndexBuffer(class="num">0,buffer_line,INDICATOR_DATA);
   SetIndexBuffer(class="num">1,buffer_color_line,INDICATOR_COLOR_INDEX);
   PlotIndexSetInteger(class="num">0,PLOT_COLOR_INDEXES,class="num">2);
   PlotIndexSetInteger(class="num">0,PLOT_LINE_COLOR,class="num">0,Blue);
  }

「用颜色索引区分阴阳线的柱状图」

在 MT5 自定义指标里,想让一根彩色柱状图随 K 线涨跌换色,核心不是改画笔,而是先喂两个缓存:一个放数值,一个放颜色索引。上面这段把 indicator_color1 设成 Red,Green,BlueViolet,但实际只通过 PlotIndexSetInteger 启用了 0 号和 1 号两种索引,分别对应蓝和橙,多余的颜色声明不会参与绘制。 OnCalculate 里从 prev_calculated 开始循环,避免每 tick 重算全部历史。判断 open[i]>close[i] 时给 buffer_color_line[i] 写 0(跌,蓝),否则写 1(涨,橙);同时把 buffer_line[i] 填成开盘价。这样柱子高低表达的是开盘价位置,颜色表达的是该根阴阳状态。 返回值用 rates_total-1,意味着最后一柱留待下一 tick 重算,这是 MT5 指标防止当前未闭合 K 线被锁死的常规做法。外汇与贵金属波动剧烈,这类视觉辅助只帮你看清结构,不代表任何方向概率优势,实盘须自担高风险。 直接把这段逻辑粘进 MQ5 文件,编译后加载到 XAUUSD 的 M5 图,能立刻看到蓝橙交替的开口柱状——若你习惯用收盘价而非开盘价做基线,把 buffer_line[i]=open[i] 换成 close[i] 即可,颜色条件不用动。

MQL5 / C++
  PlotIndexSetInteger(class="num">0,PLOT_LINE_COLOR,class="num">1,Orange); class=class="str">"cmt">//1号索引 -> 橙色
  class="kw">return(class="num">0);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| 自定义指标迭代函数                                      					 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnCalculate(class="kw">const class="type">int rates_total,
                class="kw">const class="type">int prev_calculated,
                class="kw">const class="type">class="kw">datetime &time[],
                class="kw">const class="type">class="kw">double &open[],
                class="kw">const class="type">class="kw">double &high[],
                class="kw">const class="type">class="kw">double &low[],
                class="kw">const class="type">class="kw">double &close[],
                class="kw">const class="type">long &tick_volume[],
                class="kw">const class="type">long &volume[],
                class="kw">const class="type">int &spread[])
  {
  class=class="str">"cmt">//我们为每个柱形循环填充数据缓存,以及颜色索引缓存
  for(class="type">int i=prev_calculated;i<=rates_total-class="num">1;i++)
    {
    class=class="str">"cmt">//让我们添加一个简单的绘图条件 -> 如果开盘价格大于收盘价,那么:
    if(open[i]>close[i])
      {  buffer_color_line[i]=class="num">0;  }       class=class="str">"cmt">//分配颜色索引为0
    else
      {  buffer_color_line[i]=class="num">1;  }       class=class="str">"cmt">//分配颜色索引为1
    
    class=class="str">"cmt">//确定绘图数据,在这里是开盘价
    buffer_line[i]=open[i];
    }
  class="kw">return(rates_total-class="num">1); class=class="str">"cmt">//返回已经计算的柱形的数量,
                        class=class="str">"cmt">//由于最后一个柱形要重算,减1
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property indicator_buffers class="num">2 class=class="str">"cmt">///指标缓存数量
class="macro">#class="kw">property indicator_plots class="num">1   class=class="str">"cmt">//绘图图形个数
class="macro">#class="kw">property indicator_type1 DRAW_COLOR_HISTOGRAM  class=class="str">"cmt">//绘图样式 - 彩色柱状图
class="macro">#class="kw">property indicator_width1 class="num">3                    class=class="str">"cmt">//绘制线宽(可选)
class="macro">#class="kw">property indicator_color1 Red,Green,BlueViolet class=class="str">"cmt">//确定3种颜色用来绘图
class="type">class="kw">double buffer_line[]class=class="str">"cmt">/*数据缓存*/, buffer_color_line[]class=class="str">"cmt">/*颜色索引缓存*/;
SetIndexBuffer(class="num">0,buffer_line,INDICATOR_DATA);
SetIndexBuffer(class="num">1,buffer_color_line,INDICATOR_COLOR_INDEX);
class=class="str">"cmt">//确定用来绘图的颜色索引数量
PlotIndexSetInteger(class="num">0,PLOT_COLOR_INDEXES,class="num">2);
PlotIndexSetInteger(class="num">0,PLOT_LINE_COLOR,class="num">0,Blue);   class=class="str">"cmt">//0号索引 -> 蓝色
PlotIndexSetInteger(class="num">0,PLOT_LINE_COLOR,class="num">1,Orange); class=class="str">"cmt">//1号索引 -> 橙色

MT5 里给颜色赋值的三种写法

在 MQL5 里定义一个 color 类型变量,底层都绕不开 RGB 三通道。每个通道用 0–255 的十进制或 00–FF 的十六进制表达,数值越小颜色越暗,白色是 C'255,255,255' 或 C'0xFF,0xFF,0xFF',黑色则是 C'0,0,0'。 常值写法最直观,比如 C'10,20,255' 和 C'0x0A,0x14,0xFF' 是同一支蓝,只是数制不同,随你习惯选。数值写法要注意字节序:十六进制 0x0000FF 实际等于 C'0xFF,0x00,0x00',也就是纯红,首尾两对字节是反着的。 直接用 Web 颜色名(如 Red、Blue、Orange)最省事,但只能取 web-colors 标准集里的色,想做精细渐变还是得回到 RGB。下面这段代码把三种写法摆在一起,并验证了它们彼此等价——Alert 会打印 true。 外汇与贵金属图表美化虽不影响报价,但过度依赖视觉信号可能干扰客观判断,这类改动请先在模拟盘验证。

MQL5 / C++
class="type">class="kw">color color_var = C&class="macro">#x27;class="num">10,class="num">20,class="num">255&class="macro">#x27;;
class="type">class="kw">color color_var = C&class="macro">#x27;0x0A,0x14,0xFF&class="macro">#x27;;
class="type">class="kw">color color_var = 0xFFFFFF;  class=class="str">"cmt">// 白色
class="type">class="kw">color color_var = 0x0000FF;  class=class="str">"cmt">// 红色
class="type">class="kw">color color_var = class="num">16777215  class=class="str">"cmt">// 白色
class="type">class="kw">color color_var = 0x008000  class=class="str">"cmt">// 绿色
class="type">class="kw">color color_var = class="num">32768     class=class="str">"cmt">// 绿色
class="type">class="kw">color color_var = Red;      class=class="str">"cmt">//红色
class="type">class="kw">color color_var = Blue;     class=class="str">"cmt">//蓝色
class="type">class="kw">color color_var = Orange;   class=class="str">"cmt">//橙色
class="type">class="kw">color color1 = C&class="macro">#x27;class="num">255,class="num">0,class="num">0&class="macro">#x27;;
class="type">class="kw">color color2 = C&class="macro">#x27;0xFF,0x00,0x00&class="macro">#x27;;
class="type">class="kw">color color3 = 0x0000FF;
class="type">class="kw">color color4 = class="num">255;
class="type">class="kw">color color5 = Red;
Alert((color1==color2)
      && (color1==color2)
      && (color1==color4)
      && (color1==color5)); class=class="str">"cmt">//打印true

常见问题

用双缓冲结构,一个存数值一个存颜色索引,再在OnCalculate里按涨跌条件给对应bar写不同颜色索引即可。
不行。一个缓冲区放价格或数值,另一个专门放颜色索引,缺了颜色缓冲指标线就只能单一色。
小布能直接读取品种页上的彩色指标,把异常着色段标出来并给口语化解读,省去你逐根肉眼翻。
常见三种:用PLOT_LINE_COLOR逐索引设、用C'R,G,B'直接写RGB、或预定义颜色数组按条件取索引。
能把趋势延续、走弱、反转区域用颜色切开,一眼区分主升段和回调段,减少误读单色线的滞后。