Hull moving average Channel

Author: Copyright © 2021, Vladimir Karputov
0 Views
0 Downloads
0 Favorites
Hull moving average Channel
ÿþ//+------------------------------------------------------------------+

//|                                  Hull moving average Channel.mq5 |

//|                              Copyright © 2021, Vladimir Karputov |

//|                     https://www.mql5.com/ru/market/product/43161 |

//+------------------------------------------------------------------+

#property copyright "Copyright © 2021, Vladimir Karputov"

#property link      "https://www.mql5.com/ru/market/product/43161"

#property version   "1.000"

#property description "The original code is taken from: https://www.mql5.com/en/code/25257"

#property indicator_chart_window

#property indicator_buffers 4

#property indicator_plots   2

//--- plot Hull High

#property indicator_label1  "Hull High"

#property indicator_type1   DRAW_COLOR_LINE

#property indicator_color1  clrNONE,clrBlue,clrRed

#property indicator_width1  3

//--- plot Hull Low

#property indicator_label2  "Hull Low"

#property indicator_type2   DRAW_COLOR_LINE

#property indicator_color2  clrNONE,clrBlue,clrRed

#property indicator_width2  3

//--- input parameters

input group             "Hull moving average"

input int                  Inp_period           = 20;             // Averaging period

input double               Inp_divisor          = 2.0;            // Divisor ("speed")

//--- indicator buffers

double   HullHighBuffer[];

double   HullHighColors[];

double   HullLowBuffer[];

double   HullLowColors[];

//+------------------------------------------------------------------+

//| Custom indicator initialization function                         |

//+------------------------------------------------------------------+

int OnInit()

  {

//--- indicator buffers mapping

   SetIndexBuffer(0,HullHighBuffer,INDICATOR_DATA);

   SetIndexBuffer(1,HullHighColors,INDICATOR_COLOR_INDEX);

   SetIndexBuffer(2,HullLowBuffer,INDICATOR_DATA);

   SetIndexBuffer(3,HullLowColors,INDICATOR_COLOR_INDEX);

//--- line shifts when drawing

   int draw_begin=Inp_period;

//--- set first bar from what index will be drawn

   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,draw_begin);

   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,draw_begin);

//--- initialization of objects of class CHull

   m_hull_high.init(Inp_period,Inp_divisor);

   m_hull_low.init(Inp_period,Inp_divisor);

//--- name for indicator subwindow label

   string short_name=StringFormat("Hull moving Channel(%d)",Inp_period);

   IndicatorSetString(INDICATOR_SHORTNAME,short_name);

//---

   return (INIT_SUCCEEDED);

  }

//+------------------------------------------------------------------+

//| Indicator deinitialization function                              |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

  {

//---

  }

//+------------------------------------------------------------------+

//| 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[])

  {

   int limit=prev_calculated-1;

   if(prev_calculated==0)

     {

      HullHighBuffer[0]=0.0;

      HullHighColors[0]=0.0;

      HullLowBuffer[0]=0.0;

      HullLowColors[0]=0.0;

      limit=1;

     }

   for(int i=limit; i<rates_total && !_StopFlag; i++)

     {

      HullHighBuffer[i]=m_hull_high.calculate(getPrice(PRICE_HIGH,open,high,low,close,i),i,rates_total);

      HullHighColors[i]=(i>0)?(HullHighBuffer[i]>HullHighBuffer[i-1])?1:(HullHighBuffer[i]<HullHighBuffer[i-1])?2:HullHighBuffer[i-1]:0;

      HullLowBuffer[i]=m_hull_low.calculate(getPrice(PRICE_LOW,open,high,low,close,i),i,rates_total);

      HullLowColors[i]=(i>0)?(HullLowBuffer[i]>HullLowBuffer[i-1])?1:(HullLowBuffer[i]<HullLowBuffer[i-1])?2:HullLowBuffer[i-1]:0;

     }

   return(rates_total);

  }

//+------------------------------------------------------------------+

//| Class CHull                                                      |

//+------------------------------------------------------------------+

