//------------------------------------------------------------------
#property copyright "mladen"
#property link      "www.forex-station.com"
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1  clrPaleVioletRed
#property indicator_width1  2
#property indicator_minimum -5
#property indicator_maximum 105
#property indicator_level1  50

extern ENUM_TIMEFRAMES TimeFrame   = PERIOD_CURRENT; // Time frame
input int              period      = 14;
input int              filter      = 15;
input bool             Interpolate = true;           // Interpolate in multi time frame mode

double drsi[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,period,filter,_buff,_ind)

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//

int OnInit()
{
   IndicatorBuffers(2);
   SetIndexBuffer(0,drsi);
   SetIndexBuffer(1,count);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = fmax(TimeFrame,_Period); 
   
   IndicatorShortName(timeFrameToString(TimeFrame)+" DRSI filtered ("+(string)period+")");
return(INIT_SUCCEEDED);
}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workDrsi[][2];
#define _dmp 0
#define _dmm 1
int start()
{
   int i,r,counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
         int limit = fmin(Bars-counted_bars,Bars-1); count[0]=limit;
            if (TimeFrame!=_Period)
            {
               limit = (int)fmax(limit,fmin(Bars-1,_mtfCall(1,0)*TimeFrame/_Period));
               for (i=limit;i>=0 && !_StopFlag; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                     drsi[i] = _mtfCall(0,y);
                  
                     //
                     //
                     //
                     //
                     //
                     
                     if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue;
                        #define _interpolate(buff) buff[i+j] = buff[i]+(buff[i+n]-buff[i])*j/n
                        int n,j; datetime time = iTime(NULL,TimeFrame,y);
                           for(n = 1; (i+n)<Bars && Time[i+n] >= time; n++) continue;	
                           for(j = 1; j<n && (i+n)<Bars && (i+j)<Bars; j++) _interpolate(drsi);                                     
               }
   return(0);
   }
         
   //
   //
   //
   //
   //
   
   if (ArrayRange(workDrsi,0)!=Bars) ArrayResize(workDrsi,Bars);
   for(i=limit, r=Bars-i-1; i>=0; i--,r++)
   {
      double lm = iGflt(Low[i+1]-Low[i],  filter,i,Bars,0);
      double hm = iGflt(High[i]-High[i+1],filter,i,Bars,1);
         if (hm>0 && hm>lm)
               workDrsi[r][_dmp] = hm;
         else  workDrsi[r][_dmp] = 0;
         if (lm>0 && lm>hm)
               workDrsi[r][_dmm] = lm;
         else  workDrsi[r][_dmm] = 0;
      
      //
      //
      //
      //
      //
      
      double dmp = 0;
      double dmm = 0;
      for (int k=0; k<period && (r-k)>=0; k++) { dmp += workDrsi[r-k][_dmp]; dmm += workDrsi[r-k][_dmm]; }
         if (dmm!=0)
               drsi[i] = 100-(100/(1.0+dmp/dmm));
         else  drsi[i] = drsi[i+1];   
   }      
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workGflt[][2];
double iGflt(double price, double per, int i, int bars, int instanceNo=0)
{
   if (per<=1) return(price);
   if (ArrayRange(workGflt,0)!=bars) ArrayResize(workGflt,bars); i = bars-i-1;
   
   //
   //
   //
   //
   //
   
      static double tperiod = 0;
      static double f0      = 0;
      static double f1      = 0;
      static double f2      = 0;
      if (tperiod!=per)
      {
         tperiod = per;
            double an    = 2.0*M_PI/per;
            double beta  = 2.415*(1-cos(an));
            double alpha = -beta + sqrt(beta*beta+2.0*beta);
                      f0 = alpha*alpha;
                      f1 = 2.0*(1.0-alpha);
                      f2 =    -(1.0-alpha)*(1.0-alpha);
      }

   //
   //
   //
   //
   //
   
   if (i<=2)
          workGflt[i][instanceNo] = price;
   else   workGflt[i][instanceNo] = f0*price+f1*workGflt[i-1][instanceNo]+f2*workGflt[i-2][instanceNo];
   return(workGflt[i][instanceNo]);
}

//
//
//
//
//

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("");
}
