请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化策略 帖子:3364680 新帖:1

在 MQL5 中创建多色彩指标

到此一游发表于:4 月 17 日 16:23回复(1)

简介

由于 MetaTrader 5 一干开发人员的努力,MQL5 语言应运而生。创新内容多种多样,但本文中我只想讲讲创建多色彩指标的可能性。MQL4 中也可以为某行指定颜色,但整行都相同,而且多色彩指标只能利用指标缓冲区的部分重叠来实现,很不方便。

MQL5 语言的开发人员却提供了一种新的可能性 - 为指标线的每个区段指定一个颜色(针对各行),为各个独立对象分别指定颜色(针对柱、烛形图、直方图、箭头)。如欲掌握本文内容,最好看一看 《MQL5 参考》。

我会试着于本文中论证下述主题:

  • 指标基础
  • 指标的数据缓冲区
  • 指标的彩色索引缓冲区
  • 以 RSI 指标为例介绍如何将单色绘制模式转换为多色彩模式(将 DRAW_LINE 绘制风格转换为 DRAW_COLOR_LINE)
  • 如何根据 RSI 指标值为烛形图涂色(采用 DRAW_COLOR_CANDLES 绘制风格)
  • 如何通过彩色索引缓冲区获取值
我们只研究两种颜色绘制风格 - DRAW_COLOR_LINE 和 DRAW_COLOR_CANDLES,其余绘制风格也仅仅是缓冲区数量方面有所差异而已。

为什么要用彩色指标?

使用彩色指标,您即能够:

  • 于烛形图上显示更多信息。
  • 实现指标混合(MACD 颜色取决于 RSI 值)。
  • 突显指标的重要信号。
  • 只是单纯地装饰美化您的客户端。

只需要开动您的想像力,让您的交易更加便利。

MQL5 基础

我们从指标原理着手开始。

总体来讲,指标会获取输入数据(价格、其它指标数据),履行一些计算并向多个缓冲区填入相应数据。客户端会标绘源于缓冲区的信息,该信息由指标根据其绘制类型提供。

绘图风格由开发人员定义。指标缓冲区为双精度数组,于全局层面声明。如果某风格需要一个以上的缓冲区,则可将多个缓冲区捏合到图形标绘中。如果您从未创建过自定义指标,则可以阅读相关文章(其中包含基础知识的详细介绍):“MQL5:创建您自己的指标” 与 “给新手看的 MQL5 中的自定义指标”。

下面是彩色指标的最精简代码,我来讲讲其组成部分:

//+------------------------------------------------------------------+
//|                                         test_color_indicator.mq5 |
//|                                                             ProF |
//|                                                          http:// |
//+------------------------------------------------------------------+
#property copyright "ProF"                      //作者
#property indicator_separate_window             //指标将在独立的窗口中绘制
#property indicator_buffers 2                   //指标缓存数量
#property indicator_plots 1                     //绘制指标个数
#property indicator_type1 DRAW_COLOR_HISTOGRAM  //绘图样式 - 彩色柱状图
#property indicator_width1 3                    //绘图图形的宽度(可选)
#property indicator_color1 Red,Green,BlueViolet //确定3种颜色用来绘图

//缓存声明
double buffer_line[]/*Data Buffer*/, buffer_color_line[]/*Color index buffer*/;

//+------------------------------------------------------------------+
//| 自定义指标初始化函数                                                |
//+------------------------------------------------------------------+
int OnInit()
  {
//为指标缓存分配数据数组
   SetIndexBuffer(0,buffer_line,INDICATOR_DATA);

//为指标缓存分配颜色索引数组
   SetIndexBuffer(1,buffer_color_line,INDICATOR_COLOR_INDEX);

//确定用来绘图的颜色索引数量
   PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,2);

//为每个索引设置颜色
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Blue);   //0号索引 -> 蓝色
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,Orange); //1号索引 -> 橙色
   return(0);
  }
//+------------------------------------------------------------------+
//| 自定义指标迭代函数                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   //我们为每个柱形循环填充数据缓存,以及颜色索引缓存
   for(int i=prev_calculated;i<=rates_total-1;i++)
     {
      //让我们添加一个简单的绘图条件 -> 如果开盘价格大于收盘价,那么:
      if(open[i]>close[i])
        {   buffer_color_line[i]=0;   }       //分配颜色索引为0
      else
        {  buffer_color_line[i]=1;   }       //分配颜色索引为1
      
      //确定绘图数据,在这里是开盘价
      buffer_line[i]=open[i];
     }

   return(rates_total-1); //返回已经计算的柱形的数量,
                         //由于最后一个柱形要重算,减1
  }
