Two Hull moving average

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

//|                                      Two Hull moving average.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 5

#property indicator_plots   3

//--- plot Hull Fast

#property indicator_label1  "Hull Fast"

#property indicator_type1   DRAW_COLOR_LINE

#property indicator_color1  clrGray,clrLawnGreen,clrOrangeRed

#property indicator_width1  3

//--- plot Hull Slow

#property indicator_label2  "Hull Slow"

#property indicator_type2   DRAW_COLOR_LINE

#property indicator_color2  clrGray,clrLawnGreen,clrOrangeRed

#property indicator_width2  2

//--- plot Hull Intersection

#property indicator_label3  "Hull Intersection"

#property indicator_type3   DRAW_ARROW

#property indicator_color3  clrBlue

#property indicator_width3  1

//--- input parameters

input group             "Hull moving average Fast"

input int                  Inp_Fast_period      = 20;             // Hull Fast: averaging period

input double               Inp_Fast_divisor     = 2.0;            // Hull Fast: divisor ("speed")

input ENUM_APPLIED_PRICE   Inp_Fast_price       = PRICE_CLOSE;    // Hull Fast: type of price

input group             "Hull moving average Slow"

input int                  Inp_Slow_period      = 10;             // Hull Slow: averaging period

input double               Inp_Slow_divisor     = 2.0;            // Hull Slow: divisor ("speed")

input ENUM_APPLIED_PRICE   Inp_Slow_price       = PRICE_CLOSE;    // Hull Slow: type of price

input group             "Hull Intersection"

input uchar                InpArrowCode         = 117;            // Arrow code "SELL"

input int                  InpArrowShift        = 10;             // Arrow shift "SELL" (vertical shift of in pixels)

//--- indicator buffers

double   HullFastBuffer[];

double   HullFastColors[];

double   HullSlowBuffer[];

double   HullSlowColors[];

double   HullIntersectionBuffer[];

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- indicator buffers mapping

   SetIndexBuffer(0,HullFastBuffer,INDICATOR_DATA);

   SetIndexBuffer(1,HullFastColors,INDICATOR_COLOR_INDEX);

   SetIndexBuffer(2,HullSlowBuffer,INDICATOR_DATA);

   SetIndexBuffer(3,HullSlowColors,INDICATOR_COLOR_INDEX);

   SetIndexBuffer(4,HullIntersectionBuffer,INDICATOR_DATA);

//--- setting a code from the Wingdings charset as the property of PLOT_ARROW

   PlotIndexSetInteger(2,PLOT_ARROW,InpArrowCode);

//--- set the vertical shift of arrows in pixels

   PlotIndexSetInteger(2,PLOT_ARROW_SHIFT,-InpArrowShift);

//--- set an empty value

   PlotIndexSetDouble(2,PLOT_EMPTY_VALUE,0.0);

   //--- line shifts when drawing

   int draw_begin=(Inp_Fast_period>Inp_Slow_period)?Inp_Fast_period:Inp_Slow_period;

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

   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,draw_begin);

   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,draw_begin);

   PlotIndexSetInteger(2,PLOT_DRAW_BEGIN,draw_begin);

//--- initialization of objects of class CHull

   m_hull_fast.init(Inp_Fast_period,Inp_Fast_divisor);

   m_hull_slow.init(Inp_Slow_period,Inp_Slow_divisor);

//--- name for indicator subwindow label

   string short_name=StringFormat("Two Hull moving average(%d,%d)",Inp_Fast_period,Inp_Slow_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)

     {

      HullFastBuffer[0]=0.0;

      HullFastColors[0]=0.0;

      HullSlowBuffer[0]=0.0;

      HullSlowColors[0]=0.0;

      HullIntersectionBuffer[0]=0.0;

      limit=1;

     }

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

     {

      HullFastBuffer[i]=m_hull_fast.calculate(getPrice(Inp_Fast_price,open,high,low,close,i),i,rates_total);

      HullFastColors[i]=(i>0)?(HullFastBuffer[i]>HullFastBuffer[i-1])?1:(HullFastBuffer[i]<HullFastBuffer[i-1])?2:HullFastBuffer[i-1]:0;

      HullSlowBuffer[i]=m_hull_slow.calculate(getPrice(Inp_Slow_price,open,high,low,close,i),i,rates_total);

      HullSlowColors[i]=(i>0)?(HullSlowBuffer[i]>HullSlowBuffer[i-1])?1:(HullSlowBuffer[i]<HullSlowBuffer[i-1])?2:HullSlowBuffer[i-1]:0;

      HullIntersectionBuffer[i]=((HullFastBuffer[i-1]<HullSlowBuffer[i-1]&&HullFastBuffer[i]>HullSlowBuffer[i])||(HullFastBuffer[i-1]>HullSlowBuffer[i-1]&&HullFastBuffer[i]<HullSlowBuffer[i]))?high[i]:0.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_fast;

CHull m_hull_slow;

//---

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