//+-------------------------------------------------------------------+
//|  Better Bollinger bands 
//|           ORIGINAL CODE BY           mladen |
//+-------------------------------------------------------------------+



//| MODIFIED_VERSION_Better Bollinger bands                                    |
//| MODIFIED BY AVERY T. HORTON, JR. AKA THERUMPLEDONE@GMAIL.COM     |
//| I am NOT the ORIGINAL author 
//  and I am not claiming authorship of this indicator. 
//  All I did was modify it. I hope you find my modifications useful.|
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "mladenfx@gmail.com"

#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Brown
#property indicator_color2 Brown
#property indicator_color3 Brown

extern bool   Sound.Alert    = false ;
extern bool   Show.MidBand   = false ;
extern bool   Show.PriceBox  = true ;

extern int       myBoxWidth  = 3;


extern int    BandsLength    =  20;
extern double BandsDeviation = 2.0; 
extern int    AppliedPrice   = PRICE_CLOSE;



double MaBuffer[];
double UpperBand[];
double LowerBand[];
double tBuffer[][4];


string symbol, tChartPeriod,  tShortName ;  
int    digits, period  ; 

bool Trigger ;

int OldBars = -1 ;


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   period       = Period() ;     
   tChartPeriod =  TimeFrameToString(period) ;
   symbol       =  Symbol() ;
   digits       =  Digits ;   

   tShortName = "tbb"+ symbol + tChartPeriod  ;
    
   SetIndexBuffer(0,UpperBand);
   SetIndexBuffer(1,LowerBand);
   
   if(Show.MidBand) {SetIndexBuffer(2,MaBuffer);}
   

   
   return(0);
}

//+------------------------------------------------------------------+
int deinit()
{
   ObjectDelete(tShortName+"U"); 
   ObjectDelete(tShortName+"L"); 
   ObjectDelete(tShortName+"M"); 
         
   return(0);
}


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

#define iMt1 0
#define iMt2 1
#define iUt1 2
#define iUt2 3

//
//
//
//
//

//+------------------------------------------------------------------+
int start()
{

   
   int    counted_bars=IndicatorCounted();
   int    limit,i,r;


   if( Bars != OldBars ) { Trigger = True ; }
   

   if(counted_bars < 0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit = Bars-counted_bars;
         if (ArrayRange(tBuffer,0) != Bars) ArrayResize(tBuffer,Bars);         
         
   //
   //
   //
   //
   //

   double alpha =  2.0/(BandsLength+1.0);
      for (i=limit, r=Bars-i-1; i>=0; i--,r++)
      {
         double price = iMA(NULL,0,1,0,MODE_SMA,AppliedPrice,i);
         
         //
         //
         //
         //
         //
         
            tBuffer[r][iMt1] = tBuffer[r-1][iMt1] + alpha*(price           -tBuffer[r-1][iMt1]);
            tBuffer[r][iUt1] = tBuffer[r-1][iUt1] + alpha*(tBuffer[r][iMt1]-tBuffer[r-1][iUt1]);
               double dt  = ((2-alpha)*tBuffer[r][iMt1]-tBuffer[r][iUt1])/(1-alpha);
            
            tBuffer[r][iMt2] = tBuffer[r-1][iMt2] + alpha*(MathAbs(price-dt)-tBuffer[r-1][iMt2]);
            tBuffer[r][iUt2] = tBuffer[r-1][iUt2] + alpha*(tBuffer[r][iMt2] -tBuffer[r-1][iUt2]);
               double dt2 = ((2-alpha)*tBuffer[r][iMt2]-tBuffer[r][iUt2])/(1-alpha);

         //
         //
         //
         //
         //
         
         MaBuffer[i]  = dt;
         UpperBand[i] = dt+BandsDeviation*dt2;
         LowerBand[i] = dt-BandsDeviation*dt2;
      }  



//+--------- TRO MODIFICATION ---------------------------------------+  
      
      if ( Trigger &&  Sound.Alert ) 
      {
        if( Close[0] > UpperBand[0] ) { Trigger = False ; Alert(symbol,"  ", tChartPeriod, " Price above UpperBB "+ DoubleToStr(Close[0] ,digits)); }
        if( Close[0] < LowerBand[0] ) { Trigger = False ; Alert(symbol,"  ", tChartPeriod, " Price below LowerBB "+ DoubleToStr(Close[0] ,digits)); }     
      }

   if(Show.PriceBox) { DoBox() ; }
    
   OldBars = Bars ;   

//+--------- TRO MODIFICATION ---------------------------------------+                  
   return(0);
}

//+--------- TRO MODIFICATION ---------------------------------------+  
void DoBox()    
{


       if (ObjectFind(tShortName+"U") != 0)
      {
          ObjectCreate(tShortName+"U",OBJ_ARROW,0,Time[0],UpperBand[0]);
          ObjectSet(tShortName+"U",OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE);
          ObjectSet(tShortName+"U",OBJPROP_COLOR,indicator_color1);  
          ObjectSet(tShortName+"U",OBJPROP_WIDTH,myBoxWidth);  
      } 
      else
      {
         ObjectMove(tShortName+"U",0,Time[0],UpperBand[0]);
         ObjectSet(tShortName+"U",OBJPROP_COLOR,indicator_color1);  
      }

       if (ObjectFind(tShortName+"L") != 0)
      {
          ObjectCreate(tShortName+"L",OBJ_ARROW,0,Time[0],LowerBand[0]);
          ObjectSet(tShortName+"L",OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE);
          ObjectSet(tShortName+"L",OBJPROP_COLOR,indicator_color2);  
          ObjectSet(tShortName+"L",OBJPROP_WIDTH,myBoxWidth);  
      } 
      else
      {
         ObjectMove(tShortName+"L",0,Time[0],LowerBand[0]);
         ObjectSet(tShortName+"L",OBJPROP_COLOR,indicator_color2);  
      }

       if(Show.MidBand) {
       if (ObjectFind(tShortName+"M") != 0)
      {
          ObjectCreate(tShortName+"M",OBJ_ARROW,0,Time[0],MaBuffer[0]);
          ObjectSet(tShortName+"M",OBJPROP_ARROWCODE,SYMBOL_RIGHTPRICE);
          ObjectSet(tShortName+"M",OBJPROP_COLOR,indicator_color3);  
          ObjectSet(tShortName+"M",OBJPROP_WIDTH,myBoxWidth);  
      } 
      else
      {
         ObjectMove(tShortName+"M",0,Time[0],MaBuffer[0]);
         ObjectSet(tShortName+"M",OBJPROP_COLOR,indicator_color3);  
      }
      } //if(Show.MidBand) {


      

                
   return(0);
}


//+--------- TRO MODIFICATION ---------------------------------------+  

string TimeFrameToString(int tf)
{
   string tfs;
   switch(tf) {
      case PERIOD_M1:  tfs="M1"  ; break;
      case PERIOD_M5:  tfs="M5"  ; break;
      case PERIOD_M15: tfs="M15" ; break;
      case PERIOD_M30: tfs="M30" ; break;
      case PERIOD_H1:  tfs="H1"  ; break;
      case PERIOD_H4:  tfs="H4"  ; break;
      case PERIOD_D1:  tfs="D1"  ; break;
      case PERIOD_W1:  tfs="W1"  ; break;
      case PERIOD_MN1: tfs="MN";
   }
   return(tfs);
}



//+--------- TRO MODIFICATION ---------------------------------------+  