//+------------------------------------------------------------------+

我们来检查一下编写彩色指标的细节:

#property indicator_buffers 2 ///指标缓存数量
#property indicator_plots 1   //绘图图形个数

我们于第一行中指定指标缓冲区的数量,本例中有两个缓冲区:

  1. 指标数据缓冲区,本例中为开盘价;
  2. 彩色索引缓冲区。

我们再于第二行中指定图形的数量。区分开图形与指标缓冲区非常重要。图形是指标的线(烛形、柱、箭头等)。指标缓冲区是一个含数据的数组,需要标绘,带有彩色索引的数组或是供指标内部计算使用的数组(该类型不于指标窗口中绘制)。

标绘的数量可小于等于缓冲区的数量,它取决于绘制风格以及用于计算的缓冲区的数量。绘制风格与每种风格需要的缓冲区数量表,请见 《MQL5 参考》“绘制风格”章节。

“最好玩的内容”从这里开始:

#property indicator_type1 DRAW_COLOR_HISTOGRAM  //绘图样式 - 彩色柱状图
#property indicator_width1 3                    //绘制线宽(可选)
#property indicator_color1 Red,Green,BlueViolet //确定3种颜色用来绘图

我们于第一行中指定绘图风格,本例的绘图风格是从零线开始的一个直方图。此绘图风格要求一个数据缓冲区和一个彩色索引缓冲区。所有包含 "COLOR" 一词的绘图风格都要求一个彩色索引缓冲区。

我们再于第二行中将行宽指定为 3 像素,默认行宽是 1 像素。

在第三行中,我们指定图形索引的颜色,本例中我们指定 "Red", "Green" 和 "BlueViolet" 三种颜色。颜色索引从零开始:0-"Red",1-"Green",2-"BlueViolet"。这些都是设置图形颜色必需的颜色。颜色的指定有多种方式,其中就包括 "#property indicator_color1"。这是一种“静态”方法,用于程序编译阶段。后文我们还会讨论第二种方法。

double buffer_line[]/*数据缓存*/, buffer_color_line[]/*颜色索引缓存*/;

我们在这里声明两个用作缓冲区的数组,第一个会被用作一个数据缓冲区,而第二个则会被用于彩色索引,两个全作为双精度型数组声明。

我们一起来研究指标初始化函数:

SetIndexBuffer(0,buffer_line,INDICATOR_DATA);

我们在这里为指标缓冲区分配一个数组,指定的 "INDICATOR_DATA" 缓冲区类型意味着该缓冲区将被用于存储指标值(即,它是指标的数据缓冲区)。注意第一个参数为零 (0) - 它是缓冲区索引。

SetIndexBuffer(1,buffer_color_line,INDICATOR_COLOR_INDEX);

我们在这里为指标缓冲区分配一个数组,并指定 "INDICATOR_COLOR_INDEX" 作为缓冲区类型 - 也就是说,此缓冲区会被用于存储指标每个柱的颜色索引。注意第一个参数为 (1) - 它是缓冲区索引。

缓冲区定序必须具体:首先是指标数据缓冲区,然后是颜色索引缓冲区。

最后,再讲讲指定图形颜色的第二种方式(指定颜色索引):

//确定用来绘图的颜色索引数量
PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,2);

我们在这里指定颜色索引的数量。此函数的第一个参数为 "0",它是图形索引。注意这种情况下我们必须指定颜色索引的数量(第一种方法中会由编译器计算)。

PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Blue);   //0号索引 -> 蓝色
PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,Orange); //1号索引 -> 橙色

我们在这里指定每个索引的颜色。此函数的第一个参数是图形索引,第三个参数是颜色索引,从零开始。设置颜色索引的第二种方式存在下述差异:颜色数量及其索引可以动态指定,比如利用函数。如果您两种方法都用,请记得动态方法会推翻静态方法(也就是第一种方法)。

