外建指标的数据缓冲
外建指标的主要底层机制,是把指标数组的数据,送往终端窗口的缓冲,用于画出指标线。
缓冲是内存区,保存着指标数据。MQL4 规定,一个指标最多可画出8条指标线。一个指标数组,存储一条指标线的数据,与一个缓冲关联。8个缓冲的索引从0开始,最后一个为 7。图115表示外建指标数据,如何通过缓冲,传入主图画出指标线。
图. 115. 把指标数据从指标数组通过缓冲传入主图
第一个示例
先看一个简单的外建指标。它有2条线,一条显示最高价,另一条显示最低价。
示例一:简单的外建指标 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是以上外建指标运行的结果
图. 120. userindicator.mq4在主图中画出的指标的2条线
第二个示例
示例二:简单的外建指标 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)。
图. 121.内建指标与外建指标线的重合(红线)
内建指标的选项
在副图画出指标线
#property indicator_separate_window // 这条指令确定指标线在副图画出
历史数据的数量限制
过多的历史数据,一是没用,二是碍事(造成图形过大)。用以下代码,限制其数量。
i=Bars-Counted_bars-1; // 第一个柱的索引 if (i>History-1) // 若有过多的柱, i=History-1; // 则限定为预定数目
示例:简单的外建指标 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 运行的结果。
图. 122. 在副图画出指标线。
外建指标,仅画出最新的50个柱。若要用更多历史数据,可在外建指标设置窗口更改。
图123是以直方图表示的指标线。为此,可对 separatewindow.mq4 做相应修改:
SetIndexStyle (0,DRAW_HISTOGRAM);// 指标线的特点
图. 123. 在副图中画出的指标线直方图
指标线的垂直方向与水平方向的变换
示例:外建指标 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。
图. 124. 红线向左 5 个柱,虚线与红线间隔30点
外建指标的限制
以下函数只能在指标中使用,不能用于“操盘手”和脚本:IndicatorBuffers(),IndicatorCounted (), IndicatorDigits(), IndicatorShortName(), SetIndexArrow(),SetIndexBuffer(), SetIndexDrawBegin(), SetIndexEmptyValue(), SetIndexLabel(), SetIndexShift(),SetIndexStyle(), SetLevelStyle(), SetLevelValue()。以下交易函数不能用于指标: OrderSend(),OrderClose(), OrderCloseBy(), OrderDelete() and OrderModify()。