《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标

时间:2022-09-09 09:04:59

外建指标的数据缓冲

外建指标的主要底层机制,是把指标数组的数据,送往终端窗口的缓冲,用于画出指标线。

缓冲是内存区,保存着指标数据。

MQL4 规定,一个指标最多可画出8条指标线。一个指标数组,存储一条指标线的数据,与一个缓冲关联。8个缓冲的索引从0开始,最后一个为 7。图115表示外建指标数据,如何通过缓冲,传入主图画出指标线。

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标
图. 115. 把指标数据从指标数组通过缓冲传入主图

第一个示例

先看一个简单的外建指标。它有2条线,一条显示最高价,另一条显示最低价。

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标 示例一:简单的外建指标 userindicator.mq4
//--------------------------------------------------------------------
// userindicator.mq4 
// 本程序仅用于教学
//--------------------------------------------------------------------
#property indicator_chart_window    // 在主图画出指标
#property indicator_buffers 2       // 缓冲的数目
#property indicator_color1 Blue     // 第1条指标线的颜色
#property indicator_color2 Red      // 第2条指标线的颜色
 
double Buf_0[],Buf_1[];             // 以数组当作指标缓冲
//--------------------------------------------------------------------
int init()                          // 特别函数 init()
  {
   SetIndexBuffer(0,Buf_0);         // 第一个缓冲赋值
   SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,2); // 第一条指标线的特点
   SetIndexBuffer(1,Buf_1);         // 第二个缓冲赋值
   SetIndexStyle (1,DRAW_LINE,STYLE_DOT,1);// 第二条指标线的特点
   return;                          // 退出 init()
  }
//--------------------------------------------------------------------
int start()                         // 特别函数 start()
  {
   int i,                           // 柱子 Bar 的索引
       Counted_bars;                // 当前柱子的数目
//--------------------------------------------------------------------
   Counted_bars=IndicatorCounted(); // 历史柱子的数目
   i=Bars-Counted_bars-1;           // 第一个历史柱的索引
   while(i>=0)                      // 历史柱的循环
     {
      Buf_0[i]=High[i];             // 第一个缓冲第 i 个柱的数据值
      Buf_1[i]=Low[i];              // 第二个缓冲第 i 个柱的数据值
      i--;                          // 计算下一个柱
     }
//--------------------------------------------------------------------
   return;                          // 退出 start()
  }
//--------------------------------------------------------------------

图120是以上外建指标运行的结果

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标
图. 120. userindicator.mq4在主图中画出的指标的2条线

第二个示例

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标 示例二:简单的外建指标 averagevalue.mq4. 指标线的数据,是N个柱的最小值和最大值的平均值。
//--------------------------------------------------------------------
// separatewindow.mq4 
// 仅用于教学
//--------------------------------------------------------------------
#property indicator_separate_window // 在副图中画线
#property indicator_buffers 1       // 缓冲数目
#property indicator_color1 Blue     // 第一条线的颜色
#property indicator_color2 Red      // 第二条线的颜色
 
extern int History  =50;            // 历史柱的总数
extern int Aver_Bars=5;             // 取"平均"的柱的数目
 
double Buf_0[];                     // 指标数组
//--------------------------------------------------------------------
int init()                          // 特别函数 init()
  {
   SetIndexBuffer(0,Buf_0);         // 把指标数组的值赋予缓冲
   SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,2);// 指标线的特点
   return;                          // 退出 init()
  }