接下来是研究 OnCalculate 函数,我们会为指标的图形计算缓冲区的值。我们选择直方图最简单的颜色选择规范,如果开盘价高于收盘价,则我们为当前的缓冲区元素分配的颜色索引(于 "buffer_color_line" 数组中)为零 (0)。前面已经指定,零 (0) 颜色索引对应的是 "Blue" 颜色。

如果开盘价低于收盘价,则我们分配为颜色索引为 1,对应 Orange 颜色。此为该简单示例:

测试指标

足见其简单,只需要我们发挥一点想像力就好了。

颜色设置的方法

现在,我们来详细地介绍一下颜色设置。

根据“MQL5 参照”,颜色可通过不同的方法来指定:

  • 常值表示;
  • 数值表示;
  • 利用颜色名称表示。

我们全都看一看。

常值表示

color color_var = C'10,20,255';
color color_var = C'0x0A,0x14,0xFF';

颜色根据 RGB (Red, Green, Blue) 定义,任何颜色都可作为这三种颜色的某种组合而呈现。相应地,第一个数字对应 Red (红色)组件。第二个对应 Green (绿色),第三个对应 Blue (蓝色)组件。数字(以十进制形式)可从 0 到 255。而以十六进制为基础,则值可从 00 到 FF。

第一行与第二行等同:我们将 Blue 颜色分配给 color_var 变量。差异在于指定数制中数字的表示法,第一行是十进制,第二行为十六进制。没有任何差别,您可以选择自己便利的方式。较小的数字对应着较暗的色彩,白色为:"C'255,255,255'" 或 "C'0xFF,0xFF,0xFF'",而黑色则为:"C'0,0,0'" 或 "C'0x00,0x00,0x00'"。

数值表示

color color_var = 0xFFFFFF;  // 白色
color color_var = 0x0000FF;  // 红色
color color_var = 16777215   // 白色
color color_var = 0x008000   // 绿色
color color_var = 32768      // 绿色

颜色分十六进制与十进制两种数制呈现。比如说,值 "0x0000FF" 等同于 "C'0xFF,0x00,0x00'",我们也能看到,开始和最后的数值对是交换的。

想要在十进制数制中获取值 16777215,我们需要将 FFFFFF 从十六进制转换为十进制。

颜色名称

color color_var = Red;    //红色
color color_var = Blue;   //蓝色
color color_var = Orange; //橙色

此为最简单的方式,但您只可以指定 web-colors 集中的颜色。

我们来总结一下可以如何指定颜色。

所有的三种方法都是等同的,例如:

color color1 = C'255,0,0';
color color2 = C'0xFF,0x00,0x00';
color color3 = 0x0000FF;
color color4 = 255;
color color5 = Red;

Alert((color1==color2)
       && (color1==color2)
       && (color1==color4)
       && (color1==color5)); //打印true

练习

我们已经完成了基础学习,现在,我们就来研究一下如何根据其它指标值(比如 RSI 值)利用不同的颜色为图表烛形上色。如欲创建图表上的彩色烛形图,我们需要编写一个将会在图表上标绘应用颜色烛形的指标。

此为指标代码,如果 RSI 值小于 50%,则其标绘蓝色烛形,否则标绘橙色烛形。

为避免读者混淆,不检查数据的正确性及有无错误处理。但在编写指标的工作代码时却必须考虑这些细节。

//+------------------------------------------------------------------+
//|                                                   cand_color.mq5 |
//|                                                             ProF |
//|                                                          http:// |
//+------------------------------------------------------------------+
#property copyright "ProF"                      //作者
#property indicator_chart_window                //指标在独立窗口显示

                                          //确定指标缓存的个数
//4个蜡烛线缓存,1个颜色索引缓存,1个RSI数据缓存
#property indicator_buffers 6

//确定数据窗口的名称
#property indicator_label1 "Open;High;Low;Close"

#property indicator_plots 1                     //绘图图形个数
#property indicator_type1 DRAW_COLOR_CANDLES    //绘图样式:彩色蜡烛图
#property indicator_width1 3                    //绘图图形的宽度(可选)

                                          //缓存声明
