Virge of comprehension working with indicators

 

I am taking my first jab at creating indicators on MT5.  My impression is that I can reuse a lot of the functionality of other existing tools.  So my thought here is that I wanted to try and recreate the Bollinger Bandwidth indicator.  Not the bands themselves, just an indicator that displays the difference between the upper and lower bands.  So, the thought here is that all I need to do is to invoke the iBands and get the upper and lower values, copy them into local arrays, then loop through and populate the new indicators array with the value of upper - lower and then have it ploted to the chart.  However my implementation seems to be off.  Here is the code.  I am not asking you to fix it so much as to help me to understand how I miss interpreted or went wrong.

 

//+------------------------------------------------------------------+
//|                                                   BBandwidth.mq5 |
//|                        Copyright Copyright 2010, Investors Haven |
//|                                    http://www.InvestorsHaven.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, Investors Haven"
#property link      "http://www.InvestorsHaven.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot BBBandwidth
#property indicator_label1  "BBandwidth"
#property indicator_type1   DRAW_LINE
#property indicator_color1  Purple
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// --- Inputs
input int     InpBandsPeriod=20;       // Period
input int     InpBandsShift=0;         // Shift
input double  InpBandsDeviations=2.0;  // Deviation

// --- BollingerBand handles
int BBUpperHandle;
int BBLowerHandle;

//--- indicator buffers
double         BBandwidthBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BBandwidthBuffer,INDICATOR_DATA);
   
   
   
   BBUpperHandle = iBands(_Symbol,PERIOD_CURRENT,InpBandsPeriod,InpBandsShift,InpBandsDeviations,PRICE_CLOSE);
   BBLowerHandle = iBands(_Symbol,PERIOD_CURRENT,InpBandsPeriod,InpBandsShift,InpBandsDeviations,PRICE_CLOSE);


   
   

//---
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---

//--- variables
   int pos;
   double upper_band[];
   double lower_band[];
   
   ArraySetAsSeries(lower_band,true);
   ArraySetAsSeries(upper_band,true);
   
   
   //--- check if all data calculated
   if(BarsCalculated(BBUpperHandle)<rates_total) return(0);
   if(BarsCalculated(BBLowerHandle)<rates_total) return(0);
   //--- we can copy not all data
   if(CopyBuffer(BBUpperHandle,1,0,2,upper_band) <=0) return(0);
   if(CopyBuffer(BBLowerHandle,2,0,2,lower_band) <=0) return(0);
   for(int i=pos;i<rates_total;i++)
   {
      BBandwidthBuffer[i] = upper_band[i] - lower_band[i];
      
   }
   
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,BBandwidthBuffer[rates_total]);
      
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
My first assumption is that I may have made it harder than it really should have been.

My next thought is that i should not have attempted to do the for loop. 

Bollinger Bands ®
  • votes: 14
  • 2010.01.26
  • MetaQuotes Software Corp. | English Russian Chinese Spanish Portuguese
  • www.mql5.com
The Bollinger Bands ® Indicator (BB) is similar to Envelopes. The only difference is that the bands of Envelopes are plotted a fixed distance (%) away from the moving average, while the Bollinger Bands are plotted a certain number of standard deviations away from it.
 

I think I got it now, can someone verify?

 

//+------------------------------------------------------------------+
//|                                                   BBandwidth.mq5 |
//|                        Copyright Copyright 2010, Investors Haven |
//|                                    http://www.InvestorsHaven.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, Investors Haven"
#property link      "http://www.InvestorsHaven.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot BBBandwidth
#property indicator_label1  "BBandwidth"
#property indicator_type1   DRAW_LINE
#property indicator_color1  White
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

// --- Inputs
input int     InpBandsPeriod=20;       // Period
input int     InpBandsShift=0;         // Shift
input double  InpBandsDeviations=2.0;  // Deviation

// --- BollingerBand handles
int BBUpperHandle;
int BBLowerHandle;

//--- indicator buffers
double         BBandwidthBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,BBandwidthBuffer,INDICATOR_DATA);
   
   
   
   BBUpperHandle = iBands(_Symbol,PERIOD_CURRENT,InpBandsPeriod,InpBandsShift,InpBandsDeviations,PRICE_CLOSE);
   BBLowerHandle = iBands(_Symbol,PERIOD_CURRENT,InpBandsPeriod,InpBandsShift,InpBandsDeviations,PRICE_CLOSE);


   
   

//---
   return(0);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---

//--- variables
   int pos;
   double upper_band[];
   double lower_band[];
   
   ArraySetAsSeries(lower_band,true);
   ArraySetAsSeries(upper_band,true);
   ArraySetAsSeries(BBandwidthBuffer,true);

   
   
   //--- check if all data calculated
   if(BarsCalculated(BBUpperHandle)<rates_total) return(0);
   if(BarsCalculated(BBLowerHandle)<rates_total) return(0);
   //--- we can copy not all data
   if(CopyBuffer(BBUpperHandle,1,0,rates_total,upper_band) <=0) return(0);
   if(CopyBuffer(BBLowerHandle,2,0,rates_total,lower_band) <=0) return(0);
   for(int i=pos;i<rates_total -1;i++)
   {
      BBandwidthBuffer[i] = MathFloor((upper_band[i] - lower_band[i])/_Point);
   }
   
      
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

 

Reason: