//+------------------------------------------------------------------+
//|                                          bb price on channel.mq4 |
//|                                   Copyright 2016, William Roeder |
//|                                        mailto:WHRoeder@yahoo.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2016, William Roeder"
#property link      "mailto:WHRoeder@yahoo.com"
#property version   "1.00"
#property strict

#property indicator_separate_window
#property indicator_buffers 8

#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrLime
#property indicator_style1  STYLE_SOLID
double abHigh[];

#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
double abLow[];

#property indicator_type3   DRAW_HISTOGRAM
#property indicator_style3  STYLE_SOLID
double hideAbove[];

#property indicator_type4   DRAW_HISTOGRAM
#property indicator_color4  clrLime
#property indicator_style4  STYLE_SOLID
double beHigh[];

#property indicator_type5   DRAW_HISTOGRAM
#property indicator_color5  clrRed
#property indicator_style5  STYLE_SOLID
double beLow[];
#property indicator_type6   DRAW_HISTOGRAM
#property indicator_style6  STYLE_SOLID
double hideBelow[];

#property indicator_type7   DRAW_LINE
#property indicator_color7  clrAqua
#property indicator_style7  STYLE_SOLID
double BBupper[];

#property indicator_level1       0.0
#property indicator_levelcolor   Silver

#property indicator_type8   DRAW_LINE
#property indicator_color8  clrAqua
#property indicator_style8  STYLE_SOLID
double BBlower[];

//--- input parameters
input int                period=20;
input double             deviations=2;
input ENUM_APPLIED_PRICE applied_price=PRICE_CLOSE;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int width=0;
int OnInit(){
   if(period < 1 || deviations <= 0.0) return INIT_PARAMETERS_INCORRECT;
   color bg    = (color) ChartGetInteger(0, CHART_COLOR_BACKGROUND);
   width = (int)   ChartGetInteger(0,CHART_SCALE);
//--- indicator buffers mapping
   SetIndexBuffer(0,abHigh);     SetIndexLabel(0,NULL);
                                 SetIndexStyle(0, DRAW_HISTOGRAM, EMPTY, width);
   SetIndexBuffer(1,abLow);      SetIndexLabel(1,NULL);
                                 SetIndexStyle(1, DRAW_HISTOGRAM, EMPTY, width);
   SetIndexBuffer(2,hideAbove);  SetIndexLabel(2,NULL);
                                 SetIndexStyle(2, DRAW_HISTOGRAM, EMPTY, width, 
                                                  bg);
   SetIndexBuffer(3,beHigh);     SetIndexLabel(3,NULL);
                                 SetIndexStyle(3, DRAW_HISTOGRAM, EMPTY, width);
   SetIndexBuffer(4,beLow);      SetIndexLabel(4,NULL);
                                 SetIndexStyle(4, DRAW_HISTOGRAM, EMPTY, width);
   SetIndexBuffer(5,hideBelow);  SetIndexLabel(5,NULL);
                                 SetIndexStyle(5, DRAW_HISTOGRAM, EMPTY, width, 
                                                  bg);
   SetIndexBuffer(6,BBupper);    SetIndexLabel(6,NULL);
   SetIndexBuffer(7,BBlower);    SetIndexLabel(7,NULL);

      int   digitsPips  = Digits - Digits % 2;
   IndicatorDigits(digitsPips);
//--- set short name
   IndicatorShortName(StringFormat("BBch(%i,%g,%s)", period, deviations,
                                    as_string(applied_price,1)));
//---
   return   INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]){
   if(ChartGetInteger(0,CHART_SCALE) != width)  OnInit();
//---
   #define LOOKBACK period
   int counted = IndicatorCounted();
   for(int iBar = Bars - 1 - MathMax(LOOKBACK, counted); iBar >= 0; --iBar){
      double   ma = iBands(_Symbol,0, period, deviations, 0, applied_price,
                           MODE_MAIN, iBar);
      double   up = iBands(_Symbol,0, period, deviations, 0, applied_price,
                           MODE_UPPER, iBar);
      BBupper[iBar]  = up - ma;
      BBlower[iBar]  = ma - up;
      double   cl    =  Close[iBar] - ma,    op = Open[iBar] - ma,
               hi    =   High[iBar] - ma,    lo =  Low[iBar] - ma;
      abHigh[iBar]   = abLow[iBar]  = hideAbove[iBar] =
      beHigh[iBar]   = beLow[iBar]  = hideBelow[iBar] = EMPTY_VALUE;
      if(hi > 0.0){
         if(op < cl){
            abHigh[iBar]   =  hi;
            hideAbove[iBar]=
            abLow[iBar]    =  MathMax(0.0, lo);
         } else{
            hideAbove[iBar]=
            abHigh[iBar]   =  MathMax(0.0, lo);
            abLow[iBar]    =  hi;
         }
      }
      if(lo < 0.0){
         if(op > cl){
            hideBelow[iBar]=
            beHigh[iBar]   =  MathMin(0.0, hi);
            beLow[iBar]    =  lo;
         } else{
            beHigh[iBar]   =  lo;
            hideBelow[iBar]=
            beLow[iBar]    =  MathMin(0.0, hi);
         }
      }
  }   // for
   return(rates_total);
}
string as_string(ENUM_APPLIED_PRICE p, int len=0){
   string price_XXX = EnumToString(p);
   return StringSubstr(price_XXX, 6, len);
}
//+------------------------------------------------------------------+