//+------------------------------------------------------------------+
//|                                                      BDV.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+

#property copyright "Copyright 2015"
#property link      ""
#property version   "1.00"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_width1 3
#property indicator_level1 0
#property indicator_level2 -30
#property indicator_level3 100
#property indicator_level4 40


extern ENUM_TIMEFRAMES TimeFrame = PERIOD_CURRENT;
extern int             Periods   = 20;
extern int             StartBar  = 1;
extern int             RangeBars = 100;

double PercentVariation[], SimpleVariaton[],AverageSD[],standardError[];
string indicatorFileName;
bool   returnBars;


//------------------------------------------------------------------
//
//------------------------------------------------------------------
int OnInit()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0,PercentVariation);
   SetIndexBuffer(1,AverageSD);
   SetIndexBuffer(2,SimpleVariaton);
   SetIndexBuffer(3,standardError);

      indicatorFileName = WindowExpertName();
      returnBars        = TimeFrame==-99;
      TimeFrame         = MathMax(TimeFrame,_Period);
         IndicatorShortName(timeFrameToString(TimeFrame)+" BStandarError");
   return(INIT_SUCCEEDED);
}

//
//
//
//
//

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); 
         if (returnBars) { PercentVariation[0] = limit+1; return(0); }
         if (TimeFrame != Period())
         {
            limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
            for (int i=limit; i>=0; i--)
            {
               int x = iBarShift(NULL,TimeFrame,Time[i]);               
                  PercentVariation[i]  = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Periods,StartBar,RangeBars,0,x);     
            }
         return(0);                
         }

   //
   //
   //
   //
   //
   
   for (i =limit; i >=0; i--)
   {
      standardError[i] = iStdError(Close[i],Periods,i);
      double sumSDev; int cont;
      for (int y = StartBar; y <= RangeBars+StartBar; y++, cont++)
            sumSDev += standardError[i+y];
   
      if (cont == 0) cont = 1;
   
      AverageSD[i]=sumSDev/cont;
      SimpleVariaton[i]=standardError[i]-AverageSD[i];
      if(AverageSD[i]!=0) 
            PercentVariation[i] = SimpleVariaton[i]/AverageSD[i]*100;
      else  PercentVariation[i]=0;
   }
   return(0);
}

//-------------------------------------------------------------------
//
//-------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

double workErr[][1];

double iStdError(double price, int length,int i, 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(MathSqrt(err2));
   else  return(0.00);       
}