//+------------------------------------------------------------------+ //| AdaptiveBDV_v1.0 600+.mq4 | //| Copyright © 2016, TrendLaboratory | //| http://finance.groups.yahoo.com/group/TrendLaboratory | //| E-mail: igorad2003@yahoo.co.uk | //+------------------------------------------------------------------+ #property copyright "Copyright © 2016, TrendLaboratory" #property link "http://finance.groups.yahoo.com/group/TrendLaboratory" #property link "http://newdigital-world.com" #property indicator_separate_window #property indicator_buffers 1 #property indicator_color1 clrTomato #property indicator_width1 2 #property indicator_level1 0 #property indicator_level2 -30 #property indicator_level3 100 #property indicator_level4 40 enum ENUM_MA_MODE { SMA, // Simple Moving Average EMA, // Exponential Moving Average Wilder, // Wilder Exponential Moving Average LWMA, // Linear Weighted Moving Average SineWMA, // Sine Weighted Moving Average TriMA, // Triangular Moving Average LSMA, // Least Square Moving Average (or EPMA, Linear Regression Line) SMMA, // Smoothed Moving Average HMA, // Hull Moving Average by Alan Hull ZeroLagEMA, // Zero-Lag Exponential Moving Average DEMA, // Double Exponential Moving Average by Patrick Mulloy T3_basic, // T3 by T.Tillson (original version) ITrend, // Instantaneous Trendline by J.Ehlers Median, // Moving Median GeoMean, // Geometric Mean REMA, // Regularized EMA by Chris Satchwell ILRS, // Integral of Linear Regression Slope IE_2, // Combination of LSMA and ILRS TriMAgen, // Triangular Moving Average generalized by J.Ehlers VWMA, // Volume Weighted Moving Average JSmooth, // Smoothing by Mark Jurik SMA_eq, // Simplified SMA ALMA, // Arnaud Legoux Moving Average TEMA, // Triple Exponential Moving Average by Patrick Mulloy T3, // T3 by T.Tillson (correct version) Laguerre, // Laguerre filter by J.Ehlers MD, // McGinley Dynamic BF2P, // Two-pole modified Butterworth filter by J.Ehlers BF3P, // Three-pole modified Butterworth filter by J.Ehlers SuperSmu, // SuperSmoother by J.Ehlers Decycler, // Simple Decycler by J.Ehlers eVWMA // Modified eVWMA }; enum ENUM_PRICE { close, // Close open, // Open high, // High low, // Low median, // Median typical, // Typical weightedClose, // Weighted Close heikenAshiClose, // Heiken Ashi Close heikenAshiOpen, // Heiken Ashi Open heikenAshiHigh, // Heiken Ashi High heikenAshiLow, // Heiken Ashi Low heikenAshiMedian, // Heiken Ashi Median heikenAshiTypical, // Heiken Ashi Typical heikenAshiWeighted // Heiken Ashi Weighted Close }; #define pi 3.14159265358979323846 //---- indicator parameters input ENUM_TIMEFRAMES TimeFrame = 0; // TimeFrame input ENUM_PRICE Price = 0; // Applied to input int Periods = 0; // Bollinger Bands Period(0-with adaptive length) input ENUM_MA_MODE MA_Method = SMA; // MA Method input int StartBar = 1; input int RangeBars = 100; input double Alpha = 0.07; // Cycle Smoothing Factor(eg. 0.07) input int MedianPeriod = 5; // Period of Moving Median input int DCsmooth = 5; // Period of Dominant Cycle Smoothing input double DCratio = 0.5; // Dominant Cycle Ratio (eg. 0.5) input int CountBars = 0; // Number of bars counted: 0-all bars //---- indicator buffers double bdv[]; double moving[]; double stdev[]; double iprice[]; //---- int cBars, timeframe, draw_begin, masize; string TF, IndicatorName, short_name, maname; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { timeframe = TimeFrame; if(timeframe <= Period()) timeframe = Period(); TF = tf(timeframe); IndicatorDigits(5); //---- indicator buffers mapping IndicatorBuffers(4); SetIndexBuffer(0, bdv); SetIndexStyle(0,DRAW_LINE); SetIndexBuffer(1,moving); SetIndexBuffer(2, stdev); SetIndexBuffer(3,iprice); //---- indicator name maname = EnumToString(MA_Method); masize = averageSize(MA_Method); IndicatorName = WindowExpertName(); short_name = IndicatorName + "[" + TF + "]("+ EnumToString(Price) + "," + Periods + "," + maname + "," + DoubleToStr(Alpha,3) + ")"; IndicatorShortName(short_name); SetIndexLabel(0,"BDV"); //---- if(CountBars == 0) cBars = timeframe/Period()*(iBars(NULL,TimeFrame) - (MathMax(50,Periods) + MedianPeriod + DCsmooth + RangeBars + StartBar)); else cBars = CountBars*timeframe/Period(); draw_begin = Bars - cBars; SetIndexDrawBegin(0,draw_begin); ArrayResize(tmp,masize); //---- initialization done return(0); } //+------------------------------------------------------------------+ //| AdaptiveBDV_v1.0 600+ | //+------------------------------------------------------------------+ int start() { int limit, i, shift, counted_bars = IndicatorCounted(); if(counted_bars > 0) limit =Bars - counted_bars - 1; if(counted_bars < 0) return(0); if(counted_bars < 1) { limit = Bars - 1; for(i=limit;i>=0;i--) { bdv[i] = EMPTY_VALUE; } } if(timeframe != Period()) { limit = MathMax(limit,timeframe/Period()+1); for(shift = 0;shift < limit;shift++) { int y = iBarShift(NULL,timeframe,Time[shift]); bdv[shift] = iCustom(NULL,TimeFrame,IndicatorName,0,Price,Periods,MA_Method,StartBar,RangeBars,Alpha,MedianPeriod,DCsmooth,DCratio,CountBars,0,y); } if(CountBars > 0) SetIndexDrawBegin(0,Bars - cBars); return(0); } else _AdaptBDV(limit); if(CountBars > 0) SetIndexDrawBegin(0,Bars - cBars); return(0); } //----- void _AdaptBDV(int limit) { for(int shift=limit;shift>=0;shift--) { if((int)Price <= 6) iprice[shift] = iMA(NULL,0,1,0,0,(int)Price,shift); else if((int)Price > 6 && (int)Price <= 13) iprice[shift] = HeikenAshi((int)Price-7,cBars,shift); if(Periods == 0) int length = MathMax(1,MathFloor(cyclePeriod(iprice,Alpha,MedianPeriod,DCsmooth,shift)*DCratio)); else length = Periods; if(length == 0 || shift > Bars - 2) continue; moving[shift] = allAveragesOnArray(0,iprice,length,(int)MA_Method,masize,cBars + length,shift); stdev[shift] = stdDev(iprice,moving,length,shift); int cnt = 0; double sumstdev = 0; for(int i=StartBar;i<=RangeBars+StartBar;i++) { sumstdev += stdev[shift+i]; cnt++; } if(cnt == 0) cnt = 1; double avgsd = sumstdev/cnt; if(avgsd != 0) bdv[shift] = (stdev[shift] - avgsd)/avgsd*100; else bdv[shift] = 0; } } //----- double DeltaPhase[], aprice[4], smooth[3], cycle[7], Q1[2], I1[2], iPeriod[2], cPeriod[4]; datetime prevcptime; double cyclePeriod(double& price[],double alpha,int median,int dcsmooth,int bar) { if(ArraySize(DeltaPhase) != Bars) { ArraySetAsSeries(DeltaPhase,false); ArrayResize(DeltaPhase,Bars); ArraySetAsSeries(DeltaPhase,true); } if(prevcptime != Time[bar]) { for(int i=6;i>=1;i--) { cycle[i] = cycle[i-1]; if(i < 4) { aprice[i] = aprice[i-1]; cPeriod[i] = cPeriod[i-1]; } if(i < 3) smooth[i] = smooth[i-1]; } I1[1] = I1[0]; Q1[1] = Q1[0]; iPeriod[1] = iPeriod[0]; prevcptime = Time[bar]; } aprice[0] = price[bar]; if(bar < Bars - 3) smooth[0] = (aprice[0] + 2*aprice[1] + 2*aprice[2] + aprice[3])/6; cycle[0] = (1 - 0.5*alpha)*(1 - 0.5*alpha)*(smooth[0] - 2*smooth[1] + smooth[2]) + 2*(1-alpha)*cycle[1] - (1-alpha)*(1-alpha)*cycle[2]; if(bar > Bars - 7) cycle[0] = (aprice[0] - 2*aprice[1] + aprice[2])/4; Q1[0] = (0.0962*cycle[0] + 0.5769*cycle[2] - 0.5769*cycle[4] - 0.0962*cycle[6])*(0.5+0.08*iPeriod[1]); I1[0] = cycle[3]; if(Q1[0] != 0 && Q1[1] != 0) DeltaPhase[bar] = (I1[0]/Q1[0] - I1[1]/Q1[1])/(1 + I1[0]*I1[1]/(Q1[0]*Q1[1])); if(DeltaPhase[bar] < 0.1) DeltaPhase[bar] = 0.1; if(DeltaPhase[bar] > 1.1) DeltaPhase[bar] = 1.1; double MedianDelta = MedianOnArray(DeltaPhase,median,bar); if(MedianDelta == 0) double DC = 15; else DC = 6.28318/MedianDelta + 0.5; iPeriod[0] = 0.33*DC + (1 - 2.0/(dcsmooth + 1))*iPeriod[1]; cPeriod[0] = 0.15*iPeriod[0] + 0.85*cPeriod[1]; if(cPeriod[3] == 0) return(0); return(cPeriod[0]); } //----- //---------------- //---------------- int averageSize(int mode) { int arraysize; switch(mode) { case 10: arraysize = 2; break; case 11: arraysize = 6; break; case 20: arraysize = 5; break; case 23: arraysize = 4; break; case 24: arraysize = 6; break; case 25: arraysize = 4; break; default: arraysize = 0; break; } return(arraysize); } double tmp[][2][2], ma[2][4]; datetime prevtime[2]; double allAveragesOnArray(int index,double& price[],int period,int mode,int arraysize,int cbars,int bar) { double MA[4]; if(mode == 1 || mode == 2 || mode == 7 || mode == 9 || mode == 10 || mode == 11 || mode == 12 || mode == 15 || mode == 20 || mode == 21 || (mode > 22 && mode <= 31)) { if(prevtime[index] != Time[bar]) { ma[index][3] = ma[index][2]; ma[index][2] = ma[index][1]; ma[index][1] = ma[index][0]; if(arraysize > 0) for(int i=0;i 26 && mode < 31)) for(i=0;i<4;i++) MA[i] = ma[index][i]; } switch(mode) { case 1 : ma[index][0] = EMAOnArray(price[bar],ma[index][1],period,cbars,bar); break; case 2 : ma[index][0] = WilderOnArray(price[bar],ma[index][1],period,cbars,bar); break; case 3 : ma[index][0] = LWMAOnArray(price,period,bar); break; case 4 : ma[index][0] = SineWMAOnArray(price,period,bar); break; case 5 : ma[index][0] = TriMAOnArray(price,period,bar); break; case 6 : ma[index][0] = LSMAOnArray(price,period,bar); break; case 7 : ma[index][0] = SMMAOnArray(price,ma[index][1],period,cbars,bar); break; case 8 : ma[index][0] = HMAOnArray(price,period,cbars,bar); break; case 9 : ma[index][0] = ZeroLagEMAOnArray(price,ma[index][1],period,cbars,bar); break; case 10: ma[index][0] = DEMAOnArray(index,0,price[bar],period,1,cbars,bar); break; case 11: ma[index][0] = T3_basicOnArray(index,0,price[bar],period,0.7,cbars,bar); break; case 12: ma[index][0] = ITrendOnArray(price,MA,period,cbars,bar); break; case 13: ma[index][0] = MedianOnArray(price,period,bar); break; case 14: ma[index][0] = GeoMeanOnArray(price,period,cbars,bar); break; case 15: ma[index][0] = REMAOnArray(price[bar],MA,period,0.5,cbars,bar); break; case 16: ma[index][0] = ILRSOnArray(price,period,bar); break; case 17: ma[index][0] = IE2OnArray(price,period,bar); break; case 18: ma[index][0] = TriMA_genOnArray(price,period,bar); break; case 19: ma[index][0] = VWMAOnArray(price,period,bar); break; case 20: ma[index][0] = JSmoothOnArray(index,0,price[bar],period,1,cbars,bar); break; case 21: ma[index][0] = SMA_eqOnArray(price,MA,period,cbars,bar); break; case 22: ma[index][0] = ALMAOnArray(price,period,0.85,8,bar); break; case 23: ma[index][0] = TEMAOnArray(index,price[bar],period,1,cbars,bar); break; case 24: ma[index][0] = T3OnArray(index,0,price[bar],period,0.7,cbars,bar); break; case 25: ma[index][0] = LaguerreOnArray(index,price[bar],period,4,cbars,bar); break; case 26: ma[index][0] = McGinleyOnArray(price[bar],ma[index][1],period,cbars,bar); break; case 27: ma[index][0] = BF2POnArray(price,MA,period,cbars,bar); break; case 28: ma[index][0] = BF3POnArray(price,MA,period,cbars,bar); break; case 29: ma[index][0] = SuperSmuOnArray(price,MA,period,cbars,bar); break; case 30: ma[index][0] = DecyclerOnArray(price,MA,period,cbars,bar); return(price[bar] - ma[index][0]); case 31: ma[index][0] = eVWMAOnArray(price[bar],ma[index][1],period,cbars,bar); break; default: ma[index][0] = SMAOnArray(price,period,bar); break; } return(ma[index][0]); } // MA_Method=0: SMA - Simple Moving Average double SMAOnArray(double& array[],int per,int bar) { double sum = 0; for(int i=0;i= cbars - 2) double ema = price; else ema = prev + 2.0/(1 + per)*(price - prev); return(ema); } // MA_Method=2: Wilder - Wilder Exponential Moving Average double WilderOnArray(double price,double prev,int per,int cbars,int bar) { if(bar >= cbars - 2) double wilder = price; else wilder = prev + (price - prev)/per; return(wilder); } // MA_Method=3: LWMA - Linear Weighted Moving Average double LWMAOnArray(double& array[],int per,int bar) { double sum = 0, weight = 0; for(int i=0;i 0) return(sum/weight); else return(0); } // MA_Method=4: SineWMA - Sine Weighted Moving Average double SineWMAOnArray(double& array[],int per,int bar) { double sum = 0, weight = 0; for(int i=0;i 0) return(sum/weight); else return(0); } // MA_Method=5: TriMA - Triangular Moving Average double TriMAOnArray(double& array[],int per,int bar) { int len = MathCeil((per + 1)*0.5); double sum = 0; for(int i=0;i=1;i--) sum += (i - (per + 1)/3.0)*array[bar+per-i]; return(sum*6/(per*(per + 1))); } // MA_Method=7: SMMA - Smoothed Moving Average double SMMAOnArray(double& array[],double prev,int per,int cbars,int bar) { if(bar == cbars - per) double smma = SMAOnArray(array,per,bar); else if(bar < cbars - per) { double sum = 0; for(int i=0;i= cbars - lag) double zema = price[bar]; else zema = alpha*(2*price[bar] - price[bar+lag]) + (1 - alpha)*prev; return(zema); } // MA_Method=10: DEMA - Double Exponential Moving Average by Patrick Mulloy double DEMAOnArray(int index,int num,double price,double per,double v,int cbars,int bar) { double alpha = 2.0/(1 + per); if(bar == cbars - 2) {double dema = price; tmp[num][index][0] = dema; tmp[num+1][index][0] = dema;} else if(bar < cbars - 2) { tmp[num ][index][0] = tmp[num ][index][1] + alpha*(price - tmp[num ][index][1]); tmp[num+1][index][0] = tmp[num+1][index][1] + alpha*(tmp[num][index][0] - tmp[num+1][index][1]); dema = tmp[num ][index][0]*(1+v) - tmp[num+1][index][0]*v; } return(dema); } // MA_Method=11: T3 by T.Tillson double T3_basicOnArray(int index,int num,double price,int per,double v,int cbars,int bar) { double dema1, dema2; if(bar == cbars - 2) { double T3 = price; for(int k=0;k<6;k++) tmp[num+k][index][0] = price; } else if(bar < cbars - 2) { dema1 = DEMAOnArray(index,num ,price,per,v,cbars,bar); dema2 = DEMAOnArray(index,num+2,dema1,per,v,cbars,bar); T3 = DEMAOnArray(index,num+4,dema2,per,v,cbars,bar); } return(T3); } // MA_Method=12: ITrend - Instantaneous Trendline by J.Ehlers double ITrendOnArray(double& price[],double& array[],int per,int cbars,int bar) { double alpha = 2.0/(per + 1); if(bar < cbars - 7) double it = (alpha - 0.25*alpha*alpha)*price[bar] + 0.5*alpha*alpha*price[bar+1] - (alpha - 0.75*alpha*alpha)*price[bar+2] + 2*(1 - alpha)*array[1] - (1 - alpha)*(1 - alpha)*array[2]; else it = (price[bar] + 2*price[bar+1] + price[bar+2])/4; return(it); } // MA_Method=13: Median - Moving Median double MedianOnArray(double& price[],int per,int bar) { double array[]; ArrayResize(array,per); for(int i=0;i 0) double median = array[num]; else median = 0.5*(array[num] + array[num+1]); return(median); } // MA_Method=14: GeoMean - Geometric Mean double GeoMeanOnArray(double& price[],int per,int cbars,int bar) { if(bar < cbars - per) { double gmean = MathPow(price[bar],1.0/per); for(int i=1;i= cbars - 3) double rema = price; else rema = (array[1]*(1 + 2*lambda) + alpha*(price - array[1]) - lambda*array[2])/(1 + lambda); return(rema); } // MA_Method=16: ILRS - Integral of Linear Regression Slope double ILRSOnArray(double& price[],int per,int bar) { double sum = per*(per - 1)*0.5; double sum2 = (per - 1)*per*(2*per - 1)/6.0; double sum1 = 0; double sumy = 0; for(int i=0;i 0) return(sum/weight); else return(0); } // MA_Method=20: JSmooth - Smoothing by Mark Jurik double JSmoothOnArray(int index,int num,double price,int per,double power,int cbars,int bar) { double beta = 0.45*(per - 1)/(0.45*(per - 1) + 2); double alpha = MathPow(beta,power); if(bar == cbars - 2) {tmp[num+4][index][0] = price; tmp[num+0][index][0] = price; tmp[num+2][index][0] = price;} else if(bar < cbars - 2) { tmp[num+0][index][0] = (1 - alpha)*price + alpha*tmp[num+0][index][1]; tmp[num+1][index][0] = (price - tmp[num+0][index][0])*(1-beta) + beta*tmp[num+1][index][1]; tmp[num+2][index][0] = tmp[num+0][index][0] + tmp[num+1][index][0]; tmp[num+3][index][0] = (tmp[num+2][index][0] - tmp[num+4][index][1])*MathPow((1-alpha),2) + MathPow(alpha,2)*tmp[num+3][index][1]; tmp[num+4][index][0] = tmp[num+4][index][1] + tmp[num+3][index][0]; } return(tmp[num+4][index][0]); } // MA_Method=21: SMA_eq - Simplified SMA double SMA_eqOnArray(double& price[],double& array[],int per,int cbars,int bar) { if(bar == cbars - per) double sma = SMAOnArray(price,per,bar); else if(bar < cbars - per) sma = (price[bar] - price[bar+per])/per + array[1]; return(sma); } // MA_Method=22: ALMA by Arnaud Legoux / Dimitris Kouzis-Loukas / Anthony Cascino double ALMAOnArray(double& price[],int per,double offset,double sigma,int bar) { double m = MathFloor(offset*(per - 1)), s = per/sigma, w, sum = 0, wsum = 0; for (int i=0;i= cbars - order) tmp[i][index][0] = price; else { if(i == 0) tmp[i][index][0] = (1 - gamma)*price + gamma*tmp[i][index][1]; else tmp[i][index][0] = -gamma * tmp[i-1][index][0] + tmp[i-1][index][1] + gamma * tmp[i][index][1]; aPrice[i] = tmp[i][index][0]; } } double laguerre = TriMA_genOnArray(aPrice,order,0); return(laguerre); } // MA_Method=26: MD - McGinley Dynamic double McGinleyOnArray(double price,double prev,int per,int cbars,int bar) { if(bar == cbars - 2) double md = price; else if(bar < cbars - 2) if(prev != 0) md = prev + (price - prev)/(per*MathPow(price/prev,4)/2); else md = price; return(md); } // MA_Method=27: BF2P - Two-pole modified Butterworth filter double BF2POnArray(double& price[],double& array[],int per,int cbars,int bar) { double a = MathExp(-1.414*pi/per); double b = 2*a*MathCos(1.414*1.25*pi/per); double c2 = b; double c3 = -a*a; double c1 = 1 - c2 - c3; if(bar < cbars - 7) double bf2p = c1*(price[bar] + 2*price[bar+1] + price[bar+2])/4 + c2*array[1] + c3*array[2]; else bf2p = (price[bar] + 2*price[bar+1] + price[bar+2])/4; return(bf2p); } // MA_Method=28: BF3P - Three-pole modified Butterworth filter double BF3POnArray(double& price[],double& array[],int per,int cbars,int bar) { double a = MathExp(-pi/per); double b = 2*a*MathCos(1.738*pi/per); double c = a*a; double d2 = b + c; double d3 = -(c + b*c); double d4 = c*c; double d1 = 1 - d2 - d3 - d4; if(bar < cbars - 7) double bf3p = d1*(price[bar] + 3*price[bar+1] + 3*price[bar+2] + price[bar+3])/8 + d2*array[1] + d3*array[2] + d4*array[3]; else bf3p = (price[bar] + 3*price[bar+1] + 3*price[bar+2] + price[bar+3])/8; return(bf3p); } // MA_Method=29: SuperSmu - SuperSmoother filter double SuperSmuOnArray(double& price[],double& array[],int per,int cbars,int bar) { double a = MathExp(-1.414*pi/per); double b = 2*a*MathCos(1.414*pi/per); double c2 = b; double c3 = -a*a; double c1 = 1 - c2 - c3; if(bar < cbars - 7) double supsm = c1*(price[bar] + price[bar+1])/2 + c2*array[1] + c3*array[2]; else supsm = (price[bar] + price[bar+1])/2; return(supsm); } // MA_Method=30: Decycler - Simple Decycler by J.Ehlers double DecyclerOnArray(double& price[],double& hp[],int per,int cbars,int bar) { double alpha1 = (MathCos(1.414*pi/per) + MathSin(1.414*pi/per) - 1)/MathCos(1.414*pi/per); if(bar > cbars - 4) return(0); hp[0] = (1 - alpha1/2)*(1 - alpha1/2)*(price[bar] - 2*price[bar+1] + price[bar+2]) + 2*(1 - alpha1)*hp[1] - (1 - alpha1)*(1 - alpha1)*hp[2]; return(hp[0]); } // MA_Method=31: eVWMA - Elastic Volume Weighted Moving Average by C.Fries double eVWMAOnArray(double price,double prev,int per,int cbars,int bar) { if(bar >= cbars - per) double evwma = price; else { double max = 0; for(int i=0;i= PERIOD_H1 ) result = "H" + itimeframe/PERIOD_H1; if(itimeframe >= PERIOD_D1 ) result = "D" + itimeframe/PERIOD_D1; if(itimeframe >= PERIOD_W1 ) result = "W" + itimeframe/PERIOD_W1; if(itimeframe >= PERIOD_MN1) result = "MN" + itimeframe/PERIOD_MN1; } return(result); }