double buffer_open[],buffer_high[],buffer_low[],buffer_close[]; //数据缓存
double buffer_color_line[];    //颜色索引缓存
double buffer_tmp[1];           //复制RSI值的临时缓存
double buffer_RSI[];            //RSI指标缓存
int handle_rsi=0;               //RSI指标句柄
//+------------------------------------------------------------------+
//| 自定义指标初始化函数                                                |
//+------------------------------------------------------------------+
int OnInit()
  {
/**
        *       缓存分配的顺序非常重要!
        *      数据缓存最先
        *       接下去是颜色缓存
        *       最后是用来做内部计算的缓存。
        */
//为指标缓存分配数组
   SetIndexBuffer(0,buffer_open,INDICATOR_DATA);
   SetIndexBuffer(1,buffer_high,INDICATOR_DATA);
   SetIndexBuffer(2,buffer_low,INDICATOR_DATA);
   SetIndexBuffer(3,buffer_close,INDICATOR_DATA);

//为指标的颜色索引缓存分配数组
   SetIndexBuffer(4,buffer_color_line,INDICATOR_COLOR_INDEX);

//为RSI指标缓存分配数组
   SetIndexBuffer(5,buffer_RSI,INDICATOR_CALCULATIONS);

//定义用来绘图的颜色索引数值
   PlotIndexSetInteger(0,PLOT_COLOR_INDEXES,2);

//为每个索引设置颜色
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,0,Blue);   //0号索引 -> 蓝色
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,1,Orange); //1号索引 -> 橙色
   
//获取RSI指标句柄,有必要得到它的值
   handle_rsi=iCustom(_Symbol,_Period,"Examples\\RSI");
   return(0);
  }
//+------------------------------------------------------------------+
//| 自定义指标迭代函数                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//在循环中我们为每个柱形填充数据缓存,以及颜色索引缓存
   for(int i=prev_calculated;i<=rates_total-1;i++)
     {
      //将RSI指标的数据复制到临时缓存buffer_tmp中
      CopyBuffer(handle_rsi,0,BarsCalculated(handle_rsi)-i-1,1,buffer_tmp);
      //将值从临时缓存中复制到指标缓存中
      buffer_RSI[i]=buffer_tmp[0];

      //设置绘图数据
      buffer_open[i]=open[i];  //开盘价
      buffer_high[i]=high[i];  //最高价
      buffer_low[i]=low[i];    //最低价
      buffer_close[i]=close[i];//收盘价

                               //添加一个简单条件 -> 如果RSI小于50:
      if(buffer_RSI[i]<50)
        {   buffer_color_line[i]=0;   } //为柱形分配颜色索引0
      else
        {  buffer_color_line[i]=1;   }  //为柱形分配颜色索1
     }
   return(rates_total-1); //返回已经计算的柱形的数量,
                         //由于最后一个柱形要重算,减1
  }
//+------------------------------------------------------------------+

就是这个样子:

取决于 RSI 值的彩色指标

看起来不错,但我们仍要深入。

我们利用多种色彩、根据 RSI 值来为烛形图上色,也就是所谓的渐变填充。

颜色可以手动指定,但要指定 30-40 种颜色可不太容易也不太方便。我们会执行下述步骤:我们会编写两个函数,第一个用于颜色索引,第二个用于根据函数的自变数获取颜色。该理念已写入注释。

//+------------------------------------------------------------------+
//|                                               cand_color_RSI.mq5 |
//|                                                             ProF |
//|                                                          http:// |
//+------------------------------------------------------------------+
#property copyright "ProF"                      //作者
#property indicator_chart_window                //指标在独立窗口显示

//确定指标缓存的个数
//4个蜡烛线缓存,1个颜色索引缓存,1个RSI数据缓存
#property indicator_buffers 6

//确定数据窗口的显示名称
#property indicator_label1 "Open;High;Low;Close"

#property indicator_plots 1                     //绘图图形个数
#property indicator_type1 DRAW_COLOR_CANDLES    //图样式:彩色蜡烛图
#property indicator_width1 3                    //线宽(可选)

                                          //缓存声明
