//------------------------------------------------------------------
#property copyright "mladen"
#property link      "mladenfx@gmail.com, www.forex-station.com"
//------------------------------------------------------------------

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1  White
#property indicator_width1  3
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1  20
#property indicator_level2  80
#property indicator_levelcolor DarkGray
#property strict


//
//
//
//
//

extern int                 StartFrom      = 6;                    // Starting period
extern int                 EndWith        = 48;                   // Ending period
extern ENUM_APPLIED_PRICE  Price          = PRICE_CLOSE;          // Price
extern int                 BarsToDraw     = 150;                  // No. of bars to draw
extern int                 BarsWidth      = 4;                    // Width of drawn objects
extern string              UniqueID       = "Swami r-square 1";   // Unique ID
extern bool                GenericVisible = true;                 // Generic R-squared value visible?
extern bool                SwamiVisible   = true;                 // Swami zone visible
extern color               ColorUp        = clrForestGreen;       // Color up
extern color               ColorDown      = clrSalmon;            // Color down

double rsq[];
double step;
double totalSteps;
int    window;

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//

int init()
{
   int type = DRAW_NONE; if (GenericVisible) type = DRAW_LINE;
      SetIndexBuffer(0,rsq); SetIndexStyle(0,type);
      
         //
         //
         //
         //
         //
         
         StartFrom  = MathMax(StartFrom, 6);
         EndWith    = MathMin(EndWith  ,99);
         totalSteps = EndWith-StartFrom+1.0;
         step       = 100.0/(totalSteps-1);
      IndicatorShortName(UniqueID);
   return(0);
}

//
//
//
//
//

int deinit()
{
   string lookFor       = UniqueID+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i); if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
      if (counted_bars<0) return(-1);
      if (counted_bars>0) counted_bars--;
         int limit = MathMin(Bars-counted_bars,Bars-1);
         window = WindowFind(UniqueID);

         //
         //
         //
         //
         //

         for (int i=limit, r=Bars-i-1; i>=0 ; i--,r++)
         {
            double price = iMA(NULL,0,1,0,MODE_SMA,Price,i);
            
            //
            //
            //
            //
            //
   
            rsq[i] = 0;         
            for (int k=1; k<EndWith; k++)
            {
               double trsq = 0;
               if (k>=StartFrom)
               {
                  trsq = iRsq(price,k,i,k);
                  if (SwamiVisible && i<BarsToDraw) plot((string)k,(k-StartFrom)*step,(k-StartFrom+1)*step,i,i,gradientColor((int)trsq,100,ColorDown,ColorUp),BarsWidth);
               }
               rsq[i] += trsq;
            }
            rsq[i] = MathMin(MathMax(rsq[i]/totalSteps,0),100);
         }
         
   //
   //
   //
   //
   //

   SetIndexDrawBegin(0,Bars-BarsToDraw);
   return(0);
}


//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

void plot(string namex,double valueA, double valueB, int shiftA, int shiftB, double theColor, int width=0,int style=STYLE_SOLID)
{
   string   name = UniqueID+":"+namex+(string)Time[shiftA];
   
   //
   //
   //
   //
   //
   
   if (ObjectFind(name) == -1) 
   {
       ObjectCreate(name,OBJ_TREND,window,Time[shiftA],valueA,Time[shiftB],valueB);
          ObjectSet(name,OBJPROP_RAY,false);
          ObjectSet(name,OBJPROP_BACK,true);
          ObjectSet(name,OBJPROP_STYLE,style);
          ObjectSet(name,OBJPROP_WIDTH,width);
   }
   ObjectSet(name,OBJPROP_COLOR,theColor);
   ObjectSet(name,OBJPROP_PRICE1,valueA);
   ObjectSet(name,OBJPROP_PRICE2,valueB);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

color gradientColor(int _step, int _totalSteps, color from, color to)
{
   color newBlue  = getColor(_step,_totalSteps,(from & 0XFF0000)>>16,(to & 0XFF0000)>>16)<<16;
   color newGreen = getColor(_step,_totalSteps,(from & 0X00FF00)>> 8,(to & 0X00FF00)>> 8) <<8;
   color newRed   = getColor(_step,_totalSteps,(from & 0X0000FF)    ,(to & 0X0000FF)    )    ;
   return(newBlue+newGreen+newRed);
}
color getColor(int stepNo, int _totalSteps, color from, color to)
{
   double _step = (from-to)/(_totalSteps-1.0);
   return((color)MathRound(from-_step*stepNo));
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

double workr[][100];

double iRsq(double price, double period, int i, int instanceNo=0)
{
   if (ArrayRange(workr,0) != Bars) ArrayResize(workr,Bars); i = Bars-i-1;
  
   //
   //
   //
   //
   //

      workr[i][instanceNo] = price;

         double SumX  = 0;
         double SumXX = 0;
         double SumXY = 0;
         double SumYY = 0;
         double SumY  = 0;
 
                  for(int k=0; k<period && i-k>=0; k++)
                  {
                     double tprice = workr[i-k][instanceNo];
                        SumX  += (k+1); 
                        SumXX += (k+1)*(k+1);
                        SumXY += (k+1)*tprice;
                        SumYY +=       tprice*tprice;
                        SumY  +=       tprice;
                  }
   
         double Q1  = SumXY - SumX*SumY/period;
         double Q2  = SumXX - SumX*SumX/period;
         double Q3  = SumYY - SumY*SumY/period;
         return(100.0*(Q1*Q1)/(Q2*Q3));
}

