Expert Advisors • Indicators • Scripts • Libraries

MQL.RobotFX.org is the biggest collection of MetaTrader expert advisors (MT5 & MT4), indicators, scripts and libraries that can be used to improve trading results, minimize risks or simply automate trading tasks

MetaTrader 5 Indicator | Custom Bollinger Bands

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:

MetaTrader Experts, Indicators, Scripts and Libraries

It is set to zero by default:

MetaTrader Experts, Indicators, Scripts and Libraries

Example of execution opting for the average of LinearWeighted:

MetaTrader Experts, Indicators, Scripts and Libraries   MetaTrader Experts, Indicators, Scripts and Libraries

CODE:

//+------------------------------------------------------------------+ //|                                              BBPersonalizada.mq5 | //|                                                      Lucas Vidal | //|                                             https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright   "Lucas Vidal" #property link        "https://www.mql5.com/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);   } //+------------------------------------------------------------------+
49464