//+------------------------------------------------------------------+
//|                                               FDI_Indicator.mq4  |
//|                    Fractal Dimension Index + EMA (FDI_MA)        |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2

#property indicator_label1  "FDI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGold
#property indicator_width1  2

#property indicator_label2  "FDI_MA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrDodgerBlue
#property indicator_width2  1

//--- buffers
double fdiBuffer[];
double fdiMABuffer[];

//--- input parameters
input int fdiPeriod = 200;     // FDI calculation period
input int maPeriod  = 10;     // FDI EMA period

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, fdiBuffer);
   SetIndexBuffer(1, fdiMABuffer);

   IndicatorSetInteger(INDICATOR_DIGITS, 3);

   SetIndexLabel(0, "FDI");
   SetIndexLabel(1, "FDI_MA");

   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Fractal Dimension Index Formula                                  |
//+------------------------------------------------------------------+
double CalcFDI(int shift, int period)
{
   double maxDist = 0, sumDist = 0;

   for (int i = 1; i < period; i++)
   {
      double dist = MathAbs(Close[shift] - Close[shift + i]);
      if (dist > maxDist) maxDist = dist;
      if (dist != 0.0) sumDist += dist;
   }

   if (maxDist == 0 || sumDist == 0) return 0;

   double logN = MathLog(period);
   double logR = MathLog(sumDist / (maxDist * period));
   return 1 + logR / logN;
}

//+------------------------------------------------------------------+
//| Main Calculation                                                 |
//+------------------------------------------------------------------+
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 start = MathMax(fdiPeriod, maPeriod);

   for (int i = rates_total - start - 1; i >= 0; i--)
   {
      fdiBuffer[i] = CalcFDI(i, fdiPeriod);
   }

   for (i = rates_total - start - 1; i >= 0; i--)
   {
      fdiMABuffer[i] = iMAOnArray(fdiBuffer, 0, maPeriod, 0, MODE_EMA, i);
   }

   return rates_total;
}
