2017/4/29
MT5入门到精通之十一指标高级用法
一.跨时间周期指标(注意是小周期的指标显示出大周期的指标,也就是说tf参数要比当前时间周期大)
1.效果
2.设置
image.png image.png
3.实现
//+------------------------------------------------------------------+
//| spanTimeIndicator.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 2
//--- plot fastLine
#property indicator_label1 "fastLine"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot slowLine
#property indicator_label2 "slowLine"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrYellow
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- input parameters
input int fastMa=5;
input int slowMa=10;
input ENUM_TIMEFRAMES tf=PERIOD_H2;
//不同周期k线数基本不同,很容易数组越界
input int showKlineNum=50; //显示k线个数(设置太多,有时候会加载比较慢)
//--- indicator buffers
double fastLineBuffer[];
double slowLineBuffer[];
//1.1句柄
int fastMa_h;
int slowMa_h;
//int custom_h;
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,fastLineBuffer,INDICATOR_DATA);
SetIndexBuffer(1,slowLineBuffer,INDICATOR_DATA);
//1.2.句柄初始化
fastMa_h=iMA(NULL,tf,fastMa,0,0,0);
slowMa_h=iMA(NULL,tf,slowMa,0,0,0);
//1.2.1自定义指标
//custom_h=iCustom(NULL,tf,"Examples\\custom");
//---
//1.6 数组序列号
ArraySetAsSeries(fastLineBuffer,true);
ArraySetAsSeries(slowLineBuffer,true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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[])
{
//1.3创建赋值数组
double fast[];
double slow[];
datetime tf_time[];
//1.6.1数组序列号
ArraySetAsSeries(fast,true);
ArraySetAsSeries(slow,true);
ArraySetAsSeries(tf_time,true);
setSystemReturnArrayAsSeries(time,open,high,low,close,tick_volume,volume,spread);
CopyBuffer(fastMa_h,0,0,rates_total,fast);
CopyBuffer(slowMa_h,0,0,rates_total,slow);
CopyTime(NULL,tf,0,rates_total,tf_time);
//1.4 赋值缓存数组
int limit=(prev_calculated>0) ?(rates_total-prev_calculated+1) : rates_total;
//1.5数组越界保护
limit=(limit>showKlineNum)? showKlineNum : limit;
int tf_i=0;
for(int i=0;i<limit;i++)
{
//默认小周期的时间比大周期的时间大,不需要特殊处理,如果不是tf_i++;
if(time[i]<tf_time[tf_i])
{
tf_i++;
}
fastLineBuffer[i]=fast[tf_i];
slowLineBuffer[i]=slow[tf_i];
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
void setSystemReturnArrayAsSeries(
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[])
{
ArraySetAsSeries(time,true);
ArraySetAsSeries(open,true);
ArraySetAsSeries(high,true);
ArraySetAsSeries(low,true);
ArraySetAsSeries(close,true);
ArraySetAsSeries(tick_volume,true);
ArraySetAsSeries(volume,true);
ArraySetAsSeries(spread,true);
}
//+------------------------------------------------------------------+
二将任意价格的数据做出均线指标显示
eg:(CLOSE-LLV(LOW,10))/(HHV(HIGH,10)-LLV(LOW,10))值的SMA 的8日均线
1.效果
2.实现
//+------------------------------------------------------------------+
//| baseAnyPriceMaIndicator.mq5 |
//| Copyright 2017, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_separate_window
//1.7一定要设置成2,不然就无法使用计算数据的数组anyPriceBuffer
#property indicator_buffers 2
#property indicator_plots 1
//--- plot maLine
#property indicator_label1 "maLine"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//不同周期k线数基本不同,很容易数组越界
input int showKlineNum=1000; //显示k线个数(设置太多,有时候会加载比较慢)
//--- indicator buffers
//1.要画的线
double maLineBuffer[];
//1.1不需要画线
double anyPriceBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,maLineBuffer,INDICATOR_DATA);
//1.2 设置对应的类型(计算用)
SetIndexBuffer(1,anyPriceBuffer,INDICATOR_CALCULATIONS);
//1.3 序列化
ArraySetAsSeries(maLineBuffer,true);
ArraySetAsSeries(anyPriceBuffer,true);
//1.4 指标的名称
IndicatorSetString(INDICATOR_SHORTNAME,"(CLOSE-LLV(LOW,10))/(HHV(HIGH,10)-LLV(LOW,10))值的SMA均线");
//1.5 设置指标默认值
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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[])
{
setSystemReturnArrayAsSeries(time,open,high,low,close,tick_volume,volume,spread);
//1.6 赋值缓存数组
int limit=(prev_calculated>0) ?(rates_total-prev_calculated+1) : rates_total;
//1.7数组越界保护
limit=(limit>showKlineNum)? showKlineNum : limit;
//1.8
int ragneNum=10;
if(limit < ragneNum) return (0);
for(int i=0;i<limit;i++)
{
double temp=HHV(Symbol(),0,ragneNum,i)-LLV(Symbol(),0,ragneNum,i);
if(temp!=0)
{
anyPriceBuffer[i]=(close[i]-LLV(Symbol(),0,ragneNum,i))/temp;
}
}
for(int i=0;i<limit;i++)
{
maLineBuffer[i]=iMAOnArrayMql4(anyPriceBuffer,showKlineNum,8,0,MODE_SMA,i);
}
return(rates_total);
}
//+------------------------------------------------------------------+
void setSystemReturnArrayAsSeries(
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[])
{
ArraySetAsSeries(time,true);
ArraySetAsSeries(open,true);
ArraySetAsSeries(high,true);
ArraySetAsSeries(low,true);
ArraySetAsSeries(close,true);
ArraySetAsSeries(tick_volume,true);
ArraySetAsSeries(volume,true);
ArraySetAsSeries(spread,true);
}
//+------------------------------------------------------------------+
//2.start_pos 到count+start_pos 之间最低价
double LLV(string symbol,ENUM_TIMEFRAMES tf,int count,int start_pos)
{
double low[];
ArraySetAsSeries(low,true);
CopyLow(symbol,tf,start_pos,count,low);
//2.1 设置一个比较大的默认值
double min=9999999;
for(int i=0;i<ArraySize(low);i++)
{
if(low[i]<min)
{
min=low[i];
}
}
return(min);
}
//3.start_pos 到count+start_pos 之间最高价
double HHV(string symbol,ENUM_TIMEFRAMES tf,int count,int start_pos)
{
double high[];
ArraySetAsSeries(high,true);
CopyHigh(symbol,tf,start_pos,count,high);
//3.1 设置一个比较小的默认值
double max=0;
for(int i=0;i<ArraySize(high);i++)
{
if(high[i]>max)
{
max=high[i];
}
}
return(max);
}
//+------------------------------------------------------------------+
double iMAOnArrayMql4(double &sourceArray[],int total,int iMAPeriod,int ma_shift,ENUM_MA_METHOD ma_method,int Shift)
{
double buf[];
if(total>0 && total<=iMAPeriod) return(0);
if(total==0) total=ArraySize(sourceArray);
if(ArrayResize(buf,total)<0) return(0);
switch(ma_method)
{
case MODE_SMA :
{
double sum=0;
int i,pos=total-1;
for(i=1;i<iMAPeriod;i++,pos--)
sum+=sourceArray[pos];
while(pos>=0)
{
sum+=sourceArray[pos];
buf[pos]=sum/iMAPeriod;
sum-=sourceArray[pos+iMAPeriod-1];
pos--;
}
return(buf[Shift+ma_shift]);
}
case MODE_EMA :
{
double pr=2.0/(iMAPeriod+1);
int pos=total-2;
while(pos>=0)
{
if(pos==total-2) buf[pos+1]=sourceArray[pos+1];
buf[pos]=sourceArray[pos]*pr+buf[pos+1]*(1-pr);
pos--;
}
return(buf[Shift+ma_shift]);
}
case MODE_SMMA :
{
double sum=0;
int i,k,pos;
pos=total-iMAPeriod;
while(pos>=0)
{
if(pos==total-iMAPeriod)
{
for(i=0,k=pos;i<iMAPeriod;i++,k++)
{
sum+=sourceArray[k];
buf[k]=0;
}
}
else sum=buf[pos+1]*(iMAPeriod-1)+sourceArray[pos];
buf[pos]=sum/iMAPeriod;
pos--;
}
return(buf[Shift+ma_shift]);
}
case MODE_LWMA :
{
double sum=0.0,lsum=0.0;
double price;
int i,weight=0,pos=total-1;
for(i=1;i<=iMAPeriod;i++,pos--)
{
price=sourceArray[pos];
sum+=price*i;
lsum+=price;
weight+=i;
}
pos++;
i=pos+iMAPeriod;
while(pos>=0)
{
buf[pos]=sum/weight;
if(pos==0) break;
pos--;
i--;
price=sourceArray[pos];
sum=sum-lsum+price*iMAPeriod;
lsum-=sourceArray[i];
lsum+=price;
}
return(buf[Shift+ma_shift]);
}
default: return(0);
}
return(0);
}
//+------------------------------------------------------------------+
三.含未来函数的指标(一般有未来函数的指标都要注意,它们是改写历史,不是很好的指标)
1.如果判定 用系统自带的测试功能,历史重演,看指标箭头是否会消失
2.zigzag指标改写,添加上下箭头,效果图如下
image.png3.实现(先复制系统zigzag源码,在进行如下修改即可)
//+------------------------------------------------------------------+
//| ZigZag.mq5 |
//| Copyright 2009-2017, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009-2017, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
//2.重新设置缓存数组大小,和画图对象个数
#property indicator_buffers 5
#property indicator_plots 3
//---- plot Zigzag
#property indicator_label1 "Zigzag"
#property indicator_type1 DRAW_SECTION
#property indicator_color1 Red
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//1.新增箭头线
#property indicator_label2 "ZigzagHigh"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 White
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
#property indicator_label3 "ZigzagLow"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 Yellow
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
//--- input parameters
input int ExtDepth=12;
input int ExtDeviation=5;
input int ExtBackstep=3;
//--- indicator buffers
double ZigzagBuffer[]; // main buffer
double HighMapBuffer[]; // highs
double LowMapBuffer[]; // lows
//3.添加缓存数组
double ZigzagHighBuffer[]; //
double ZigzagLowBuffer[]; //
int level=3; // recounting depth
double deviation; // deviation in points
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA);
SetIndexBuffer(3,HighMapBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(4,LowMapBuffer,INDICATOR_CALCULATIONS);
//3.1 设置缓存数组(注意下标是1-2,不是上面的3-4)
SetIndexBuffer(1,ZigzagHighBuffer,INDICATOR_DATA);
SetIndexBuffer(2,ZigzagLowBuffer,INDICATOR_DATA);
//--- set short name and digits
PlotIndexSetString(0,PLOT_LABEL,"ZigZag("+(string)ExtDepth+","+(string)ExtDeviation+","+(string)ExtBackstep+")");
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- set empty value
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//3.2
PlotIndexSetInteger(1,PLOT_ARROW,226);
PlotIndexSetInteger(2,PLOT_ARROW,225);
PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0);
//--- to use in cycle
deviation=ExtDeviation*_Point;
//---
return(0);
}
//+------------------------------------------------------------------+
//| searching index of the highest bar |
//+------------------------------------------------------------------+
int iHighest(const double &array[],
int depth,
int startPos)
{
int index=startPos;
//--- start index validation
if(startPos<0)
{
Print("Invalid parameter in the function iHighest, startPos =",startPos);
return 0;
}
int size=ArraySize(array);
//--- depth correction if need
if(startPos-depth<0) depth=startPos;
double max=array[startPos];
//--- start searching
for(int i=startPos;i>startPos-depth;i--)
{
if(array[i]>max)
{
index=i;
max=array[i];
}
}
//--- return index of the highest bar
return(index);
}
//+------------------------------------------------------------------+
//| searching index of the lowest bar |
//+------------------------------------------------------------------+
int iLowest(const double &array[],
int depth,
int startPos)
{
int index=startPos;
//--- start index validation
if(startPos<0)
{
Print("Invalid parameter in the function iLowest, startPos =",startPos);
return 0;
}
int size=ArraySize(array);
//--- depth correction if need
if(startPos-depth<0) depth=startPos;
double min=array[startPos];
//--- start searching
for(int i=startPos;i>startPos-depth;i--)
{
if(array[i]<min)
{
index=i;
min=array[i];
}
}
//--- return index of the lowest bar
return(index);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
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[])
{
int i=0;
int limit=0,counterZ=0,whatlookfor=0;
int shift=0,back=0,lasthighpos=0,lastlowpos=0;
double val=0,res=0;
double curlow=0,curhigh=0,lasthigh=0,lastlow=0;
//--- auxiliary enumeration
enum looling_for
{
Pike=1, // searching for next high
Sill=-1 // searching for next low
};
//--- initializing
if(prev_calculated==0)
{
ArrayInitialize(ZigzagBuffer,0.0);
ArrayInitialize(HighMapBuffer,0.0);
ArrayInitialize(LowMapBuffer,0.0);
//4.1 类推
ArrayInitialize(ZigzagHighBuffer,0.0);
ArrayInitialize(ZigzagLowBuffer,0.0);
}
//---
if(rates_total<100) return(0);
//--- set start position for calculations
if(prev_calculated==0) limit=ExtDepth;
//--- ZigZag was already counted before
if(prev_calculated>0)
{
i=rates_total-1;
//--- searching third extremum from the last uncompleted bar
while(counterZ<level && i>rates_total-100)
{
res=ZigzagBuffer[i];
if(res!=0) counterZ++;
i--;
}
i++;
limit=i;
//--- what type of exremum we are going to find
if(LowMapBuffer[i]!=0)
{
curlow=LowMapBuffer[i];
whatlookfor=Pike;
}
else
{
curhigh=HighMapBuffer[i];
whatlookfor=Sill;
}
//--- chipping
for(i=limit+1;i<rates_total && !IsStopped();i++)
{
ZigzagBuffer[i]=0.0;
LowMapBuffer[i]=0.0;
HighMapBuffer[i]=0.0;
//4.2类推
ZigzagHighBuffer[i]=0.0;
ZigzagLowBuffer[i]=0.0;
}
}
//--- searching High and Low
for(shift=limit;shift<rates_total && !IsStopped();shift++)
{
val=low[iLowest(low,ExtDepth,shift)];
if(val==lastlow) val=0.0;
else
{
lastlow=val;
if((low[shift]-val)>deviation) val=0.0;
else
{
for(back=1;back<=ExtBackstep;back++)
{
res=LowMapBuffer[shift-back];
if((res!=0) && (res>val)) LowMapBuffer[shift-back]=0.0;
}
}
}
if(low[shift]==val) LowMapBuffer[shift]=val; else LowMapBuffer[shift]=0.0;
//--- high
val=high[iHighest(high,ExtDepth,shift)];
if(val==lasthigh) val=0.0;
else
{
lasthigh=val;
if((val-high[shift])>deviation) val=0.0;
else
{
for(back=1;back<=ExtBackstep;back++)
{
res=HighMapBuffer[shift-back];
if((res!=0) && (res<val)) HighMapBuffer[shift-back]=0.0;
}
}
}
if(high[shift]==val) HighMapBuffer[shift]=val; else HighMapBuffer[shift]=0.0;
}
//--- last preparation
if(whatlookfor==0)// uncertain quantity
{
lastlow=0;
lasthigh=0;
}
else
{
lastlow=curlow;
lasthigh=curhigh;
}
//--- final rejection
for(shift=limit;shift<rates_total && !IsStopped();shift++)
{
res=0.0;
switch(whatlookfor)
{
case 0: // search for peak or lawn
if(lastlow==0 && lasthigh==0)
{
if(HighMapBuffer[shift]!=0)
{
lasthigh=high[shift];
lasthighpos=shift;
whatlookfor=Sill;
ZigzagBuffer[shift]=lasthigh;
res=1;
}
if(LowMapBuffer[shift]!=0)
{
lastlow=low[shift];
lastlowpos=shift;
whatlookfor=Pike;
ZigzagBuffer[shift]=lastlow;
res=1;
}
}
break;
case Pike: // search for peak
if(LowMapBuffer[shift]!=0.0 && LowMapBuffer[shift]<lastlow && HighMapBuffer[shift]==0.0)
{
ZigzagBuffer[lastlowpos]=0.0;
lastlowpos=shift;
lastlow=LowMapBuffer[shift];
ZigzagBuffer[shift]=lastlow;
res=1;
}
if(HighMapBuffer[shift]!=0.0 && LowMapBuffer[shift]==0.0)
{
lasthigh=HighMapBuffer[shift];
lasthighpos=shift;
ZigzagBuffer[shift]=lasthigh;
whatlookfor=Sill;
res=1;
}
break;
case Sill: // search for lawn
if(HighMapBuffer[shift]!=0.0 && HighMapBuffer[shift]>lasthigh && LowMapBuffer[shift]==0.0)
{
ZigzagBuffer[lasthighpos]=0.0;
lasthighpos=shift;
lasthigh=HighMapBuffer[shift];
ZigzagBuffer[shift]=lasthigh;
}
if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0)
{
lastlow=LowMapBuffer[shift];
lastlowpos=shift;
ZigzagBuffer[shift]=lastlow;
whatlookfor=Pike;
}
break;
default: return(rates_total);
}
}
//5.画箭头的主要代码
for(shift=limit;shift<rates_total && !IsStopped();shift++)
{
if(ZigzagBuffer[shift]>0)
{
if(NormalizeDouble(ZigzagBuffer[shift],Digits())>=NormalizeDouble(high[shift],Digits()))
{
ZigzagHighBuffer[shift]=ZigzagBuffer[shift];
}
if(NormalizeDouble(ZigzagBuffer[shift],Digits())<=NormalizeDouble(low[shift],Digits()))
{
ZigzagLowBuffer[shift]=ZigzagBuffer[shift];
}
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
如果您发现本文对你有所帮助,如果您认为其他人也可能受益,请把它分享出去。
网友评论