//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1  DeepSkyBlue
#property indicator_color2  PaleVioletRed
#property indicator_color3  DeepSkyBlue
#property indicator_width3  2
#property indicator_style1  STYLE_DOT
#property indicator_style2  STYLE_DOT

//
//
//
//
//

extern int    RsivPeriod             = 30;
extern int    LinearRegressionPeriod = 40;
extern int    VolatilityPeriod       = 7;
extern int    Price                  = PRICE_CLOSE;
extern double BasicLevelUp           = 70;
extern double BasicLevelDown         = 30;

//
//
//
//
//

double bufferUp[];
double bufferDn[];
double bufferMi[];
double prices[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0,bufferUp);
   SetIndexBuffer(1,bufferDn);
   SetIndexBuffer(2,bufferMi);
   SetIndexBuffer(3,prices);
         IndicatorShortName("Rsiv ("+")");
   return(0);
}
int deinit() { return(0); }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//


double work[][7];
#define _diff    0
#define _upScore 1
#define _upDiff  2
#define _dnScore 3
#define _dnDiff  4
#define _lrValue 5
#define _levelMo 6

//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int limit,r,i;
   
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
           limit=MathMin(Bars-counted_bars,Bars-1);
           if (ArrayRange(work,0)!=Bars) ArrayResize(work,Bars);
           

   //
   //
   //
   //
   //
   
   for(i=limit, r=Bars-i-1; i>=0; i--, r++)
   {
      double price = iMA(NULL,0,1,0,MODE_SMA,Price,i);
         work[r][_lrValue] = 3.0*iMA(NULL,0,LinearRegressionPeriod,0,MODE_LWMA,Price,i)-2.0*iMA(NULL,0,LinearRegressionPeriod,0,MODE_SMA,Price,i);
         work[r][_diff]    = price - work[r][_lrValue];
      
      //
      //
      //
      //
      //

         work[r][_upScore] = 0;
         work[r][_upDiff]  = 0;
         work[r][_dnScore] = 0;
         work[r][_dnDiff]  = 0;
            if (work[r][_diff]>work[r-1][_diff])
            {
               work[r][_upScore] = 1; 
               work[r][_upDiff]  = work[r][_diff]-work[r-1][_diff];
            }
            if (work[r][_diff]<work[r-1][_diff])
            {
               work[r][_dnScore] = 1; 
               work[r][_dnDiff]  = work[r-1][_diff]-work[r][_diff];
            }
      
      //
      //
      //
      //
      //
      
         double pos     = 0; 
         double neg     = 0;         
         double posDiff = 0;
         double negDiff = 0;
         for (int k=0; k<RsivPeriod && (r-k)>=0; k++)
         {
            pos += work[r-k][_upScore]; posDiff += work[r-k][_upDiff];
            neg += work[r-k][_dnScore]; negDiff += work[r-k][_dnDiff];
         }
         bufferMi[i] = 100-(100/(1+(pos*posDiff/(neg*negDiff+0.000001))));
      
      //
      //
      //
      //
      //
      
         prices[i] = 100.0*iATR(NULL,0,VolatilityPeriod,i)/iMA(NULL,0,VolatilityPeriod,0,MODE_EMA,Price,i);
         work[r][_levelMo] = prices[i] - iLRSlope(LinearRegressionPeriod,i);
               bufferUp[i] = BasicLevelUp  +work[r-1][_levelMo];
               bufferDn[i] = BasicLevelDown-work[r-1][_levelMo];
   }
   
   //
   //
   //
   //
   //
 
   return(0);
}


//---------------------------------------------------------------------------------|
//                                                                                 |
//---------------------------------------------------------------------------------|
//
//
//
//
//

int    lr_period=0;
double lr_sumX;
double lr_sumXSqr;
double lr_divisor;

//
//
//
//
//

double iLRSlope(int len, int shift)
{
   double LinearRegValue;
   double LinearRegSlope;
   double Intercept;
   double SumXY = 0;
   double SumY  = 0;

   //
   //
   //
   //
   //

   if (lr_period != len)
   {
      lr_period  = len;
      lr_sumX    = lr_period * (lr_period-1) / 2;
      lr_sumXSqr = lr_period * (lr_period-1) * (2 * lr_period - 1) / 6;
      lr_divisor = MathPow(lr_sumX,2) - lr_period * lr_sumXSqr;
   }

   //
   //
   //
   //
   //

   for (int i=0; i<lr_period; i++)
   {
      double price = prices[i+shift];
            SumXY += i*price;
            SumY  +=   price;
   }
   if( lr_divisor != 0 ) 
         	LinearRegSlope = (lr_period * SumXY - lr_sumX * SumY)/lr_divisor;
   else     LinearRegSlope = 0; 
   
   //
   //
   //
   //
   //
   
   Intercept      = (SumY - LinearRegSlope * lr_sumX) / lr_period ;
	LinearRegValue = Intercept  + LinearRegSlope * (lr_period-1);
   return(LinearRegSlope);
}