double buffer_open[],buffer_high[],buffer_low[],buffer_close[];//数据缓存
double buffer_color_line[];     //颜色索引缓存
double buffer_tmp[1];          //RSI值的临时缓存
double buffer_RSI[];            //RSI指标缓存
int handle_rsi=0;               //RSI指标句柄
//+------------------------------------------------------------------+
//|    设置一个绘图图形的颜色                                           |
//+------------------------------------------------------------------+
/*
*       本函数设置一个绘图图形的颜色 
*       从绿色到蓝色50种颜色。
*       绘图颜色的索引传给函数。

void setPlotColor(int plot)
  {
   PlotIndexSetInteger(plot,PLOT_COLOR_INDEXES,50); //确定颜色个数

                                               //在循环中我们指定颜色
   for(int i=0;i<=24;i++)
     {
      PlotIndexSetInteger(plot,PLOT_LINE_COLOR,i,StringToColor("\"0,175,"+IntegerToString(i*7)+"\""));
     }
   for(int i=0;i<=24;i++)
     {
      PlotIndexSetInteger(plot,PLOT_LINE_COLOR,i+25,StringToColor("\"0,"+IntegerToString(175-i*7)+",175\""));
     }
  }
//+------------------------------------------------------------------+
//|  获取颜色索引                                                      |
//+------------------------------------------------------------------+
/*
*       本函数返回颜色索引
*       第一个参数是当前指标的值
*       第二个参数是指标的最小值
*       第三个参数是指标的最大值
*/
int getPlotColor(double current,double min,double max)
  {
   return((int)NormalizeDouble((50/(max-min))*current,0));
  }
//+------------------------------------------------------------------+
//| 自定义指标初始化函数                                                |
//+------------------------------------------------------------------+
int OnInit()
  {
/**
        *       指标缓存的顺序非常重要!
        *      数据缓存最先
        *       接下去是颜色缓存
        *       最后是用来做内部计算的缓存。
        */
//为指标缓存分配数组
   SetIndexBuffer(0,buffer_open,INDICATOR_DATA);
   SetIndexBuffer(1,buffer_high,INDICATOR_DATA);
   SetIndexBuffer(2,buffer_low,INDICATOR_DATA);
   SetIndexBuffer(3,buffer_close,INDICATOR_DATA);

//为颜色索引缓存分配数组
   SetIndexBuffer(4,buffer_color_line,INDICATOR_COLOR_INDEX);

//为RSI指标缓存分配数组
   SetIndexBuffer(5,buffer_RSI,INDICATOR_CALCULATIONS);

//指定颜色索引
   setPlotColor(0);

//获取RSI指标句柄,有必要得到它的值
   handle_rsi=iCustom(_Symbol,_Period,"Examples\\RSI",6);
   return(0);
  }
//+------------------------------------------------------------------+
//| 自定义指标迭代函数                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//我们为每个柱形循环填充数据缓存,以及颜色索引缓存
   for(int i=prev_calculated;i<=rates_total-1;i++)
     {
      //将RSI指标的数据复制到临时缓存buffer_tmp中
      CopyBuffer(handle_rsi,0,BarsCalculated(handle_rsi)-i-1,1,buffer_tmp);
      //然后从临时缓存中将数据复制出来
      buffer_RSI[i]=buffer_tmp[0];

      //确定绘图数据
      buffer_open[i]=open[i];  //开盘价
      buffer_high[i]=high[i];  //最高价
      buffer_low[i]=low[i];    //最低价
      buffer_close[i]=close[i];//收盘价

      //根据RSI指标值绘制蜡烛图
      //RSI = 0     - 蜡烛图为绿色
      //RSI = 100   - 蜡烛图为蓝色
      //0<RSI<100   - 蜡烛图颜色在绿和蓝之间 
      buffer_color_line[i]=getPlotColor(buffer_RSI[i],0,100);

     }
   return(rates_total-1); //返回已经计算的柱形的数量,
                         //由于最后一个柱形要重算,减1
  }
//+------------------------------------------------------------------+

就是这个样子:

RSI_gradient

以此为例设置其它颜色。尝试用另一种指标替换 RSI。

实践练习始终都很重要。

绘图风格:传统型与多色彩型

您可以为现有的指标上色,需要执行下述步骤:将绘制风格改为多色彩,添加缓冲区,为其分配指标缓冲区并指定上色详情。

下面是传统绘制风格与相应的多色彩(已上色)绘制风格对比表:

之前
之后
DRAW_LINEDRAW_COLOR_LINE
DRAW_SECTIONDRAW_COLOR_SECTION
DRAW_HISTOGRAMDRAW_COLOR_HISTOGRAM
DRAW_HISTOGRAM2DRAW_COLOR_HISTOGRAM2
DRAW_ARROWDRAW_COLOR_ARROW
DRAW_ZIGZAGDRAW_COLOR_ZIGZAG (示例)
DRAW_CANDLESDRAW_COLOR_CANDLES

