//------------------------------------------------------------------
#property copyright "mladen"
#property link      "www,forex-tsd.com"
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1  LimeGreen
#property indicator_color2  LimeGreen
#property indicator_color3  PaleVioletRed
#property indicator_color4  PaleVioletRed
#property indicator_color5  DarkGray
#property indicator_width1  2
#property indicator_width3  2
#property indicator_width5  2
#property indicator_minimum -50
#property indicator_maximum +50
#property indicator_level1   30
#property indicator_level2  -30
#property indicator_levelcolor DarkGray

//
//
//
//
//

extern int Length    = 14;
extern int Price     = PRICE_CLOSE;
extern int DevPeriod = 14;
extern int AvgPeriod = 14;


//
//
//
//
//

double rsi[];
double rsiHuu[];
double rsiHud[];
double rsiHdd[];
double rsiHdu[];
double slope[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(6);
      SetIndexBuffer(0,rsiHuu); SetIndexStyle(0, DRAW_HISTOGRAM);
      SetIndexBuffer(1,rsiHud); SetIndexStyle(1, DRAW_HISTOGRAM);
      SetIndexBuffer(2,rsiHdd); SetIndexStyle(2, DRAW_HISTOGRAM);
      SetIndexBuffer(3,rsiHdu); SetIndexStyle(3, DRAW_HISTOGRAM);
      SetIndexBuffer(4,rsi);
      SetIndexBuffer(5,slope);
         IndicatorShortName("Adaptive rsi ("+Length+")");
   return(0);
}
int deinit() { return(0); }

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double wrkBuffer[][1];

int start()
{
   int i,r,counted_bars=IndicatorCounted();

   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
         int limit = MathMin(Bars-counted_bars,Bars-1);
         if (ArrayRange(wrkBuffer,0) != Bars) ArrayResize(wrkBuffer,Bars);

   //
   //
   //
   //
   //
   
   for(i=limit, r=Bars-i-1; i>=0; i--, r++)
   {
      wrkBuffer[r][0] = (iMA(NULL,0,1,0,MODE_SMA,Price,i)+2.0*iMA(NULL,0,1,0,MODE_SMA,Price,i+1)+iMA(NULL,0,1,0,MODE_SMA,Price,i+2))/4.0;
      double dev      = iStdDev(NULL,0,DevPeriod,0,MODE_SMA,Price,i);
      double avg      = iSma(dev,AvgPeriod,i);
         if (dev!=0)
               double period = Length*avg/dev;
         else         period = Length; 
         period = MathMax(period,3);
      double cu = 0;
      double cd = 0;
      for (int k=0; k<period; k++) 
      {
            double diff = wrkBuffer[r-k][0]-wrkBuffer[r-k-1][0];
               if (diff > 0) 
                     cu = cu+diff;
               else  cd = cd-diff;
      }
      if ((cu+cd)!=0)
              rsi[i] = 50.0*((cu-cd)/(cu+cd)+1.0)-50;
      else    rsi[i] = 0;
      
      //
      //
      //
      //
      //
      
      rsiHuu[i] = EMPTY_VALUE;
      rsiHud[i] = EMPTY_VALUE;
      rsiHdd[i] = EMPTY_VALUE;
      rsiHdu[i] = EMPTY_VALUE;
      slope[i]  = slope[i+1];
         if (rsi[i]>rsi[i+1]) slope[i] =  1;
         if (rsi[i]<rsi[i+1]) slope[i] = -1;
         if (rsi[i]>0)
         if (slope[i]==1)
               rsiHuu[i] = rsi[i];
         else  rsiHud[i] = rsi[i];
         if (rsi[i]<0)
         if (slope[i]==1)
               rsiHdu[i] = rsi[i];
         else  rsiHdd[i] = rsi[i];
   }
   
   //
   //
   //
   //
   //
   
   return(0);
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//

double workSma[][2];
double iSma(double price, int period, int r, int instanceNo=0)
{
   if (ArrayRange(workSma,0)!= Bars) ArrayResize(workSma,Bars); instanceNo *= 2; r = Bars-r-1;

   //
   //
   //
   //
   //
      
   workSma[r][instanceNo] = price;
   if (r>=period)
          workSma[r][instanceNo+1] = workSma[r-1][instanceNo+1]+(workSma[r][instanceNo]-workSma[r-period][instanceNo])/period;
   else { workSma[r][instanceNo+1] = 0; for(int k=0; k<period && (r-k)>=0; k++) workSma[r][instanceNo+1] += workSma[r-k][instanceNo];  
          workSma[r][instanceNo+1] /= k; }
   return(workSma[r][instanceNo+1]);
}

