外建指标的数据缓冲
外建指标的主要底层机制,是把指标数组的数据,送往终端窗口的缓冲,用于画出指标线。
缓冲是内存区,保存着指标数据。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个柱的最小值和最大值的平均值。 |
//--------------------------------------------------------------------如果把外建指标 averagevalue.mq4 “粘”入平移指标MA上,会看到3条指标线。若这2个指标的周期相同,MA指标线会与外建指标的一条线合并(重合),只看到2条线(见图121)。
// 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()
}
//--------------------------------------------------------------------
图. 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()。