//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "www_forex-station_com"

#property indicator_chart_window
#property  indicator_buffers 4
#property  indicator_color1  DimGray
#property  indicator_color2  DimGray
#property  indicator_color3  DeepSkyBlue
#property  indicator_color4  PaleVioletRed
#property  indicator_style1  STYLE_DOT
#property  indicator_style2  STYLE_DOT

//
//
//
//
//

extern int  ChannelPeriod = 150;
extern bool UseHighLow    = false;

//
//
//
//
//

double bufferUp[];
double bufferDn[];
double bufferMiu[];
double bufferMid[];
double prices[];

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   IndicatorBuffers(5);
   SetIndexBuffer(0,bufferMiu);
   SetIndexBuffer(1,bufferMid);
   SetIndexBuffer(2,bufferUp);
   SetIndexBuffer(3,bufferDn);
   SetIndexBuffer(4,prices);
         IndicatorShortName("regression channel ("+ChannelPeriod+")");
   return(0);
}
int deinit() { return(0); }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

double regressionLine[];
int start()
{
   int counted_bars=IndicatorCounted();
   int limit,i,k;
   
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
           limit=MathMin(Bars-counted_bars,Bars-1);
           if (ArraySize(regressionLine)!=ChannelPeriod) ArrayResize(regressionLine,ChannelPeriod);

   //
   //
   //
   //
   //
   
   for(i=limit; i>=0; i--)
   {
      prices[i] = Close[i]; if (i>ChannelPeriod) continue;
      double slope;
      double value = iLRValue(slope,ChannelPeriod,i);
         
         //
         //
         //
         //
         //
         
         double dist = 0;
            for (k=0; k<ChannelPeriod; k++)
            {
               regressionLine[k]=value-k*slope;
               if (UseHighLow)
                     dist = MathMax(dist,MathMax(High[i+k] -regressionLine[k],regressionLine[k]-Low[i+k]));
               else  dist = MathMax(dist,MathMax(Close[i+k]-regressionLine[k],regressionLine[k]-Close[i+k]));
            }
            for (k=0; k<ChannelPeriod; k++)
            {
               bufferDn[i+k]  = regressionLine[k]-dist;
               bufferUp[i+k]  = regressionLine[k]+dist;
               bufferMiu[i+k] = regressionLine[k]+dist*0.3333;
               bufferMid[i+k] = regressionLine[k]-dist*0.3333;
            }
   }
   
   //
   //
   //
   //
   //
 
   int drawBegin = Bars-ChannelPeriod;
         for (k=0; k<4; k++) SetIndexDrawBegin(k,drawBegin);
   return(0);
}


//---------------------------------------------------------------------------------|
//                                                                                 |
//---------------------------------------------------------------------------------|
//
//
//
//
//

int    lr_period=0;
double lr_sumX;
double lr_sumXSqr;
double lr_divisor;

//
//
//
//
//

double iLRValue(double& LinearRegSlope, int len, int shift)
{
   double LinearRegValue;
   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(LinearRegValue);
}