此为经过修改的 RSI 代码,根据其自身值上色。

所有修改均有注释。

//+------------------------------------------------------------------+
//|                                                          RSI.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright   "2009, MetaQuotes Software Corp."
#property link        "http://www.mql5.com"
#property description "Relative Strength Index"
//--- 指标设置
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 30
#property indicator_level2 70
/////////////////////////////////////////////////////////////////////
#property indicator_buffers 4 //缓存的数量增加1
#property indicator_width1 5  //线宽设置为4像素
/////////////////////////////////////////////////////////////////////
#property indicator_plots   1
/////////////////////////////////////////////////////////////////////
//绘图风格已经从 DRAW_LINE 变为 DRAW_COLOR_LINE
#property indicator_type1   DRAW_COLOR_LINE
/////////////////////////////////////////////////////////////////////
#property indicator_color1  DodgerBlue
//--- 输入参数
input int InpPeriodRSI=14; // 周期
//--- 指标缓存
double    ExtRSIBuffer[];
double    ExtPosBuffer[];
double    ExtNegBuffer[];
//--- 全局变量
int       ExtPeriodRSI;

//////////////////////////////////////////////////////////////////////
double buffer_color[]; //为颜色索引声明一个数组

//添加两个函数
//+------------------------------------------------------------------+
//|    设置一个绘图图形的颜色                                           |
//+------------------------------------------------------------------+
/*
*      本函数设置一个绘图图形的颜色 
*      从绿色到蓝色的50种颜色。
*       绘图颜色的索引传给函数。
*/
void setPlotColor(int plot)
  {
   PlotIndexSetInteger(plot,PLOT_COLOR_INDEXES,50); //设置颜色的数量

                                                    //在循环中确定颜色
   for(int i=0;i<=24;i++)
     {
      PlotIndexSetInteger(plot,PLOT_LINE_COLOR,i,StringToColor("\"0,175,"+IntegerToString(i*7)+"\""));
     }
   for(int i=0;i<=24;i++)
     {
      PlotIndexSetInteger(plot,PLOT_LINE_COLOR,i+25,StringToColor("\"0,"+IntegerToString(175-i*7)+",175\""));
     }
  }
//+------------------------------------------------------------------+
//|  获取颜色索引                                                      |
//+------------------------------------------------------------------+
/*
*       本函数返回颜色索引
*       第一个参数是当前指标的值
*       第二个参数是指标的最小值
*       第三个参数是指标的最大值
*/
int getPlotColor(double current,double min,double max)
  {
   return((int)NormalizeDouble((50/(max-min))*current,0));
  }
//////////////////////////////////////////////////////////////////////


//+------------------------------------------------------------------+
//| 自定义指标初始化函数                                                |
//+------------------------------------------------------------------+
void OnInit()
  {
//--- 检查输入
   if(InpPeriodRSI<1)
     {
      ExtPeriodRSI=12;
      Print("Incorrect value for input variable InpPeriodRSI =",InpPeriodRSI,
            "Indicator will use value =",ExtPeriodRSI,"for calculations.");
     }
   else ExtPeriodRSI=InpPeriodRSI;
//--- 指标缓存映射
   SetIndexBuffer(0,ExtRSIBuffer,INDICATOR_DATA);
   
/////////////////////////////////////////////////////////////////////
//为颜色索引缓存分配数组
        SetIndexBuffer(1,buffer_color,INDICATOR_COLOR_INDEX);
//缓存的顺序变了!
        SetIndexBuffer(2,ExtPosBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,ExtNegBuffer,INDICATOR_CALCULATIONS);
//设置颜色
   setPlotColor(0);
/////////////////////////////////////////////////////////////////////

//--- 设置精度
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//--- 设置绘图开始的第一个柱形的索引位置
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtPeriodRSI);
//--- 数据窗口名称和指标子窗口标签
   IndicatorSetString(INDICATOR_SHORTNAME,"RSI("+string(ExtPeriodRSI)+")");
//--- 初始化结束
  }
//+------------------------------------------------------------------+
//| 相对强弱指数                                                       |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   int    i;
   double diff;
//--- 检查利率计算
   if(rates_total<=ExtPeriodRSI)
      return(0);
