I developed this indicator to provide an alternative to the standard moving average methods in the MetaTrader 5 Bollinger Bands indicator, which only offer the ‘simple’ method. With my indicator, users have the option to select from additional methods including Exponential, Smoothed, and LinearWeighted.
To utilize this indicator, you need to place it in a directory (on Windows) resembling the following path:
C:\Users\lucas\AppData\Roaming\MetaQuotes\Terminal\Indicators\Examples
Added features:
It is set to zero by default:
Example of execution opting for the average of LinearWeighted:
CODE:
//+------------------------------------------------------------------+ //| BBPersonalizada.mq5 | //| Lucas Vidal | //| | //+------------------------------------------------------------------+ #property copyright "Lucas Vidal" #property link "/en/users/lucasmoura00" #property description "Bollinger Bands Personalizada" #include <MovingAverages.mqh> //--- #property indicator_chart_window #property indicator_buffers 4 #property indicator_plots 3 #property indicator_type1 DRAW_LINE #property indicator_color1 LightSeaGreen #property indicator_type2 DRAW_LINE #property indicator_color2 LightSeaGreen #property indicator_type3 DRAW_LINE #property indicator_color3 LightSeaGreen #property indicator_label1 "Bands middle" #property indicator_label2 "Bands upper" #property indicator_label3 "Bands lower" //--- input parametrs enum MovingAverageMethod { Simple, // 0 Exponential, // 1 Smoothed, // 2 LinearWeighted // 3 }; input MovingAverageMethod InpMaMethod = Simple; // Método da Média Móvel input int InpBandsPeriod=20; // Period input int InpBandsShift=0; // Shift input double InpBandsDeviations=2.0; // Deviation //--- global variables int ExtBandsPeriod,ExtBandsShift; double ExtBandsDeviations; int ExtPlotBegin=0; //--- indicator buffer double ExtMLBuffer[]; double ExtTLBuffer[]; double ExtBLBuffer[]; double ExtStdDevBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ void OnInit() { //--- check for input values if(InpBandsPeriod<2) { ExtBandsPeriod=20; PrintFormat("Incorrect value for input variable InpBandsPeriod=%d. Indicator will use value=%d for calculations.",InpBandsPeriod,ExtBandsPeriod); } else ExtBandsPeriod=InpBandsPeriod; if(InpBandsShift<0) { ExtBandsShift=0; PrintFormat("Incorrect value for input variable InpBandsShift=%d. Indicator will use value=%d for calculations.",InpBandsShift,ExtBandsShift); } else ExtBandsShift=InpBandsShift; if(InpBandsDeviations==0.0) { ExtBandsDeviations=2.0; PrintFormat("Incorrect value for input variable InpBandsDeviations=%f. Indicator will use value=%f for calculations.",InpBandsDeviations,ExtBandsDeviations); } else ExtBandsDeviations=InpBandsDeviations; //--- define buffers SetIndexBuffer(0,ExtMLBuffer); SetIndexBuffer(1,ExtTLBuffer); SetIndexBuffer(2,ExtBLBuffer); SetIndexBuffer(3,ExtStdDevBuffer,INDICATOR_CALCULATIONS); //--- set index labels PlotIndexSetString(0,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Middle"); PlotIndexSetString(1,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Upper"); PlotIndexSetString(2,PLOT_LABEL,"Bands("+string(ExtBandsPeriod)+") Lower"); //--- indicator name IndicatorSetString(INDICATOR_SHORTNAME,"Bollinger Bands"); //--- indexes draw begin settings ExtPlotBegin=ExtBandsPeriod-1; PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtBandsPeriod); PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtBandsPeriod); PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtBandsPeriod); //--- indexes shift settings PlotIndexSetInteger(0,PLOT_SHIFT,ExtBandsShift); PlotIndexSetInteger(1,PLOT_SHIFT,ExtBandsShift); PlotIndexSetInteger(2,PLOT_SHIFT,ExtBandsShift); //--- number of digits of indicator value IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1); } //+------------------------------------------------------------------+ //| Calculate Moving Average | //+------------------------------------------------------------------+ double CalculateMovingAverage(int position, int period, const double &price[]) { switch(InpMaMethod) { case Simple: return SimpleMA(position, period, price); case Exponential: // Corrigindo a chamada da função iMA com os parâmetros corretos return iMA(NULL, 0, period, 0, MODE_EMA, PRICE_CLOSE); case Smoothed: // Implemente sua função SMMA aqui break; case LinearWeighted: return LinearWeightedMA(position, period, price); } return 0; // Retorno padrão em caso de método indefinido } //+------------------------------------------------------------------+ //| Bollinger Bands | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { if(rates_total<ExtPlotBegin) return(0); //--- indexes draw begin settings, when we've recieved previous begin if(ExtPlotBegin!=ExtBandsPeriod+begin) { ExtPlotBegin=ExtBandsPeriod+begin; PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,ExtPlotBegin); PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,ExtPlotBegin); PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,ExtPlotBegin); } //--- starting calculation int pos; if(prev_calculated>1) pos=prev_calculated-1; else pos=0; //--- main cycle for(int i=pos; i<rates_total && !IsStopped(); i++) { //--- middle line ExtMLBuffer[i]=CalculateMovingAverage(i, ExtBandsPeriod, price); //--- calculate and write down StdDev ExtStdDevBuffer[i]=StdDev_Func(i,price,ExtMLBuffer,ExtBandsPeriod); //--- upper line ExtTLBuffer[i]=ExtMLBuffer[i]+ExtBandsDeviations*ExtStdDevBuffer[i]; //--- lower line ExtBLBuffer[i]=ExtMLBuffer[i]-ExtBandsDeviations*ExtStdDevBuffer[i]; } //--- OnCalculate done. Return new prev_calculated. return(rates_total); } //+------------------------------------------------------------------+ //| Calculate Standard Deviation | //+------------------------------------------------------------------+ double StdDev_Func(const int position,const double &price[],const double &ma_price[],const int period) { double std_dev=0.0; //--- calcualte StdDev if(position>=period) { for(int i=0; i<period; i++) std_dev+=MathPow(price[position-i]-ma_price[position],2.0); std_dev=MathSqrt(std_dev/period); } //--- return calculated value return(std_dev); } //+------------------------------------------------------------------+