Индикаторы: Bollinger Squeeze Basic MT5

 

Bollinger Squeeze Basic MT5:

Индикатор Bollinger Squeeze Basic MetaTrader - комплексный индикатор на основе Momentum, полос Боллинджера и канала Кельтнера. Индикатор строится в отдельном окне графика в виде гистограммы Momentum и ряда точек, показывающих соотношение между текущими значениями полос Боллинджера и канала Кельтнера. Индикатор доступен для версий торговой платформы MT4 и MT5.

Bollinger Squeeze Basic MT5

Author: Tuan Nguyen Van

 
Похоже на тренд и подтверждение в одном индикаторе. Интересно!
 

Привет Спасибо, что поделились кодом вашего индикатора, я попытался преобразовать индикатор Sqeeze Momentum из Trading View, вот код, который у меня есть... он немного отличается... Хотелось бы услышать от вас ответ на этот вопрос! Спасибо.


//+------------------------------------------------------------------------+
//|SqueezeMomentumIndicator.mq5 |
//|Переведено из Pine Script с помощью 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 int    LengthBB = 20;         // Длина ВВ
input double MultBB = 2.0;          // BB MultFactor
input int    LengthKC = 20;         // Длина KC
input double MultKC = 1.5;          // KC MultFactor
input bool   UseTrueRange = true;   // Используйте TrueRange (KC)

//--- индикаторные буферы
double MomentumBuffer[];       // Значения моментов
double MomentumColorBuffer[];  // Моментальные цвета
double SqueezeBuffer[];        // Сжатые значения
double SqueezeColorBuffer[];   // Сдавливание цветов

//+------------------------------------------------------------------+
//| Пользовательская функция инициализации индикатора|
//+------------------------------------------------------------------+
int OnInit()
{
   //--- отображение индикаторных буферов
   SetIndexBuffer(0, MomentumBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, MomentumColorBuffer, INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2, SqueezeBuffer, INDICATOR_DATA);
   SetIndexBuffer(3, SqueezeColorBuffer, INDICATOR_COLOR_INDEX);
   
   //--- установите индексы цветов
   PlotIndexSetInteger(0, PLOT_COLOR_INDEXES, 4); // 4 цвета для гистограммы
   PlotIndexSetInteger(1, PLOT_COLOR_INDEXES, 3); // 3 цвета для линии
   
   //--- установите имя индикатора
   IndicatorSetString(INDICATOR_SHORTNAME, "SQZMOM_LB [LazyBear]");
   
   //--- установить точность
   IndicatorSetInteger(INDICATOR_DIGITS, 5);
   
   //--- установите массивы в качестве серий
   ArraySetAsSeries(MomentumBuffer, true);
   ArraySetAsSeries(MomentumColorBuffer, true);
   ArraySetAsSeries(SqueezeBuffer, true);
   ArraySetAsSeries(SqueezeColorBuffer, true);
   
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Простая скользящая средняя|
//+------------------------------------------------------------------+
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;
}

//+------------------------------------------------------------------+
//| Стандартное отклонение|
//+------------------------------------------------------------------+
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);
}

//+------------------------------------------------------------------+
//| Линейная регрессия|
//+------------------------------------------------------------------+
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;
}

//+------------------------------------------------------------------+
//| Пользовательская функция итерации индикатора|
//+------------------------------------------------------------------+
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 min_bars = MathMax(LengthBB, LengthKC) + 1;
   if(rates_total < min_bars) return(0);
   
   // Установите массивы как серии для правильной индексации
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(close, true);
   
   // Вычислите начальную точку
   int limit;
   if(prev_calculated == 0)
      limit = rates_total - min_bars;
   else
      limit = rates_total - prev_calculated;
   
   limit = MathMin(limit, rates_total - min_bars);
   
   // Подготовьте массивы для расчета источников
   double source[];
   ArrayResize(source, rates_total);
   ArraySetAsSeries(source, true);
   
   // Основной цикл вычислений
   for(int i = limit; i >= 0; i--)
   {
      // Рассчитать полосы Боллинджера
      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;
      
      // Вычислить каналы Кельтнера
      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;
      
      // Рассчитать условия сжатия
      bool sqzOn = (lowerBB > lowerKC) && (upperBB < upperKC);
      bool sqzOff = (lowerBB < lowerKC) && (upperBB > upperKC);
      bool noSqz = !sqzOn && !sqzOff;
      
      // Найдите наибольший максимум и наименьший минимум за период KC
      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];
      }
      
      // Рассчитайте источник для 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;
      }
      
      // Рассчитайте импульс с помощью линейной регрессии
      MomentumBuffer[i] = LinReg(source, LengthKC, i);
      
      // Установите значение линии выдавливания (всегда 0)
      SqueezeBuffer[i] = 0;
      
      // Установите цвета на основе условий точно так же, как в 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; // лайм
            else
               MomentumColorBuffer[i] = 1; // зеленый
         }
         else
         {
            if(MomentumBuffer[i] < MomentumBuffer[i+1])
               MomentumColorBuffer[i] = 2; // красный
            else
               MomentumColorBuffer[i] = 3; // бордовый
         }
      }
      else
      {
         // Для первого бара
         MomentumColorBuffer[i] = (MomentumBuffer[i] > 0) ? 0 : 2; // лайм или красный
      }
      
      // scolor = noSqz ? blue : sqzOn ? black : gray
      if(noSqz)
         SqueezeColorBuffer[i] = 0; // синий
      else if(sqzOn)
         SqueezeColorBuffer[i] = 1; // черный
      else
         SqueezeColorBuffer[i] = 2; // серый
   }
   
   return(rates_total);
}
//+------------------------------------------------------------------+



Файлы: