//------------------------------------------------------------------
#property copyright "www.forex-station.com"
#property link      "www.forex-station.com"
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_width1  2
#property indicator_width2  2
#property indicator_width3  2
#property indicator_width4  2
#property strict

//
//
//

input int                Length          = 35;              // Linear regression calculation period
input int                SmoothingLength = 3;               // Smoothing length
input ENUM_APPLIED_PRICE Price           = PRICE_CLOSE;     // Price
input double             BandsRisk       = 1;               // Bands risk
input color              inpColorUp      = clrLimeGreen;    // Color for up
input color              inpColorDn      = clrRed;          // Color for down

double upb[],dnb[],upa[],dna[],zero[],trend[];

//------------------------------------------------------------------
//
//------------------------------------------------------------------

int OnInit()
{
   IndicatorBuffers(6);
   SetIndexBuffer(0,upb, INDICATOR_DATA); SetIndexStyle(0,DRAW_LINE,EMPTY,EMPTY,inpColorUp);
   SetIndexBuffer(1,dnb, INDICATOR_DATA); SetIndexStyle(1,DRAW_LINE,EMPTY,EMPTY,inpColorDn);
   SetIndexBuffer(2,upa, INDICATOR_DATA); SetIndexStyle(2,DRAW_ARROW, EMPTY,EMPTY,inpColorUp); SetIndexArrow(2,159);
   SetIndexBuffer(3,dna, INDICATOR_DATA); SetIndexStyle(3,DRAW_ARROW, EMPTY,EMPTY,inpColorDn); SetIndexArrow(3,159);
   SetIndexBuffer(4,zero,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,trend,INDICATOR_CALCULATIONS);
         
   IndicatorShortName("Std error band stops");
return(INIT_SUCCEEDED);
}  
void OnDeinit(const int reason) {  }

//------------------------------------------------------------------
//
//------------------------------------------------------------------

int OnCalculate (const int       rates_total,
                 const int       prev_calculated,
                 const datetime& btime[],
                 const double&   open[],
                 const double&   high[],
                 const double&   low[],
                 const double&   close[],
                 const long&     tick_volume[],
                 const long&     volume[],
                 const int&      spread[] )
{
   int i,r,k,limit=fmin(rates_total-prev_calculated+1,rates_total-1);
      
   //
   //
   //
   
   struct sSteStruct
   {
     double dev;
     double reg;
     double amax;
     double amin;
     double bmax;
     double bmin;
   };
   static sSteStruct wrk[];
   static int        wrkSize = -1;
                 if (wrkSize<rates_total) wrkSize = ArrayResize(wrk,rates_total+500);
   
   //
   //
   //

   for(i=limit, r=rates_total-limit-1; i>=0; i--,r++)
   {
      wrk[r].reg   = 3.0*iMA(NULL,0,Length,0,MODE_LWMA,Price,i)-2.0*iMA(NULL,0,Length,0,MODE_SMA,Price,i);
      wrk[r].dev   = iStdError(iMA(NULL,0,1,0,MODE_SMA,Price,i),Length,i,rates_total);
      double avglr = wrk[r].reg; for (k=1; k<SmoothingLength && (r-k)>=0; k++) avglr += wrk[r-k].reg; avglr /= k;
      double avger = wrk[r].dev; for (k=1; k<SmoothingLength && (r-k)>=0; k++) avger += wrk[r-k].dev; avger /= k;
         zero[i]     = avglr;
         wrk[r].amax = zero[i]+avger;
         wrk[r].amin = zero[i]-avger;
   	   wrk[r].bmax = wrk[r].amax+0.5*(BandsRisk-1)*(wrk[r].amax-wrk[r].amin);
	  	   wrk[r].bmin = wrk[r].amin-0.5*(BandsRisk-1)*(wrk[r].amax-wrk[r].amin);
         trend[i] = (r>0) ? (close[i]>wrk[r-1].amax) ? 1 : (close[i]<wrk[r-1].amin) ? -1 : trend[i+1] : 0;
         if (r>0)
         {
            if (trend[i]==-1 && wrk[r].amax>wrk[r-1].amax) wrk[r].amax = wrk[r-1].amax;
            if (trend[i]== 1 && wrk[r].amin<wrk[r-1].amin) wrk[r].amin = wrk[r-1].amin;
            if (trend[i]==-1 && wrk[r].bmax>wrk[r-1].bmax) wrk[r].bmax = wrk[r-1].bmax;
            if (trend[i]== 1 && wrk[r].bmin<wrk[r-1].bmin) wrk[r].bmin = wrk[r-1].bmin;
         }                  
         upb[i] = EMPTY_VALUE; dnb[i] = EMPTY_VALUE;
         if (trend[i] ==  1) upb[i] = wrk[r].bmin; 
         if (trend[i] == -1) dnb[i] = wrk[r].bmax; 
           upa[i] = (r>0) ? (trend[i]!=trend[i+1] && trend[i]== 1) ? upb[i] : EMPTY_VALUE :  EMPTY_VALUE;
           dna[i] = (r>0) ? (trend[i]!=trend[i+1] && trend[i]==-1) ? dnb[i] : EMPTY_VALUE :  EMPTY_VALUE;
   }        
return(rates_total);
}

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------

double workErr[][1];

double iStdError(double price, int length,int i, int bars, int forInstance = 0)
{
   if (ArrayRange(workErr,0)!=bars) ArrayResize(workErr,bars);
      int r = bars-i-1; workErr[r][forInstance] = price;
                        
      //
      //
      //
      //
      //
                              
      double avgY     = workErr[r][forInstance]; int j; for (j=1; j<length && (r-j)>=0; j++) avgY += workErr[r-j][forInstance]; avgY /= j;
      double avgX     = length * (length-1) * 0.5 / length;
      double sumDxSqr = 0.00;
      double sumDySqr = 0.00;
      double sumDxDy  = 0.00;
   
      for (int k=0; k<length && (r-k)>=0; k++)
      {
         double dx = k-avgX;
         double dy = workErr[r-k][forInstance]-avgY;
            sumDxSqr += (dx*dx);
            sumDySqr += (dy*dy);
            sumDxDy  += (dx*dy);
      }
      double err2 = (sumDySqr-(sumDxDy*sumDxDy)/sumDxSqr)/(length-2); 
      
   //
   //
   //
         
   if (err2 > 0)
         return(sqrt(err2));
   else  return(0.00);       
}