//--------------------------------------------------------------------
int start()                         // 特别函数 start()
  {
   int i,                           // 柱的索引
   n,                               // 正常参数
   Counted_bars;                    // 历史柱的数目
   double
   Sum_H,                           // 计算周期内最高价的汇总
   Sum_L;                           // 计算周期内最低价的汇总
//--------------------------------------------------------------------
   Counted_bars=IndicatorCounted(); // 历史柱的数目
   i=Bars-Counted_bars-1;           // 历史柱的第一个的索引
   if (i>History-1)                 // 若有太多的柱,计算指定的范围
      i=History-1;                  
   while(i>=0)                      // 循环处理历史柱
     {
      Sum_H=0;                      // 清空
      Sum_L=0;                      // 清空
      for(n=i;n<=i+Aver_Bars-1;n++) // 汇总过程的循环
        {
         Sum_H=Sum_H + High[n];     // 累计最高价
         Sum_L=Sum_L + Low[n];      // 累计最低价
        }
      Buf_0[i]=(Sum_H-Sum_L)/Aver_Bars;// 在第一个缓冲第 i 柱的值
      i--;                          // 下一个计算对象的索引
     }
//--------------------------------------------------------------------
   return;                          // 退出 start()
  }
//--------------------------------------------------------------------
如果把外建指标 averagevalue.mq4 “粘”入平移指标MA上,会看到3条指标线。若这2个指标的周期相同,MA指标线会与外建指标的一条线合并(重合),只看到2条线(见图121)。

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标
图. 121.内建指标与外建指标线的重合(红线)

内建指标的选项

在副图画出指标线

#property indicator_separate_window // 这条指令确定指标线在副图画出

历史数据的数量限制

过多的历史数据,一是没用,二是碍事(造成图形过大)。用以下代码,限制其数量。

   i=Bars-Counted_bars-1;           // 第一个柱的索引
   if (i>History-1)                 // 若有过多的柱,
      i=History-1;                  // 则限定为预定数目
《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标 示例:简单的外建指标 separatewindow.mq4. 指标线画在副图。
//--------------------------------------------------------------------
// separatewindow.mq4 
// 仅用于教学
//--------------------------------------------------------------------
#property indicator_separate_window // 在副图画线
#property indicator_buffers 1       // 缓冲数目
#property indicator_color1 Blue     // 第1根线的颜色
#property indicator_color2 Red      // 第2根线的颜色
 
extern int History  =50;            // 柱的历史数据的数量
extern int Aver_Bars=5;             // 柱的总数
 
double Buf_0[];                     // 指标数组
//--------------------------------------------------------------------
int init()                          // 特别函数 init()
  {
   SetIndexBuffer(0,Buf_0);         // 数组与缓冲建立关联
   SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,2);// 线的特点
   return;                          // 退出 init()
  }
//--------------------------------------------------------------------
int start()                         // 特别函数 start()
  {
   int i,                           // 柱的索引
   n,                               // 一般变量
   Counted_bars;                    // 要计算的柱的量
   double
   Sum_H,                           // 周期内最高价的汇总
   Sum_L;                           // 周期内最低价的汇总
//--------------------------------------------------------------------
   Counted_bars=IndicatorCounted(); // 要计算的柱的量
   i=Bars-Counted_bars-1;           // 第1柱的索引
   if (i>History-1)                 // 柱太多了,
      i=History-1;                  // 于是,以预定数目为准
   while(i>=0)                      // 逐一计算每个柱
     {
      Sum_H=0;                      // 清零
      Sum_L=0;                      // 清零
      for(n=i;n<=i+Aver_Bars-1;n++) // 汇总
        {
         Sum_H=Sum_H + High[n];     // 累计最高价
         Sum_L=Sum_L + Low[n];      // 累计最低价
        }
      Buf_0[i]=(Sum_H-Sum_L)/Aver_Bars;// 第1个缓冲的第 i 个柱的值
      i--;                          // 下个柱的索引
     }
//--------------------------------------------------------------------
   return;                          // 退出 start()
  }
//--------------------------------------------------------------------

图122是指标separatewindow.mq4 运行的结果。

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标
图. 122. 在副图画出指标线。

外建指标,仅画出最新的50个柱。若要用更多历史数据,可在外建指标设置窗口更改。

