Indicators: Bollinger Squeeze Basic MT5

 

Bollinger Squeeze Basic MT5:

Bollinger Squeeze Basic MetaTrader indicator — is a complex indicator based on Momentum, Bollinger bands, and Keltner channel. The indicator is drawn in the separate window of the chart as a Momentum histogram and a range of dots when show the relationship between the current Bollinger bands and Keltner channel values. This indicator is available for both MT4 and MT5 versions of the trading platform.

Bollinger Squeeze Basic MT5

Author: Tuan Nguyen Van

 
Sound like a trend and confirmation in the same indicator. interesting!
 

Hi Thanks for sharing your Indicator code, I tried to convert the Sqeeze Momentum Indicator from Trading View, here is the code I have.. it is bit different.. Would like to hear from you on this! Thanks. 


//+------------------------------------------------------------------------+
//|                                     SqueezeMomentumIndicator.mq5 |
//|                           Converted from Pine Script by LazyBear |
//|                                                                                       |
//+------------------------------------------------------------------------+
#property copyright "Converted from Pine Script by LazyBear"
#property link      ""
#property version   "1.02"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   2
#property indicator_type1   DRAW_COLOR_HISTOGRAM
#property indicator_color1  clrLime, clrGreen, clrRed, clrMaroon
#property indicator_style1  STYLE_SOLID
#property indicator_width1  4
#property indicator_label1  "Squeeze Momentum"
#property indicator_type2   DRAW_COLOR_LINE
#property indicator_color2  clrBlue, clrBlack, clrGray
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
#property indicator_label2  "Squeeze"

//--- input parameters
input int    LengthBB = 20;         // BB Length
input double MultBB = 2.0;          // BB MultFactor
input int    LengthKC = 20;         // KC Length
input double MultKC = 1.5;          // KC MultFactor
input bool   UseTrueRange = true;   // Use TrueRange (KC)

//--- indicator buffers
double MomentumBuffer[];       // Momentum values
double MomentumColorBuffer[];  // Momentum colors
double SqueezeBuffer[];        // Squeeze values
double SqueezeColorBuffer[];   // Squeeze colors

//+------------------------------------------------------------------+
//| Custom indicator initialization function                          |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   SetIndexBuffer(0, MomentumBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, MomentumColorBuffer, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2, SqueezeBuffer, INDICATOR_DATA);
   SetIndexBuffer(3, SqueezeColorBuffer, INDICATOR_COLOR_INDEX);
   
   //--- set color indexes
   PlotIndexSetInteger(0, PLOT_COLOR_INDEXES, 4); // 4 colors for histogram
   PlotIndexSetInteger(1, PLOT_COLOR_INDEXES, 3); // 3 colors for line
   
   //--- set indicator name
   IndicatorSetString(INDICATOR_SHORTNAME, "SQZMOM_LB [LazyBear]");
   
   //--- set precision
   IndicatorSetInteger(INDICATOR_DIGITS, 5);
   
   //--- set arrays as series
   ArraySetAsSeries(MomentumBuffer, true);
   ArraySetAsSeries(MomentumColorBuffer, true);
   ArraySetAsSeries(SqueezeBuffer, true);
   ArraySetAsSeries(SqueezeColorBuffer, true);
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Simple Moving Average                                             |
//+------------------------------------------------------------------+
double SimpleMA(const double &price[], int period, int shift)
{
   double sum = 0.0;
   for(int i = 0; i < period; i++)
   {
      sum += price[shift + i];
   }
   return sum / period;
}

//+------------------------------------------------------------------+
//| Standard Deviation                                                |
//+------------------------------------------------------------------+
double StdDev(const double &price[], int period, int shift)
{
   double avg = SimpleMA(price, period, shift);
   double sum = 0.0;
   
   for(int i = 0; i < period; i++)
   {
      sum += MathPow(price[shift + i] - avg, 2);
   }
   
   return MathSqrt(sum / period);
}

//+------------------------------------------------------------------+
//| Linear Regression                                                 |
//+------------------------------------------------------------------+
double LinReg(const double &price[], int period, int shift)
{
   double sum_x = 0.0;
   double sum_y = 0.0;
   double sum_xy = 0.0;
   double sum_x2 = 0.0;
   
   for(int i = 0; i < period; i++)
   {
      sum_x += i;
      sum_y += price[shift + i];
      sum_xy += i * price[shift + i];
      sum_x2 += i * i;
   }
   
   double m = period;
   double slope = (m * sum_xy - sum_x * sum_y) / (m * sum_x2 - sum_x * sum_x);
   double intercept = (sum_y - slope * sum_x) / m;
   
   return intercept;
}

