#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 Yellow
#property indicator_color2 Lime
#property indicator_color3 Lime
#property indicator_color4 Red
#property indicator_color5 Red
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2
#property indicator_width5 2

extern int HMA_Period = 20;
extern int HMA_PriceType = 0;
extern int HMA_Method = 3;
extern bool NormalizeValues = TRUE;
extern int NormalizeDigitsPlus = 2;
extern int VerticalShift = 0;
int gi_100;
double g_ibuf_104[];
double g_ibuf_108[];
double g_ibuf_112[];
double g_ibuf_116[];
double g_ibuf_120[];
double g_ibuf_124[];

int init() {
   gi_100 = MarketInfo(Symbol(), MODE_DIGITS) + NormalizeDigitsPlus;
   IndicatorShortName("HMA(" + HMA_Period + ")");
   IndicatorDigits(gi_100);
   IndicatorBuffers(6);
   SetIndexBuffer(0, g_ibuf_104);
   SetIndexBuffer(1, g_ibuf_108);
   SetIndexBuffer(2, g_ibuf_112);
   SetIndexBuffer(3, g_ibuf_116);
   SetIndexBuffer(4, g_ibuf_120);
   SetIndexBuffer(5, g_ibuf_124);
   int li_0 = HMA_Period + MathFloor(MathSqrt(HMA_Period));
   for (int li_4 = 0; li_4 < 5; li_4++) {
      SetIndexDrawBegin(li_4, li_0);
      SetIndexLabel(li_4, "Hull Moving Average");
   }
   return (0);
}

int start() {
   int l_period_0 = MathFloor(HMA_Period / 2);
   int l_period_4 = MathFloor(MathSqrt(HMA_Period));
   int li_8 = IndicatorCounted();
   if (li_8 < 0) return (-1);
   if (li_8 > 0) li_8--;
   int li_12 = Bars - li_8;
   if (g_ibuf_104[li_12] > g_ibuf_104[li_12 + 1]) CleanPoint(li_12, g_ibuf_108, g_ibuf_112);
   if (g_ibuf_104[li_12] < g_ibuf_104[li_12 + 1]) CleanPoint(li_12, g_ibuf_116, g_ibuf_120);
   for (int li_16 = li_12; li_16 >= 0; li_16--) g_ibuf_124[li_16] = 2.0 * iMA(NULL, 0, l_period_0, 0, HMA_Method, HMA_PriceType, li_16) - iMA(NULL, 0, HMA_Period, 0, HMA_Method, HMA_PriceType, li_16);
   for (li_16 = li_12; li_16 >= 0; li_16--) {
      if (NormalizeValues) g_ibuf_104[li_16] = NormalizeDouble(iMAOnArray(g_ibuf_124, 0, l_period_4, 0, HMA_Method, li_16), gi_100) + VerticalShift * Point;
      else g_ibuf_104[li_16] = iMAOnArray(g_ibuf_124, 0, l_period_4, 0, HMA_Method, li_16) + VerticalShift * Point;
      g_ibuf_108[li_16] = EMPTY_VALUE;
      g_ibuf_112[li_16] = EMPTY_VALUE;
      g_ibuf_116[li_16] = EMPTY_VALUE;
      g_ibuf_120[li_16] = EMPTY_VALUE;
      if (g_ibuf_104[li_16] > g_ibuf_104[li_16 + 1]) PlotPoint(li_16, g_ibuf_108, g_ibuf_112, g_ibuf_104);
      if (g_ibuf_104[li_16] < g_ibuf_104[li_16 + 1]) PlotPoint(li_16, g_ibuf_116, g_ibuf_120, g_ibuf_104);
   }
   return (0);
}

void CleanPoint(int ai_0, double &ada_4[], double &ada_8[]) {
   if (ada_8[ai_0] != EMPTY_VALUE && ada_8[ai_0 + 1] != EMPTY_VALUE) {
      ada_8[ai_0 + 1] = EMPTY_VALUE;
      return;
   }
   if (ada_4[ai_0] != EMPTY_VALUE && ada_4[ai_0 + 1] != EMPTY_VALUE && ada_4[ai_0 + 2] == EMPTY_VALUE) ada_4[ai_0 + 1] = EMPTY_VALUE;
}

void PlotPoint(int ai_0, double &ada_4[], double &ada_8[], double ada_12[]) {
   if (ada_4[ai_0 + 1] == EMPTY_VALUE) {
      if (ada_4[ai_0 + 2] == EMPTY_VALUE) {
         ada_4[ai_0] = ada_12[ai_0];
         ada_4[ai_0 + 1] = ada_12[ai_0 + 1];
         ada_8[ai_0] = EMPTY_VALUE;
         return;
      }
      ada_8[ai_0] = ada_12[ai_0];
      ada_8[ai_0 + 1] = ada_12[ai_0 + 1];
      ada_4[ai_0] = EMPTY_VALUE;
      return;
   }
   ada_4[ai_0] = ada_12[ai_0];
   ada_8[ai_0] = EMPTY_VALUE;
}