图123是以直方图表示的指标线。为此,可对 separatewindow.mq4 做相应修改:

   
   SetIndexStyle (0,DRAW_HISTOGRAM);// 指标线的特点

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标
图. 123. 在副图中画出的指标线直方图

指标线的垂直方向与水平方向的变换

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标 示例:外建指标 displacement.mq4 。指标线的垂直/水平变换。
//--------------------------------------------------------------------
// displacement.mq4 
// 仅用于教学
//--------------------------------------------------------------------
#property indicator_chart_window       // 在主图中画线
#property indicator_buffers 3          // 缓冲数目
#property indicator_color1 Red         // 第1条线的颜色
#property indicator_color2 Blue        // 第2条线的颜色
#property indicator_color3 Green       // 第3条线的颜色
 
extern int History  =500;              // 历史柱的数量
extern int Aver_Bars=5;                // 柱的总数
extern int Left_Right= 5;              // 柱的水平轴
extern int Up_Down  =25;               // 点位的垂直轴
 
double Line_0[],Line_1[],Line_2[];     // 缓冲
//--------------------------------------------------------------------
int init()                             // 特别函数 init()
  {
//--------------------------------------------------------------------
   SetIndexBuffer(0,Line_0);           // 数组与缓冲建立关联
   SetIndexStyle (0,DRAW_LINE,STYLE_SOLID,2);// 线的特点
//--------------------------------------------------------------------
   SetIndexBuffer(1,Line_1);           // 第1数组与第1缓冲建立关联
   SetIndexStyle (1,DRAW_LINE,STYLE_DOT,1);// 线的特点
//--------------------------------------------------------------------
   SetIndexBuffer(2,Line_2);           // 第2数组与第2缓冲建立关联
   SetIndexStyle (2,DRAW_LINE,STYLE_DOT,1);// 线的特点
//--------------------------------------------------------------------
   return;                             // 退出 init()
  }
//--------------------------------------------------------------------
int start()                            // 特别函数 start()
  {
   int i,                              // 柱的索引
       n,                              // 普通变量,表示索引值
       k,                              // 指标数组索引
       Counted_bars;                   // 要计算的柱的数目
       double
       Sum;                            // 周期内最高价与最低价的汇总
//--------------------------------------------------------------------
   Counted_bars=IndicatorCounted();    // 要计算的柱的数目
   i=Bars-Counted_bars-1;              // 第1柱的索引
   if (i>History-1)                    // 若柱太多,
      i=History-1;                     // 则以预定值为准
 
   while(i>=0)                         // 逐个柱进行处理
     {
      Sum=0;                           // 清零
      for(n=i;n<=i+Aver_Bars-1;n++)    // 汇总
         Sum=Sum + High[n]+Low[n];     // 累计
      k=i+Left_Right;                  // 取得索引
      Line_0[k]= Sum/2/Aver_Bars;      // 第1个缓冲的第k个柱的数据值
      Line_1[k]= Line_0[k]+Up_Down*Point;// 第1个缓冲的值
      Line_2[k]= Line_0[k]-Up_Down*Point;// 第2个缓冲的值
 
      i--;                             // 下一个柱的索引
     }
//--------------------------------------------------------------------
   return;                             // 退出 start()
  }
//--------------------------------------------------------------------

指标运行结果见图124。

《MQL4实用编程》读书笔记(8) - 简单编程:编写外建指标
图. 124. 红线向左 5 个柱,虚线与红线间隔30点

外建指标的限制

以下函数只能在指标中使用,不能用于“操盘手”和脚本:IndicatorBuffers(),IndicatorCounted (), IndicatorDigits(), IndicatorShortName(), SetIndexArrow(),SetIndexBuffer(), SetIndexDrawBegin(), SetIndexEmptyValue(), SetIndexLabel(), SetIndexShift(),SetIndexStyle(), SetLevelStyle(), SetLevelValue()。

以下交易函数不能用于指标: OrderSend(),OrderClose(), OrderCloseBy(), OrderDelete() and OrderModify()。