//+------------------------------------------------------------------ #property copyright "mladen" #property link "mladenfx@gmail.com" #property description "QQE" //+------------------------------------------------------------------ #property indicator_separate_window #property indicator_buffers 4 #property indicator_plots 3 #property indicator_label1 "QQE fast" #property indicator_type1 DRAW_LINE #property indicator_color1 clrDarkGray #property indicator_style1 STYLE_DOT #property indicator_label2 "QQE slow" #property indicator_type2 DRAW_LINE #property indicator_color2 clrDarkGray #property indicator_label3 "QQE" #property indicator_type3 DRAW_COLOR_LINE #property indicator_color3 clrDarkGray,clrDeepSkyBlue,clrLightSalmon #property indicator_width3 2 //--- input parameters input int inpRsiPeriod = 14; // RSI period input int inpRsiSmoothingFactor = 5; // RSI smoothing factor input double inpWPFast = 2.618; // Fast period input double inpWPSlow = 4.236; // Slow period input ENUM_APPLIED_PRICE inpPrice=PRICE_CLOSE; // Price //--- buffers declarations double val[],valc[],levs[],levf[]; // #include // //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,levf,INDICATOR_DATA); SetIndexBuffer(1,levs,INDICATOR_DATA); SetIndexBuffer(2,val,INDICATOR_DATA); SetIndexBuffer(3,valc,INDICATOR_COLOR_INDEX); //--- indicator short name assignment IndicatorSetString(INDICATOR_SHORTNAME,"QQE ("+(string)inpRsiPeriod+","+(string)inpRsiSmoothingFactor+")"); //--- return (INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator de-initialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| 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[]) { if(!customChartIndicator.OnCalculate(rates_total,prev_calculated,time,close)) return(0); if(!customChartIndicator.BufferSynchronizationCheck(close)) return(0); int _prev_calculated = customChartIndicator.GetPrevCalculated(); /// if(Bars(_Symbol,_Period)0 ? MathAbs(val[i-1]-val[i]) : 0),inpRsiPeriod,i,rates_total,1); double _iEmm = iEma( _iEma,inpRsiPeriod,i,rates_total,2); double _iEmf = _iEmm*inpWPFast; double _iEms = _iEmm*inpWPSlow; // //--- // { double tr = (i>0) ? levs[i-1] : 0; double dv = tr; if(val[i] < tr) { tr = val[i] + _iEms; if((i>0 && val[i-1] < dv) && (tr > dv)) tr = dv; } if(val[i] > tr) { tr = val[i] - _iEms; if((i>0 && val[i-1] > dv) && (tr < dv)) tr = dv; } levs[i]=tr; } { double tr = (i>0) ? levf[i-1] : 0; double dv = tr; if(val[i] < tr) { tr = val[i] + _iEmf; if((i>0 && val[i-1] < dv) && (tr > dv)) tr = dv; } if(val[i] > tr) { tr = val[i] - _iEmf; if((i>0 && val[i-1] > dv) && (tr < dv)) tr = dv; } levf[i]=tr; } valc[i]=(val[i]>levf[i] && val[i]>levs[i]) ? 1 :(val[i]0) ? valc[i-1]: 0; } return (i); } //+------------------------------------------------------------------+ //| Custom functions | //+------------------------------------------------------------------+ #define rsiInstances 1 #define rsiInstancesSize 3 double workRsi[][rsiInstances*rsiInstancesSize]; #define _price 0 #define _change 1 #define _changa 2 // //--- // double iRsi(double price,double period,int r,int bars,int instanceNo=0) { if(ArrayRange(workRsi,0)!=bars) ArrayResize(workRsi,bars); int z=instanceNo*rsiInstancesSize; // // // // // workRsi[r][z+_price]=price; if(r=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 alpha=1.0/MathMax(period,1); 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)); } // //--- // double workEma[][3]; // //--- // 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 getPrice(ENUM_APPLIED_PRICE tprice,const double &open[],const double &close[],const double &high[],const double &low[],int i,int _bars) { switch(tprice) { case PRICE_CLOSE: return(close[i]); case PRICE_OPEN: return(open[i]); case PRICE_HIGH: return(high[i]); case PRICE_LOW: return(low[i]); case PRICE_MEDIAN: return((high[i]+low[i])/2.0); case PRICE_TYPICAL: return((high[i]+low[i]+close[i])/3.0); case PRICE_WEIGHTED: return((high[i]+low[i]+close[i]+close[i])/4.0); } return(0); } //+------------------------------------------------------------------+