class CHull

  {

private :

   int               m_fullPeriod;

   int               m_halfPeriod;

   int               m_sqrtPeriod;

   int               m_arraySize;

   double            m_weight1;

   double            m_weight2;

   double            m_weight3;

   struct sHullArrayStruct

     {

      double         value;

      double         value3;

      double         wsum1;

      double         wsum2;

      double         wsum3;

      double         lsum1;

      double         lsum2;

      double         lsum3;

     };

   sHullArrayStruct  m_array[];



public :

                     CHull() : m_fullPeriod(1), m_halfPeriod(1), m_sqrtPeriod(1), m_arraySize(-1) {                     }

                    ~CHull()                                                                      { ArrayFree(m_array); }

   //+------------------------------------------------------------------+

   //| init                                                             |

   //+------------------------------------------------------------------+

   bool              init(int period, double divisor)

     {

      m_fullPeriod = (int)(period>1 ? period : 1);

      m_halfPeriod = (int)(m_fullPeriod>1 ? m_fullPeriod/(divisor>1 ? divisor : 1) : 1);

      m_sqrtPeriod = (int) MathSqrt(m_fullPeriod);

      m_arraySize  = -1;

      m_weight1 = m_weight2 = m_weight3 = 1;

      return(true);

     }

   //+------------------------------------------------------------------+

   //| calculate                                                        |

   //+------------------------------------------------------------------+

   double            calculate(double value, int i, int bars)

     {

      if(m_arraySize<bars)

        {

         m_arraySize = ArrayResize(m_array,bars+500);

         if(m_arraySize<bars)

            return(0);

        }

      //---

      m_array[i].value=value;

      if(i>m_fullPeriod)

        {

         m_array[i].wsum1 = m_array[i-1].wsum1+value*m_halfPeriod-m_array[i-1].lsum1;

         m_array[i].lsum1 = m_array[i-1].lsum1+value-m_array[i-m_halfPeriod].value;

         m_array[i].wsum2 = m_array[i-1].wsum2+value*m_fullPeriod-m_array[i-1].lsum2;

         m_array[i].lsum2 = m_array[i-1].lsum2+value-m_array[i-m_fullPeriod].value;

        }

      else

        {

         m_array[i].wsum1 = m_array[i].wsum2 =m_array[i].lsum1 = m_array[i].lsum2 = m_weight1 = m_weight2 = 0;

         for(int k=0, w1=m_halfPeriod, w2=m_fullPeriod; w2>0 && i>=k; k++, w1--, w2--)

           {

            if(w1>0)

              {

               m_array[i].wsum1 += m_array[i-k].value*w1;

               m_array[i].lsum1 += m_array[i-k].value;

               m_weight1        += w1;

              }

            m_array[i].wsum2 += m_array[i-k].value*w2;

            m_array[i].lsum2 += m_array[i-k].value;

            m_weight2        += w2;

           }

        }

      m_array[i].value3=2.0*m_array[i].wsum1/m_weight1-m_array[i].wsum2/m_weight2;

      //---

      if(i>m_sqrtPeriod)

        {

         m_array[i].wsum3 = m_array[i-1].wsum3+m_array[i].value3*m_sqrtPeriod-m_array[i-1].lsum3;

         m_array[i].lsum3 = m_array[i-1].lsum3+m_array[i].value3-m_array[i-m_sqrtPeriod].value3;

        }

      else

        {

         m_array[i].wsum3 =

            m_array[i].lsum3 = m_weight3 = 0;

         for(int k=0, w3=m_sqrtPeriod; w3>0 && i>=k; k++, w3--)

           {

            m_array[i].wsum3 += m_array[i-k].value3*w3;

            m_array[i].lsum3 += m_array[i-k].value3;

            m_weight3        += w3;

           }

        }

      return(m_array[i].wsum3/m_weight3);

     }

  };

//---

CHull m_hull_high;

CHull m_hull_low;

//---

template <typename T>

double getPrice(ENUM_APPLIED_PRICE tprice, T& open[], T& high[], T& low[], T& close[], int i)

  {

   switch(tprice)

     {

      case PRICE_CLOSE:

         return(close[i]);

      case PRICE_OPEN:

         return(open[i]);

      case PRICE_HIGH:

         return(high[i]);

      case PRICE_LOW:

         return(low[i]);

      case PRICE_MEDIAN:

         return((high[i]+low[i])/2.0);

      case PRICE_TYPICAL:

         return((high[i]+low[i]+close[i])/3.0);

      case PRICE_WEIGHTED:

         return((high[i]+low[i]+close[i]+close[i])/4.0);

     }

   return(0);

  }

//------------------------------------------------------------------

Comments