//--- 初步计算
   int pos=prev_calculated-1;
   if(pos<=ExtPeriodRSI)
     {
      //--- 指标的第一个RSIPeriod值不计算
      ExtRSIBuffer[0]=0.0;
      ExtPosBuffer[0]=0.0;
      ExtNegBuffer[0]=0.0;
      double SumP=0.0;
      double SumN=0.0;
      for(i=1;i<=ExtPeriodRSI;i++)
        {
         ExtRSIBuffer[i]=0.0;
         ExtPosBuffer[i]=0.0;
         ExtNegBuffer[i]=0.0;
         diff=price[i]-price[i-1];
         SumP+=(diff>0?diff:0);
         SumN+=(diff<0?-diff:0);
        }
      //--- 计算首个可视值
      ExtPosBuffer[ExtPeriodRSI]=SumP/ExtPeriodRSI;
      ExtNegBuffer[ExtPeriodRSI]=SumN/ExtPeriodRSI;
      ExtRSIBuffer[ExtPeriodRSI]=100.0-(100.0/(1.0+ExtPosBuffer[ExtPeriodRSI]/ExtNegBuffer[ExtPeriodRSI]));
      //--- 为主要计算过程准备位置值
      pos=ExtPeriodRSI+1;
     }
//--- 主循环
   for(i=pos;i<rates_total;i++)
     {
      diff=price[i]-price[i-1];
      ExtPosBuffer[i]=(ExtPosBuffer[i-1]*(ExtPeriodRSI-1)+(diff>0.0?diff:0.0))/ExtPeriodRSI;
      ExtNegBuffer[i]=(ExtNegBuffer[i-1]*(ExtPeriodRSI-1)+(diff<0.0?-diff:0.0))/ExtPeriodRSI;
      ExtRSIBuffer[i]=100.0-100.0/(1+ExtPosBuffer[i]/ExtNegBuffer[i]);
/////////////////////////////////////////////////////////////////////
//绘制
                buffer_color[i] = getPlotColor(ExtRSIBuffer[i],0,100);
/////////////////////////////////////////////////////////////////////
     }
//--- OnCalculate函数结束。返回新的prev_calculated。
   return(rates_total);
  }
//+------------------------------------------------------------------+

这就是了,您可以对比烛形图与 RSI 的颜色。

RSI 颜色

如何从 EA 交易/指标/脚本获取指标的颜色值

经常会因某 EA 交易的自动化交易或某些其它目的,需要获取某行的颜色。

实现很简单,我们来看一个脚本。

//+------------------------------------------------------------------+
//|                                                         test.mq5 |
//|                                                             ProF |
//|                                                          http:// |
//+------------------------------------------------------------------+
#property copyright "ProF"
#property link      "http://"
#property version   "1.00"
//+------------------------------------------------------------------+
//| 脚本程序开始函数                                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
        int handle = 0; //指标句柄
        double tmp[1];  //颜色索引缓存的临时数组
        //获取我们修改过的RSI指标的句柄
        handle = iCustom(_Symbol,_Period,"Examples\\RSI",6);
        
        //记住,值存储在我们修改过的RSI的缓存1中
        //颜色索引存储在缓存0中
        //从RSI指标的缓存“1”中复制数据
        CopyBuffer(handle,1,0,1,tmp);
        
        //报警显示由RSI返回的最近的颜色索引
        Alert(tmp[0]); //例如,如果返回0,意味着那个RSI
        //用绿色绘制,并且它当前的水平接近0。
  }
//+-----------------------------------------------------------------+
注意:我们可以获取颜色索引的值,而不是颜色本身!

您必须掌握颜色索引与颜色值之间的对应关系。此外,您还必须清楚颜色索引的缓冲区。

想找到它,您需要懂得颜色索引设置的标准,或是凭经验利用此脚本或其它方法来确定。

总结

我们一起学习了下述 MQL5 绘制风格:DRAW_COLOR_LINE, DRAW_COLOR_CANDLES。我们完成了烛形图的上色,并学会了如何为 RSI 指标上色 (DRAW_LINE -> DRAW_COLOR_LINE)。此外,我们还学会了如何获取颜色缓冲区索引的值。

MQL5 语言拥有大量的绘制风格,没有做不到,只有想不到。使用彩色线条可以更好地观察市场。

好好利用新机遇,更舒适地进行交易。

全部回复

0/140

量化课程

    移动端课程