Download MetaTrader 5
To add comments, please log in or register
Register at MQL5.community and leave your comments!
gvdraganov
33
gvdraganov 2015.01.08 01:22 

I am trying to recreate the BandWidth indicator for the Bollinger Envelope (not BBands, but Envelope).


I am still struggling with the not normalized version. See code below.


My issue: when trying to draw the line, no line is to be seen. The formula is (UpperBB - lowerBB) / middleBB.


I tested around - if I delete the last part and leave it as (UpperBB - lowerBB), then the line gets drawn. It seems that the division by the buffer seems to mess up everything.


Anyone has an idea?


Code here:


//+------------------------------------------------------------------+
//|                                                        Bands.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              https://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "https://www.mql4.com"
#property description "BandWidth Bollinger Envelopes"
#property strict

#include <MovingAverages.mqh>

#property  indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Gold

//--- indicator parameters
input int    InpBandsPeriod=20;      // Bands Period
input int    InpBandsShift=0;        // Bands Shift
input double InpBandsDeviations=1.5; // Bands Deviations
//--- buffers
double ExtWidthBuffer[];
double ExtMovingBuffer[];
double ExtMAHighBuffer[];
double ExtMALowBuffer[];
double ExtUpperBuffer[];
double ExtLowerBuffer[];
double ExtStdDevHighBuffer[];
double ExtStdDevLowBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//--- 1 additional buffer used for counting.
   IndicatorBuffers(8);
   IndicatorDigits(Digits);
//--- upper band
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtWidthBuffer);
   SetIndexShift(0,InpBandsShift);
   SetIndexLabel(0,"Bands width");
   
   SetIndexBuffer(1,ExtUpperBuffer);
   SetIndexBuffer(2,ExtLowerBuffer);
   SetIndexBuffer(3,ExtMovingBuffer);
   SetIndexBuffer(4,ExtMAHighBuffer);
   SetIndexBuffer(5,ExtMALowBuffer);
   SetIndexBuffer(6,ExtStdDevHighBuffer);
   SetIndexBuffer(7,ExtStdDevLowBuffer);
//--- check for input parameter
   if(InpBandsPeriod<=0)
     {
      Print("Wrong input parameter Bands Period=",InpBandsPeriod);
      return(INIT_FAILED);
     }
//---
   SetIndexDrawBegin(0,InpBandsPeriod+InpBandsShift);
//--- initialization done
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Bollinger Bands                                                  |
//+------------------------------------------------------------------+
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[])
  {
   int i,pos;
//---
   if(rates_total<=InpBandsPeriod || InpBandsPeriod<=0)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtWidthBuffer,false);
   ArraySetAsSeries(ExtMovingBuffer,false);
   ArraySetAsSeries(ExtUpperBuffer,false);
   ArraySetAsSeries(ExtLowerBuffer,false);
   ArraySetAsSeries(ExtStdDevHighBuffer,false);
   ArraySetAsSeries(ExtStdDevLowBuffer,false);
   ArraySetAsSeries(ExtMAHighBuffer,false);
   ArraySetAsSeries(ExtMALowBuffer,false);
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
//--- initial zero
   if(prev_calculated<1)
     {
      for(i=0; i<InpBandsPeriod; i++)
        {
         ExtWidthBuffer[i]=EMPTY_VALUE;
         ExtMovingBuffer[i]=EMPTY_VALUE;
         ExtUpperBuffer[i]=EMPTY_VALUE;
         ExtLowerBuffer[i]=EMPTY_VALUE;
        }
     }
//--- starting calculation
   if(prev_calculated>1)
      pos=prev_calculated-1;
   else
      pos=0;
//--- main cycle
   for(i=pos; i<rates_total && !IsStopped(); i++)
     {
      ExtMAHighBuffer[i]=SimpleMA(i,InpBandsPeriod,high);
      ExtMALowBuffer[i]=SimpleMA(i,InpBandsPeriod,low);
      ExtStdDevHighBuffer[i]=StdDev_Func(i,high,ExtMAHighBuffer,InpBandsPeriod);
      ExtStdDevLowBuffer[i]=StdDev_Func(i,low,ExtMALowBuffer,InpBandsPeriod);
      ExtUpperBuffer[i]=SimpleMA(i,InpBandsPeriod,high)+InpBandsDeviations*ExtStdDevHighBuffer[i];
      ExtLowerBuffer[i]=SimpleMA(i,InpBandsPeriod,low)-InpBandsDeviations*ExtStdDevLowBuffer[i];
      ExtMovingBuffer[i]=(ExtUpperBuffer[i]+ExtLowerBuffer[i])/2;
      

      
      
      //What I want to do is:
      //ExtWidthBuffer[i]=(ExtUpperBuffer[i]-ExtLowerBuffer[i])/ExtMovingBuffer[i];
      //No line drawn on chart and upper and lower limit turn to +/- 90000000.
      //Checked, and all 3 return values.
      //Alert(ExtUpperBuffer[i], " ",ExtLowerBuffer[i], " ",ExtMovingBuffer[i]);
      
      //Simple substracting works though and you can see the line.
      ExtWidthBuffer[i]=(ExtUpperBuffer[i]-ExtLowerBuffer[i]);
      
      
      
      
      //---
     }
    


//---- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Calculate Standard Deviation                                     |
//+------------------------------------------------------------------+
double StdDev_Func(int position,const double &price[],const double &MAprice[],int period)
  {
//--- variables
   double StdDev_dTmp=0.0;
//--- check for position
   if(position>=period)
     {
      //--- calcualte StdDev
      for(int i=0; i<period; i++)
         StdDev_dTmp+=MathPow(price[position-i]-MAprice[position],2);
      StdDev_dTmp=MathSqrt(StdDev_dTmp/period);
     }
//--- return calculated value
   return(StdDev_dTmp);
  }
//+------------------------------------------------------------------+
Keith Watford
Moderator
8028
Keith Watford 2015.01.08 02:58  
Nocciolate:


My issue: when trying to draw the line, no line is to be seen. The formula is (UpperBB - lowerBB) / middleBB.

 It is a zero divide error.

I've not looked too closely at your code, but

      if(ExtMovingBuffer[i]!=0 && ExtMovingBuffer[i]!=EMPTY_VALUE)
         ExtWidthBuffer[i]=(ExtUpperBuffer[i]-ExtLowerBuffer[i])/ExtMovingBuffer[i];

 Will prevent the error

gvdraganov
33
gvdraganov 2015.01.08 17:56  

Hi GumRai,


thanks a lot for looking at it.


I am not quite sure that's the issue. If you exchange the division sign by a multiplication one, you'll get a perfectly working indicator with no places where the value is 0.

Keith Watford
Moderator
8028
Keith Watford 2015.01.08 22:51  
Nocciolate:

I am not quite sure that's the issue. If you exchange the division sign by a multiplication one, you'll get a perfectly working indicator with no places where the value is 0.

Are you sure about that?

try this

      ExtWidthBuffer[i]=(ExtUpperBuffer[i]-ExtLowerBuffer[i])*ExtMovingBuffer[i];
         
      if(ExtWidthBuffer[i]==0)
         Print(i);

 I think that you will see that there are zero values

Did you try my suggestion that I posted? 

/
To add comments, please log in or register