//+------------------------------------------------------------------+ //| bb stops stochastic | //| translated from Mladen's mt5 version | //| | //+------------------------------------------------------------------+ #property copyright "www.forex-station.com" #property link "www.forex-station.com" #property indicator_separate_window #property indicator_buffers 7 #property indicator_type1 DRAW_LINE #property indicator_color1 clrGray #property indicator_style1 STYLE_DOT #property indicator_type2 DRAW_LINE #property indicator_color2 clrGray #property indicator_style2 STYLE_DOT #property indicator_type3 DRAW_LINE #property indicator_color3 clrSilver #property indicator_style3 STYLE_DASH #property indicator_type4 DRAW_LINE #property indicator_color4 clrDodgerBlue #property indicator_width4 3 #property indicator_type5 DRAW_LINE #property indicator_color5 clrSandyBrown #property indicator_width5 3 #property indicator_color6 clrDodgerBlue, #property indicator_width6 2 #property indicator_color7 clrSandyBrown #property indicator_width7 2 #property strict // // // // // enum enPrices { pr_close, // Close pr_open, // Open pr_high, // High pr_low, // Low pr_median, // Median pr_typical, // Typical pr_weighted, // Weighted pr_average, // Average (high+low+open+close)/4 pr_medianb, // Average median body (open+close)/2 pr_tbiased, // Trend biased price pr_tbiased2, // Trend biased (extreme) price pr_haclose, // Heiken ashi close pr_haopen , // Heiken ashi open pr_hahigh, // Heiken ashi high pr_halow, // Heiken ashi low pr_hamedian, // Heiken ashi median pr_hatypical, // Heiken ashi typical pr_haweighted, // Heiken ashi weighted pr_haaverage, // Heiken ashi average pr_hamedianb, // Heiken ashi median body pr_hatbiased, // Heiken ashi trend biased price pr_hatbiased2, // Heiken ashi trend biased (extreme) price pr_habclose, // Heiken ashi (better formula) close pr_habopen , // Heiken ashi (better formula) open pr_habhigh, // Heiken ashi (better formula) high pr_hablow, // Heiken ashi (better formula) low pr_habmedian, // Heiken ashi (better formula) median pr_habtypical, // Heiken ashi (better formula) typical pr_habweighted,// Heiken ashi (better formula) weighted pr_habaverage, // Heiken ashi (better formula) average pr_habmedianb, // Heiken ashi (better formula) median body pr_habtbiased, // Heiken ashi (better formula) trend biased price pr_habtbiased2 // Heiken ashi (better formula) trend biased (extreme) price }; enum enMaTypes { ma_sma, // Simple moving average ma_ema, // Exponential moving average ma_smma, // Smoothed MA ma_lwma, // Linear weighted MA ma_slwma, // Smoothed LWMA ma_dsema, // Double Smoothed Exponential average ma_tema, // Triple exponential moving average - TEMA ma_lsma, // Linear regression value (lsma) ma_dema // Double exponential moving average - DEMA }; extern ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; // Time frame input int StoPeriod = 32; // Stochastic period input int StoSlowing = 9; // Stochastic slowing period input enPrices PriceH = pr_high; // Price high input enPrices PriceL = pr_low; // Price low input enPrices PriceC = pr_close; // Price close input int MaPeriod = 20; // Bollinger bands period input enMaTypes MaMethod = ma_sma; // Moving average method input int DevPeriod = 20; // Deviations period input double Deviation = 1; // Deviation input bool DeviationSample = false; // Deviation sample correction? input double Risk = 1; // Risk input bool alertsOn = true; // Turn alerts on? input bool alertsOnCurrent = false; // Alerts on still opened bar? input bool alertsMessage = true; // Alerts should display message? input bool alertsSound = false; // Alerts should play a sound? input bool alertsNotify = false; // Alerts should send a notification? input bool alertsEmail = false; // Alerts should send an email? input string soundFile = "alert2.wav"; // Sound file input bool Interpolate = true; // Interpolate in multi time frame mode? // // // // // double sto[],bblu[],bbld[],upa[],dna[],amax[],amin[],bmin[],bmax[],trend[],count[]; string indicatorFileName; #define _mtfCall(_buff,_y) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,StoPeriod,StoSlowing,PriceH,PriceL,PriceC,MaPeriod,MaMethod,DevPeriod,Deviation,DeviationSample,Risk,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,_buff,_y) //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // // // // // int OnInit() { IndicatorBuffers(11); SetIndexBuffer(0, bmax, INDICATOR_DATA); SetIndexBuffer(1, bmin, INDICATOR_DATA); SetIndexBuffer(2, sto, INDICATOR_DATA); SetIndexBuffer(3, bblu, INDICATOR_DATA); SetIndexBuffer(4, bbld, INDICATOR_DATA); SetIndexBuffer(5, upa, INDICATOR_DATA); SetIndexStyle(5,DRAW_ARROW); SetIndexArrow(5,159); SetIndexBuffer(6, dna, INDICATOR_DATA); SetIndexStyle(6,DRAW_ARROW); SetIndexArrow(6,159); SetIndexBuffer(7, amax, INDICATOR_CALCULATIONS); SetIndexBuffer(8, amin, INDICATOR_CALCULATIONS); SetIndexBuffer(9, trend,INDICATOR_CALCULATIONS); SetIndexBuffer(10,count,INDICATOR_CALCULATIONS); indicatorFileName = WindowExpertName(); TimeFrame = fmax(TimeFrame,_Period); IndicatorShortName(timeFrameToString(TimeFrame)+" bb stops stochastic ("+(string)StoPeriod+","+(string)StoSlowing+","+(string)MaPeriod+")"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ // // // // // 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 &tickVolume[], const long &volume[], const int &spread[]) { int i,counted_bars=prev_calculated; if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; int limit = fmin(rates_total-counted_bars,rates_total-1); count[0]=limit; if (TimeFrame!=_Period) { limit = (int)fmax(limit,fmin(rates_total-1,_mtfCall(10,0)*TimeFrame/_Period)); for (i=limit;i>=0 && !_StopFlag; i--) { int y = iBarShift(NULL,TimeFrame,Time[i]); bmax[i] = _mtfCall(0,y); bmin[i] = _mtfCall(1,y); sto[i] = _mtfCall(2,y); bblu[i] = _mtfCall(3,y); bbld[i] = _mtfCall(4,y); upa[i] = EMPTY_VALUE; dna[i] = EMPTY_VALUE; trend[i] = _mtfCall(9,y); // // // // // if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue; #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n int n,k; datetime btime = iTime(NULL,TimeFrame,y); for(n = 1; (i+n)= btime; n++) continue; for(k = 1; k= 0; i--) { if (trend[i] == 1) bblu[i]=bmin[i]; if (trend[i] ==-1) bbld[i]=bmax[i]; upa[i] = (i= 0; i--) { double prices[3]; prices[0] = getPrice(PriceH,open,close,high,low,i,rates_total,0); prices[1] = getPrice(PriceL,open,close,high,low,i,rates_total,1); prices[2] = getPrice(PriceC,open,close,high,low,i,rates_total,2); ArraySort(prices); sto[i] = iStoch(prices[1],prices[2],prices[0],StoPeriod,StoSlowing,i,rates_total); double dev = iDeviation(sto[i],DevPeriod,DeviationSample,i,rates_total); double ma = iCustomMa(MaMethod,sto[i],MaPeriod,i,rates_total); amax[i] = ma+dev*Deviation; amin[i] = ma-dev*Deviation; bmax[i] = amax[i]+0.5*(Risk-1)*(amax[i]-amin[i]); bmin[i] = amin[i]-0.5*(Risk-1)*(amax[i]-amin[i]); trend[i] = (iamax[i+1]) ? 1 : (sto[i]amax[i+1]) amax[i] = amax[i+1]; if (trend[i]== 1 && amin[i]bmax[i+1]) bmax[i] = bmax[i+1]; if (trend[i]== 1 && bmin[i]=0; k++) { workSto[i][_mi+instanceNo] = fmin(workSto[i][_mi+instanceNo],workSto[i-k][instanceNo+_lo]); workSto[i][_ma+instanceNo] = fmax(workSto[i][_ma+instanceNo],workSto[i-k][instanceNo+_hi]); } double sumlow = 0.0; double sumhigh = 0.0; for(int k=0; k=0; k++) { sumlow += workSto[i-k][_re+instanceNo]-workSto[i-k][_mi+instanceNo]; sumhigh += workSto[i-k][_ma+instanceNo]-workSto[i-k][_mi+instanceNo]; } // // // // // if(sumhigh!=0.0) return(100.0*sumlow/sumhigh); else return(0); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // #define _maInstances 1 #define _maWorkBufferx1 1*_maInstances #define _maWorkBufferx2 2*_maInstances #define _maWorkBufferx3 3*_maInstances double iCustomMa(int mode, double price, double length, int r, int bars, int instanceNo=0) { r = bars-r-1; switch (mode) { case ma_sma : return(iSma(price,(int)ceil(length),r,bars,instanceNo)); case ma_ema : return(iEma(price,length,r,bars,instanceNo)); case ma_smma : return(iSmma(price,length,r,bars,instanceNo)); case ma_lwma : return(iLwma(price,(int)ceil(length),r,bars,instanceNo)); case ma_slwma : return(iSlwma(price,(int)ceil(length),r,bars,instanceNo)); case ma_dsema : return(iDsema(price,length,r,bars,instanceNo)); case ma_tema : return(iTema(price,length,r,bars,instanceNo)); case ma_lsma : return(iLinr(price,(int)ceil(length),r,bars,instanceNo)); case ma_dema : return(iDema(price,length,r,bars,instanceNo)); default : return(price); } } // // // // // double workSma[][_maWorkBufferx1]; double iSma(double price, int period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workSma,0)!= _bars) ArrayResize(workSma,_bars); workSma[r][instanceNo+0] = price; double avg = price; int k=1; for(; k=0; k++) avg += workSma[r-k][instanceNo+0]; return(avg/(double)k); } // // // // // double workEma[][_maWorkBufferx1]; double iEma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workEma,0)!= _bars) ArrayResize(workEma,_bars); workEma[r][instanceNo] = price; if (r>0 && period>1) workEma[r][instanceNo] = workEma[r-1][instanceNo]+(2.0/(1.0+period))*(price-workEma[r-1][instanceNo]); return(workEma[r][instanceNo]); } // // // // // double workSmma[][_maWorkBufferx1]; double iSmma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars); workSmma[r][instanceNo] = price; if (r>1 && period>1) workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1][instanceNo])/period; return(workSmma[r][instanceNo]); } // // // // // double workLwma[][_maWorkBufferx1]; double iLwma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars); workLwma[r][instanceNo] = price; if (period<=1) return(price); double sumw = period; double sum = period*price; for(int k=1; k=0; k++) { double weight = period-k; sumw += weight; sum += weight*workLwma[r-k][instanceNo]; } return(sum/sumw); } // // // // // double workSlwma[][_maWorkBufferx2]; double iSlwma(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workSlwma,0)!= _bars) ArrayResize(workSlwma,_bars); // // // // // int SqrtPeriod = (int)floor(sqrt(period)); instanceNo *= 2; workSlwma[r][instanceNo] = price; // // // // // double sumw = period; double sum = period*price; for(int k=1; k=0; k++) { double weight = period-k; sumw += weight; sum += weight*workSlwma[r-k][instanceNo]; } workSlwma[r][instanceNo+1] = (sum/sumw); // // // // // sumw = SqrtPeriod; sum = SqrtPeriod*workSlwma[r][instanceNo+1]; for(int k=1; k=0; k++) { double weight = SqrtPeriod-k; sumw += weight; sum += weight*workSlwma[r-k][instanceNo+1]; } return(sum/sumw); } // // // // // double workDsema[][_maWorkBufferx2]; #define _ema1 0 #define _ema2 1 double iDsema(double price, double period, int r, int _bars, int instanceNo=0) { if (ArrayRange(workDsema,0)!= _bars) ArrayResize(workDsema,_bars); instanceNo*=2; // // // // // workDsema[r][_ema1+instanceNo] = price; workDsema[r][_ema2+instanceNo] = price; if (r>0 && period>1) { double alpha = 2.0 /(1.0+sqrt(period)); workDsema[r][_ema1+instanceNo] = workDsema[r-1][_ema1+instanceNo]+alpha*(price -workDsema[r-1][_ema1+instanceNo]); workDsema[r][_ema2+instanceNo] = workDsema[r-1][_ema2+instanceNo]+alpha*(workDsema[r][_ema1+instanceNo]-workDsema[r-1][_ema2+instanceNo]); } return(workDsema[r][_ema2+instanceNo]); } // // // // // double workTema[][_maWorkBufferx3]; #define _tema1 0 #define _tema2 1 #define _tema3 2 double iTema(double price, double period, int r, int bars, int instanceNo=0) { if (ArrayRange(workTema,0)!= bars) ArrayResize(workTema,bars); instanceNo*=3; // // // // // workTema[r][_tema1+instanceNo] = price; workTema[r][_tema2+instanceNo] = price; workTema[r][_tema3+instanceNo] = price; if (r>0 && period>1) { double alpha = 2.0 / (1.0+period); workTema[r][_tema1+instanceNo] = workTema[r-1][_tema1+instanceNo]+alpha*(price -workTema[r-1][_tema1+instanceNo]); workTema[r][_tema2+instanceNo] = workTema[r-1][_tema2+instanceNo]+alpha*(workTema[r][_tema1+instanceNo]-workTema[r-1][_tema2+instanceNo]); workTema[r][_tema3+instanceNo] = workTema[r-1][_tema3+instanceNo]+alpha*(workTema[r][_tema2+instanceNo]-workTema[r-1][_tema3+instanceNo]); } return(workTema[r][_tema3+instanceNo]+3.0*(workTema[r][_tema1+instanceNo]-workTema[r][_tema2+instanceNo])); } // // // // // double workLinr[][_maWorkBufferx1]; double iLinr(double price, int period, int r, int bars, int instanceNo=0) { if (ArrayRange(workLinr,0)!= bars) ArrayResize(workLinr,bars); // // // // // period = MathMax(period,1); workLinr[r][instanceNo] = price; if (r=0; k++) { double weight = period-k; lwmw += weight; lwma += weight*workLinr[r-k][instanceNo]; sma += workLinr[r-k][instanceNo]; } return(3.0*lwma/lwmw-2.0*sma/period); } // // // // // double workDema[][_maWorkBufferx2]; #define _dema1 0 #define _dema2 1 double iDema(double price, double period, int r, int bars, int instanceNo=0) { if (period<=1) return(price); if (ArrayRange(workDema,0)!= bars) ArrayResize(workDema,bars); instanceNo*=2; // // // // // workDema[r][_dema1+instanceNo] = price; workDema[r][_dema2+instanceNo] = price; double alpha = 2.0 / (1.0+period); if (r>0) { workDema[r][_dema1+instanceNo] = workDema[r-1][_dema1+instanceNo]+alpha*(price -workDema[r-1][_dema1+instanceNo]); workDema[r][_dema2+instanceNo] = workDema[r-1][_dema2+instanceNo]+alpha*(workDema[r][_dema1+instanceNo]-workDema[r-1][_dema2+instanceNo]); } return(workDema[r][_dema1+instanceNo]*2.0-workDema[r][_dema2+instanceNo]); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // #define _prHABF(_prtype) (_prtype>=pr_habclose && _prtype<=pr_habtbiased2) #define _priceInstances 3 #define _priceInstancesSize 4 double workHa[][_priceInstances*_priceInstancesSize]; double getPrice(int tprice, const double& open[], const double& close[], const double& high[], const double& low[], int i, int bars, int instanceNo=0) { if (tprice>=pr_haclose) { if (ArrayRange(workHa,0)!= bars) ArrayResize(workHa,bars); instanceNo*=_priceInstancesSize; int r = bars-i-1; // // // // // double haOpen = (r>0) ? (workHa[r-1][instanceNo+2] + workHa[r-1][instanceNo+3])/2.0 : (open[i]+close[i])/2;; double haClose = (open[i]+high[i]+low[i]+close[i]) / 4.0; if (_prHABF(tprice)) if (high[i]!=low[i]) haClose = (open[i]+close[i])/2.0+(((close[i]-open[i])/(high[i]-low[i]))*fabs((close[i]-open[i])/2.0)); else haClose = (open[i]+close[i])/2.0; double haHigh = fmax(high[i], fmax(haOpen,haClose)); double haLow = fmin(low[i] , fmin(haOpen,haClose)); // // // // // if(haOpenhaOpen) return((haHigh+haClose)/2.0); else return((haLow+haClose)/2.0); case pr_hatbiased2: case pr_habtbiased2: if (haClose>haOpen) return(haHigh); if (haCloseopen[i]) return((high[i]+close[i])/2.0); else return((low[i]+close[i])/2.0); case pr_tbiased2: if (close[i]>open[i]) return(high[i]); if (close[i]=0; k++) { newMean = (workDev[i-k][instanceNo]-oldMean)/(k+1)+oldMean; squares += (workDev[i-k][instanceNo]-oldMean)*(workDev[i-k][instanceNo]-newMean); oldMean = newMean; } return(MathSqrt(squares/MathMax(k-isSample,1))); } //------------------------------------------------------------------- // //------------------------------------------------------------------- // // // // // string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"}; int iTfTable[] = {1,5,15,30,60,240,1440,10080,43200}; string timeFrameToString(int tf) { for (int i=ArraySize(iTfTable)-1; i>=0; i--) if (tf==iTfTable[i]) return(sTfTable[i]); return(""); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // void doAlert(string doWhat) { static string previousAlert="nothing"; static datetime previousTime; string message; if (previousAlert != doWhat || previousTime != Time[0]) { previousAlert = doWhat; previousTime = Time[0]; // // // // // message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" BB stops Stochastic state changed to "+doWhat; if (alertsMessage) Alert(message); if (alertsNotify) SendNotification(message); if (alertsEmail) SendMail(_Symbol+" BB stops Stochastic ",message); if (alertsSound) PlaySound(soundFile); } }