//------------------------------------------------------------------ #property copyright "© mladen, 2017" #property link "www.forex-station.com" //------------------------------------------------------------------ #property indicator_separate_window #property indicator_buffers 8 #property indicator_plots 5 #property indicator_label1 "rsi OB/OS zone" #property indicator_type1 DRAW_FILLING #property indicator_color1 C'209,243,209',C'255,230,183' #property indicator_label2 "rsi up level" #property indicator_type2 DRAW_LINE #property indicator_color2 clrLimeGreen #property indicator_style2 STYLE_DOT #property indicator_label3 "rsi middle level" #property indicator_type3 DRAW_LINE #property indicator_color3 clrSilver #property indicator_style3 STYLE_DOT #property indicator_label4 "rsi down level" #property indicator_type4 DRAW_LINE #property indicator_color4 clrOrange #property indicator_style4 STYLE_DOT #property indicator_label5 "rsi" #property indicator_type5 DRAW_COLOR_LINE #property indicator_color5 clrSilver,clrLimeGreen,clrOrange #property indicator_width5 2 // // // // // 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 }; enum enRsiTypes { rsi_cut, // Cuttler's RSI rsi_ehl, // Ehlers' smoothed RSI rsi_har, // Harris' RSI rsi_rap, // Rapid RSI rsi_rsi, // RSI rsi_rsx, // RSX rsi_slo // Slow RSI }; enum enColorOn { cc_onSlope, // Change color on slope change cc_onMiddle, // Change color on middle line cross cc_onLevels // Change color on outer levels cross }; enum enMaTypes { ma_sma, // Simple moving average ma_ema, // Exponential moving average ma_smma, // Smoothed MA ma_lwma // Linear weighted MA }; input ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT; // Time frame input int RsiPeriod = 14; // Rsi period input enPrices RsiPrice = pr_close; // Price to use input enRsiTypes RsiMethod = rsi_rsi; // Rsi method input int PriceSmoothing = 0; // Price smoothing (<= 1 for no smoothing) input enMaTypes PriceSmoothingM = ma_ema; // Price smoothing method input enColorOn ColorOn = cc_onLevels; // Color change : input int MinMaxPeriod = 50; // Floating levels period (<= 1 for fixed levels) input double LevelUp = 80.0; // Up level % input double LevelDown = 20.0; // Down level % input bool alertsOn = false; // Turn alerts on? input bool alertsOnCurrent = true; // Alert on current bar? input bool alertsMessage = true; // Display messageas on alerts? input bool alertsSound = false; // Play sound on alerts? input bool alertsEmail = false; // Send email on alerts? input bool alertsNotify = false; // Send push notification on alerts? input bool Interpolate = true; // Interpolate mtf data ? double rsi[],rsic[],fill1[],fill2[],levelUp[],levelMi[],levelDn[],count[]; int _mtfHandle = INVALID_HANDLE; ENUM_TIMEFRAMES timeFrame; #define _mtfCall iCustom(_Symbol,timeFrame,getIndicatorName(),PERIOD_CURRENT,RsiPeriod,RsiPrice,RsiMethod,PriceSmoothing,PriceSmoothingM,ColorOn,MinMaxPeriod,LevelUp,LevelDown,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,alertsNotify) //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // int OnInit() { SetIndexBuffer(0,fill1 ,INDICATOR_DATA); SetIndexBuffer(1,fill2 ,INDICATOR_DATA); SetIndexBuffer(2,levelUp,INDICATOR_DATA); SetIndexBuffer(3,levelMi,INDICATOR_DATA); SetIndexBuffer(4,levelDn,INDICATOR_DATA); SetIndexBuffer(5,rsi ,INDICATOR_DATA); SetIndexBuffer(6,rsic ,INDICATOR_COLOR_INDEX); SetIndexBuffer(7,count ,INDICATOR_CALCULATIONS); for (int i=0; i<4; i++) PlotIndexSetInteger(i,PLOT_SHOW_DATA,false); timeFrame = MathMax(_Period,TimeFrame); IndicatorSetString(INDICATOR_SHORTNAME,timeFrameToString(timeFrame)+" "+getRsiName(RsiMethod)+"(oma) ("+(string)RsiPeriod+","+(string)PriceSmoothing+","+(string)MinMaxPeriod+")"); return(0); } //------------------------------------------------------------------ // //------------------------------------------------------------------ // // // // // 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[]) { if (Bars(_Symbol,_Period) 0 && time[i-n] >= currTime[0]; n++) continue; for(k=1; (i-k)>=0 && k=0; k++) { min = MathMin(rsi[i-k],min); max = MathMax(rsi[i-k],max); } double range = max-min; levelUp[i] = min+LevelUp *range/100.0; levelDn[i] = min+LevelDown*range/100.0; levelMi[i] = min+0.5*range; } switch(ColorOn) { case cc_onLevels: rsic[i] = (rsi[i]>levelUp[i]) ? 1 : (rsi[i]levelMi[i]) ? 1 : (rsi[i]0) ? (rsi[i]>rsi[i-1]) ? 1 : (rsi[i]levelUp[i]) ? levelUp[i] : (rsi[i]=0; k++) sum += MathAbs(workRsi[r-k][z+_price]-workRsi[r-k-1][z+_price]); workRsi[r][z+_change] = (workRsi[r][z+_price]-workRsi[0][z+_price])/MathMax(k,1); workRsi[r][z+_changa] = sum/MathMax(k,1); } else { double change = workRsi[r][z+_price]-workRsi[r-1][z+_price]; workRsi[r][z+_change] = workRsi[r-1][z+_change] + alpha*( change - workRsi[r-1][z+_change]); workRsi[r][z+_changa] = workRsi[r-1][z+_changa] + alpha*(MathAbs(change) - workRsi[r-1][z+_changa]); } return(50.0*(workRsi[r][z+_change]/MathMax(workRsi[r][z+_changa],DBL_MIN)+1)); } // // // // // case rsi_slo : { double up = 0, dn = 0; for(int k=0; k<(int)period && (r-k-1)>=0; k++) { double diff = workRsi[r-k][z+_price]- workRsi[r-k-1][z+_price]; if(diff>0) up += diff; else dn -= diff; } if (r<1) workRsi[r][z+_rsival] = 50; else workRsi[r][z+_rsival] = workRsi[r-1][z+_rsival]+(1/MathMax(period,1))*(100*up/MathMax(up+dn,DBL_MIN)-workRsi[r-1][z+_rsival]); return(workRsi[r][z+_rsival]); } // // // // // case rsi_rap : { double up = 0, dn = 0; for(int k=0; k<(int)period && (r-k-1)>=0; k++) { double diff = workRsi[r-k][z+_price]- workRsi[r-k-1][z+_price]; if(diff>0) up += diff; else dn -= diff; } return(100 * up /MathMax(up + dn,DBL_MIN)); } // // // // // case rsi_ehl : { double up = 0, dn = 0; workRsi[r][z+_prices] = (r>2) ? (workRsi[r][z+_price]+2.*workRsi[r-1][z+_price]+workRsi[r-2][z+_price])/4.0 : price; for(int k=0; k<(int)period && (r-k-1)>=0; k++) { double diff = workRsi[r-k][z+_prices]- workRsi[r-k-1][z+_prices]; if(diff>0) up += diff; else dn -= diff; } return(50*(up-dn)/MathMax(up+dn,DBL_MIN)+50); } // // // // // case rsi_cut : { double sump = 0; double sumn = 0; for (int k=0; k<(int)period && (r-k-1)>=0; k++) { double diff = workRsi[r-k][z+_price]-workRsi[r-k-1][z+_price]; if (diff > 0) sump += diff; else sumn -= diff; } workRsi[r][instanceNo+_rsival] = 100.0-100.0/(1.0+sump/MathMax(sumn,DBL_MIN)); return(workRsi[r][instanceNo+_rsival]); } // // // // // case rsi_har : { double avgUp=0,avgDn=0,up=0,dn=0; for(int k=0; k<(int)period && (r-k-1)>=0; k++) { double diff = workRsi[r-k][instanceNo+_price]- workRsi[r-k-1][instanceNo+_price]; if(diff>0) { avgUp += diff; up++; } else { avgDn -= diff; dn++; } } if (up!=0) avgUp /= up; if (dn!=0) avgDn /= dn; workRsi[r][instanceNo+_rsival] = 100-100/(1.0+(avgUp/MathMax(avgDn,DBL_MIN))); return(workRsi[r][instanceNo+_rsival]); } // // // // // case rsi_rsx : { double Kg = (3.0)/(2.0+period), Hg = 1.0-Kg; if (r=pr_haclose) { if (ArrayRange(workHa,0)!= _bars) ArrayResize(workHa,_bars); instanceNo*=_priceInstancesSize; // // // // // double haOpen; if (i>0) haOpen = (workHa[i-1][instanceNo+2] + workHa[i-1][instanceNo+3])/2.0; else haOpen = (open[i]+close[i])/2; double haClose = (open[i] + high[i] + low[i] + close[i]) / 4.0; double haHigh = MathMax(high[i], MathMax(haOpen,haClose)); double haLow = MathMin(low[i] , MathMin(haOpen,haClose)); if(haOpen haOpen) return((haHigh+haClose)/2.0); else return((haLow+haClose)/2.0); case pr_hatbiased2: 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++) workSma[r][instanceNo+1] += workSma[r-k][instanceNo+0]; workSma[r][instanceNo+1] /= 1.0*k; return(workSma[r][instanceNo+1]); } // // // // // 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); } //------------------------------------------------------------------- // //------------------------------------------------------------------- // // // // // string getIndicatorName() { string path = MQL5InfoString(MQL5_PROGRAM_PATH); string data = TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Indicators\\"; string name = StringSubstr(path,StringLen(data)); return(name); } // // // // // int _tfsPer[]={PERIOD_M1,PERIOD_M2,PERIOD_M3,PERIOD_M4,PERIOD_M5,PERIOD_M6,PERIOD_M10,PERIOD_M12,PERIOD_M15,PERIOD_M20,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1,PERIOD_W1,PERIOD_MN1}; string _tfsStr[]={"1 minute","2 minutes","3 minutes","4 minutes","5 minutes","6 minutes","10 minutes","12 minutes","15 minutes","20 minutes","30 minutes","1 hour","2 hours","3 hours","4 hours","6 hours","8 hours","12 hours","daily","weekly","monthly"}; string timeFrameToString(int period) { if (period==PERIOD_CURRENT) period = _Period; int i; for(i=0;i0) { CopyTime(_Symbol,_timeFrame,time[0],1,testTime); SeriesInfoInteger(_Symbol,_timeFrame,SERIES_FIRSTDATE,startTime); } if (startTime<=0 || startTime>time[0]) { Comment(MQL5InfoString(MQL5_PROGRAM_NAME)+"\nMissing data for "+timeFrameToString(_timeFrame)+" time frame\nRe-trying on next tick"); warned=true; return(false); } } if (warned) { Comment(""); warned=false; } return(true); }