//+------------------------------------------------------------------+ //| ! Reversion Index.mq4 | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "wherever" #property link "wherever" #property indicator_separate_window #property indicator_buffers 6 #property indicator_color1 clrSilver #property indicator_color2 clrDeepSkyBlue #property indicator_color3 clrDeepSkyBlue #property indicator_color4 clrSandyBrown #property indicator_color5 clrSandyBrown #property indicator_color6 clrRed #property indicator_width1 3 #property indicator_width2 3 #property indicator_width3 3 #property indicator_width4 3 #property indicator_width5 3 #property indicator_style6 STYLE_DOT #property strict // // // input int inpLength = 35; // Length input ENUM_APPLIED_PRICE inpPrice = PRICE_CLOSE; // Price to use input double inpSmooth = 35; // Smoothing period input double inpSignal = 10; // Signal period double val[],valUa[],valUb[],valDa[],valDb[],sig[],valc[]; struct sGlobalStruct { double mom,moa,per,sig; int len,lim; }; sGlobalStruct glo; // // // int OnInit() { IndicatorBuffers(7); SetIndexBuffer(0 ,val, INDICATOR_DATA); SetIndexStyle(0 ,DRAW_LINE); SetIndexBuffer(1 ,valUa,INDICATOR_DATA); SetIndexStyle(1 ,DRAW_LINE); SetIndexBuffer(2 ,valUb,INDICATOR_DATA); SetIndexStyle(2 ,DRAW_LINE); SetIndexBuffer(3 ,valDa,INDICATOR_DATA); SetIndexStyle(3 ,DRAW_LINE); SetIndexBuffer(4 ,valDb,INDICATOR_DATA); SetIndexStyle(4 ,DRAW_LINE); SetIndexBuffer(5 ,sig, INDICATOR_DATA); SetIndexStyle(5 ,DRAW_LINE); SetIndexBuffer(6 ,valc,INDICATOR_CALCULATIONS); for(int i=0; i<6; i++) SetIndexLabel(i,NULL); glo.len = fmax(inpLength,1); glo.per = fmax(inpSmooth,1); glo.sig = fmax(inpSignal,1); IndicatorSetString(INDICATOR_SHORTNAME," Reversion Index ("+(string)inpLength+","+DoubleToStr(inpSmooth,2)+","+DoubleToStr(inpSignal,2)+")"); 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[]) { glo.lim = (prev_calculated>0) ? rates_total-prev_calculated : rates_total-1; // // // struct sWrkStruct { double prc,rat; }; static sWrkStruct wrk[]; static int wrkSize = -1; if (wrkSize=0 && !_StopFlag; i--, r++) { wrk[r].prc = iMA(_Symbol,_Period,1,0,MODE_SMA,inpPrice,i); glo.mom = glo.moa = 0; for(int k=0; k=0; k++) { glo.mom += wrk[r-k].prc - wrk[r-k-1].prc; glo.moa += fabs(glo.mom); } wrk[r].rat = (glo.moa!=0.0) ? glo.mom/glo.moa : 0.0; val[i] = iSuperSmoother(wrk[r].rat,glo.per,r,0); sig[i] = iSuperSmoother(val[i] ,glo.sig,r,1); valc[i] = (r>0) ? (val[i]>val[i+1]) ? 1 : (val[i]1 && period>1) { if(ArrayRange(workSsmCoeffs,0)<(instance+1)) { ArrayResize(workSsmCoeffs,instance+1); workSsmCoeffs[instance][_period]=-99; } if(workSsmCoeffs[instance][_period]!=period) { double a1 = MathExp(-1.414*M_PI/period); double b1 = 2.0*a1*MathCos(1.414*M_PI/period); workSsmCoeffs[instance][_c2] = b1; workSsmCoeffs[instance][_c3] = -a1*a1; workSsmCoeffs[instance][_c1] = 1.0 - workSsmCoeffs[instance][_c2] - workSsmCoeffs[instance][_c3]; workSsmCoeffs[instance][_period] = period; } int _indO = (i-2)%_ssmRingSize; int _indP = (i-1)%_ssmRingSize; workSsm[_indC][_inst+_price] = price; workSsm[_indC][_inst+_ssm] = workSsmCoeffs[instance][_c1]*(price+workSsm[_indP][_inst+_price])/2.0 + workSsmCoeffs[instance][_c2]* workSsm[_indP][_inst+_ssm] + workSsmCoeffs[instance][_c3]* workSsm[_indO][_inst+_ssm]; } else for(int k=0; k<_ssmInstancesSize; k++) workSsm[_indC][_inst+k]= price; return(workSsm[_indC][_inst+_ssm]); // // // #undef _period #undef _c1 #undef _c2 #undef _c3 #undef _ssm #undef _price } // // // void iCleanPoint(int i,int bars,double& first[],double& second[]) { if (i>=bars-3) return; if ((second[i] != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE)) second[i+1] = EMPTY_VALUE; else if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE)) first[i+1] = EMPTY_VALUE; } void iPlotPoint(int i,int bars,double& first[],double& second[],double& from[]) { if (i>=bars-2) return; if (first[i+1] == EMPTY_VALUE) if (first[i+2] == EMPTY_VALUE) { first[i] = from[i]; first[i+1] = from[i+1]; second[i] = EMPTY_VALUE; } else { second[i] = from[i]; second[i+1] = from[i+1]; first[i] = EMPTY_VALUE; } else { first[i] = from[i]; second[i] = EMPTY_VALUE; } }