MQL4自定义指标开发核心特性详解
从属性定义到iCustom调用的完整实战指南
自定义指标的基本定位与头属性选择
在MetaTrader 4交易系统中,自定义指标是用MQL4编写、用于根据历史与实时行情计算并绘制技术分析数据的程序。与脚本和EA不同,指标不能下单,但可随行情自动重算并可视化。创建一个能被平台正确识别和加载的指标,必须在mq4文件头部通过#property指令做二选一的定义:指定指标绘制在主图表窗口还是独立窗口。若选择主图叠加,使用#property indicator_chart_window;若在副图显示,则用#property indicator_separate_window。这个选择决定了指标与K线的视觉层级关系,也影响后续DRAW_HISTOGRAM等模式的行为差异。
- indicator_chart_window:指标线直接画在价格K线上,如Ichimoku
- indicator_separate_window:指标在下方独立子窗口,如加速/减速震荡指标
- 二者必须且只能选其一,否则编译或加载异常
数值范围与缓冲区数量的声明
平台需要知道指标数值的合理边界以及内部用于计算的数组个数。通过#property indicator_minimum和#property indicator_maximum可设定Y轴显示区间,例如RSI必须设为0和100,避免图形拉伸失真。缓冲区数量则用#property indicator_buffers N声明,N为1到8之间的整数,代表你向系统注册的指标数组(buffer)数目。这些数组必须是double类型的一维数组,且通过SetIndexBuffer绑定。若计算时需要更多临时数组(不直接绘制),可像Accelerator例子那样在init中调用IndicatorBuffers(5)申请超过头属性声明的额外空间,系统会统一管理内存。
#property indicator_minimum Min_Value #property indicator_maximum Max_Value #property indicator_buffers N
指标线颜色与绘制风格控制
每一条指标线(buffer)的颜色通过#property indicator_colorN设置,N对应buffer索引。绘制风格由SetIndexStyle在init中设定,常用模式包括DRAW_LINE直线、DRAW_HISTOGRAM柱状、DRAW_NONE不绘制。以Ichimoku为例,转折线、基准线用DRAW_LINE;云层使用偶数buffer与奇数buffer配对画柱形,并另设线型buffer画边框。Accelerator中ExtBuffer0设DRAW_NONE仅作数据传递,ExtBuffer1/2用双色柱形表达涨跌。SetIndexShift可平移线条,如Ichimoku的先行带向前位移Kijun根K线。
#property indicator_color1 Silver #property indicator_color2 Red #property indicator_colorN <SomeColor>
- DRAW_LINE:数组点间连直线
- DRAW_HISTOGRAM:主窗画于两buffer间,子窗画于0与buffer间
- DRAW_NONE:计算用不显示,配合NULL标签隐藏数据窗口项
Ichimoku指标实例拆解
Ichimoku Kinko Hyo是主图指标,声明7个buffer。init中先设定各线风格与Shift,SpanA/B用DRAW_HISTOGRAM配合Dot线框。SetIndexDrawBegin控制从哪个元素开始画,避免未成熟数据干扰。start函数用IndicatorCounted获取已计算柱数,仅补算新增部分:Tenkan Sen取前9根高低中点,Kijun取26根,云层为二者均值位移。Chinkou为收盘价向后位移。该结构展示了多buffer协同与历史数据高效重算的经典写法。
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Red
#property indicator_color2 Blue
#property indicator_color3 SandyBrown
#property indicator_color4 Thistle
#property indicator_color5 Lime
#property indicator_color6 SandyBrown
#property indicator_color7 Thistle
extern int Tenkan=9;
extern int Kijun=26;
extern int Senkou=52;
double Tenkan_Buffer[];
double Kijun_Buffer[];
double SpanA_Buffer[];
double SpanB_Buffer[];
double Chinkou_Buffer[];
double SpanA2_Buffer[];
double SpanB2_Buffer[];
int a_begin;
int init(){
SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(0,Tenkan_Buffer); SetIndexDrawBegin(0,Tenkan-1); SetIndexLabel(0,"Tenkan Sen");
SetIndexStyle(1,DRAW_LINE); SetIndexBuffer(1,Kijun_Buffer); SetIndexDrawBegin(1,Kijun-1); SetIndexLabel(1,"Kijun Sen");
a_begin=Kijun; if(a_begin<Tenkan) a_begin=Tenkan;
SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_DOT); SetIndexBuffer(2,SpanA_Buffer); SetIndexDrawBegin(2,Kijun+a_begin-1); SetIndexShift(2,Kijun); SetIndexLabel(2,NULL);
SetIndexStyle(5,DRAW_LINE,STYLE_DOT); SetIndexBuffer(5,SpanA2_Buffer); SetIndexDrawBegin(5,Kijun+a_begin-1); SetIndexShift(5,Kijun); SetIndexLabel(5,"Senkou Span A");
SetIndexStyle(3,DRAW_HISTOGRAM,STYLE_DOT); SetIndexBuffer(3,SpanB_Buffer); SetIndexDrawBegin(3,Kijun+Senkou-1); SetIndexShift(3,Kijun); SetIndexLabel(3,NULL);
SetIndexStyle(6,DRAW_LINE,STYLE_DOT); SetIndexBuffer(6,SpanB2_Buffer); SetIndexDrawBegin(6,Kijun+Senkou-1); SetIndexShift(6,Kijun); SetIndexLabel(6,"Senkou Span B");
SetIndexStyle(4,DRAW_LINE); SetIndexBuffer(4,Chinkou_Buffer); SetIndexShift(4,-Kijun); SetIndexLabel(4,"Chinkou Span");
return(0);
}
Accelerator震荡指标与额外缓冲区
加速/减速震荡指标在独立窗口,头属性仅声明3个buffer,但init调用IndicatorBuffers(5)申请5个,其中ExtBuffer3/4作中间计算。SetIndexDigits(Digits+2)提高精度,因差值小数位更多。信号线为中位价双均线差再取均线,故前38根置空。柱形图用ExtBuffer1/2分装涨跌色,ExtBuffer0隐藏。此例说明:绘制需要的buffer可在头声明,纯计算buffer用IndicatorBuffers扩展,且DRAW_NONE可隐藏主线但仍供EA读取。
#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Black
#property indicator_color2 Green
#property indicator_color3 Red
double ExtBuffer0[]; double ExtBuffer1[]; double ExtBuffer2[]; double ExtBuffer3[]; double ExtBuffer4[];
int init(){
IndicatorBuffers(5);
SetIndexStyle(0,DRAW_NONE); SetIndexStyle(1,DRAW_HISTOGRAM); SetIndexStyle(2,DRAW_HISTOGRAM);
IndicatorDigits(Digits+2);
SetIndexDrawBegin(0,38); SetIndexDrawBegin(1,38); SetIndexDrawBegin(2,38);
SetIndexBuffer(0,ExtBuffer0); SetIndexBuffer(1,ExtBuffer1); SetIndexBuffer(2,ExtBuffer2);
SetIndexBuffer(3,ExtBuffer3); SetIndexBuffer(4,ExtBuffer4);
IndicatorShortName("AC"); SetIndexLabel(1,NULL); SetIndexLabel(2,NULL);
return(0);
}
IndicatorCounted与经济化计算
IndicatorCounted()返回历史已成功计算过的柱数。在start开头获取该值,可从Bars-counted_bars位置起只算新数据,大幅降低CPU负载。当指标重初始化或历史数据大更新时,此值归零重算。注意若counted_bars>0,Accelerator例子将其减1以重算最后一根,防止报价跳动遗漏。错误使用会导致图形断层或重复计算卡顿。
在EA中通过iCustom调用指标
EA或脚本可用iCustom函数读取任意指标值。前两个参数NULL和0表示当前图表当前周期;第三参数为指标文件名(不含.mq4);其后是extern输入参数依次传入;倒数第二为buffer索引;最后为偏移shift(0为最新)。若指标无参,可省略参数直接用初始值。例如读取Accelerator最新值:iCustom(NULL,0,"Accelerator",0,0)。调用Ichimoku带参:iCustom(NULL,0,"Ichimoku",9,26,52,0,shift)。不传参版本:iCustom(NULL,0,"Ichimoku",0,shift)使用默认9,26,52。多参数EA务必显式传参,勿依赖默认。
double current_AC = iCustom( NULL, 0, "Accelerator", 0, 0 ); iCustom( NULL, 0, "Ichimoku", 9, 26, 52, 0, shift ); iCustom( NULL, 0, "Ichimoku", 0, shift );