//+------------------------------------------------------------------+
//| 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[])
{
   // Check for minimum data
   int min_bars = MathMax(LengthBB, LengthKC) + 1;
   if(rates_total < min_bars) return(0);
   
   // Set arrays as series for proper indexing
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(close, true);
   
   // Calculate start point
   int limit;
   if(prev_calculated == 0)
      limit = rates_total - min_bars;
   else
      limit = rates_total - prev_calculated;
   
   limit = MathMin(limit, rates_total - min_bars);
   
   // Prepare arrays for source calculation
   double source[];
   ArrayResize(source, rates_total);
   ArraySetAsSeries(source, true);
   
   // Main calculation loop
   for(int i = limit; i >= 0; i--)
   {
      // Calculate Bollinger Bands
      double basis = 0.0;
      for(int j = 0; j < LengthBB; j++)
         basis += close[i+j];
      basis /= LengthBB;
      
      double dev = 0.0;
      for(int j = 0; j < LengthBB; j++)
         dev += MathPow(close[i+j] - basis, 2);
      dev = MultBB * MathSqrt(dev / LengthBB);
      
      double upperBB = basis + dev;
      double lowerBB = basis - dev;
      
      // Calculate Keltner Channels
      double ma = 0.0;
      for(int j = 0; j < LengthKC; j++)
         ma += close[i+j];
      ma /= LengthKC;
      
      double range_sum = 0.0;
      for(int j = 0; j < LengthKC; j++)
      {
         double tr;
         if(UseTrueRange && i+j+1 < rates_total)
            tr = MathMax(high[i+j] - low[i+j], 
                 MathMax(MathAbs(high[i+j] - close[i+j+1]), 
                         MathAbs(low[i+j] - close[i+j+1])));
         else
            tr = high[i+j] - low[i+j];
         
         range_sum += tr;
      }
      double range_ma = range_sum / LengthKC;
      
      double upperKC = ma + MultKC * range_ma;
      double lowerKC = ma - MultKC * range_ma;
      
      // Calculate squeeze conditions
      bool sqzOn = (lowerBB > lowerKC) && (upperBB < upperKC);
      bool sqzOff = (lowerBB < lowerKC) && (upperBB > upperKC);
      bool noSqz = !sqzOn && !sqzOff;
      
      // Find highest high and lowest low for KC period
      double highest = high[i];
      double lowest = low[i];
      
      for(int j = 1; j < LengthKC; j++)
      {
         if(i+j >= rates_total) break;
         if(high[i+j] > highest) highest = high[i+j];
         if(low[i+j] < lowest) lowest = low[i+j];
      }
      
      // Calculate source for linreg
      double avg_hl = (highest + lowest) / 2;
      double avg_val = (avg_hl + ma) / 2;
      
      for(int j = 0; j < LengthKC; j++)
      {
         if(i+j >= rates_total) break;
         source[i+j] = close[i+j] - avg_val;
      }
      
      // Calculate momentum with linear regression
      MomentumBuffer[i] = LinReg(source, LengthKC, i);
      
      // Set squeeze line value (always 0)
      SqueezeBuffer[i] = 0;
      
      // Set colors based on conditions exactly as in Pine Script
      // bcolor = iff(val > 0, iff(val > nz(val[1]), lime, green), iff(val < nz(val[1]), red, maroon))
      if(i < rates_total - 1)
      {
         if(MomentumBuffer[i] > 0)
         {
            if(MomentumBuffer[i] > MomentumBuffer[i+1])
               MomentumColorBuffer[i] = 0; // lime
            else
               MomentumColorBuffer[i] = 1; // green
         }
         else
         {
            if(MomentumBuffer[i] < MomentumBuffer[i+1])
               MomentumColorBuffer[i] = 2; // red
            else
               MomentumColorBuffer[i] = 3; // maroon
         }
      }
      else
      {
         // For the first bar
         MomentumColorBuffer[i] = (MomentumBuffer[i] > 0) ? 0 : 2; // lime or red
      }
      
      // scolor = noSqz ? blue : sqzOn ? black : gray
      if(noSqz)
         SqueezeColorBuffer[i] = 0; // blue
      else if(sqzOn)
         SqueezeColorBuffer[i] = 1; // black
      else
         SqueezeColorBuffer[i] = 2; // gray
   }
   
   return(rates_total);
}
//+------------------------------------------------------------------+



Files: