//+------------------------------------------------------------------+
//| MFI Normalized Indicator                                          |
//+------------------------------------------------------------------+
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1  clrBlue
#property indicator_levelcolor clrTomato

input int MFI_Periods = 10;
input int BB_Period    = 40;
input int BB_Deviation = 2;

double Normalized[];
double MFI[];

//+------------------------------------------------------------------+
int OnInit()
{
   IndicatorShortName("MFI Normalized");
   IndicatorBuffers(2);

   SetIndexStyle(0, DRAW_LINE);
   SetIndexBuffer(0, Normalized);
   SetIndexLabel(0, "Normalized");

   SetIndexStyle(1, DRAW_NONE);
   SetIndexBuffer(1, MFI);
   SetIndexLabel(1, "MFI");

   SetIndexEmptyValue(0, EMPTY_VALUE);
   SetIndexEmptyValue(1, EMPTY_VALUE);

   SetLevelValue(1, 1.0);
   SetLevelValue(2, 0.0);

   if (MFI_Periods < 1 || BB_Period < 1 || BB_Deviation < 1)
   {
      Alert("MFI Normalized: Invalid input parameters.");
      return INIT_PARAMETERS_INCORRECT;
   }

   return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
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[])
{
   // Minimum bars needed before any output is valid
   int minBars = MFI_Periods + BB_Period + 1;

   if (rates_total < minBars)
      return 0;

   // Calculate how many bars to (re)calculate
   int limit;
   if (prev_calculated <= 0)
      limit = rates_total - MFI_Periods - 1;
   else
      limit = rates_total - prev_calculated + 1;

   // Clamp limit to a safe maximum
   if (limit > rates_total - MFI_Periods - 1)
      limit = rates_total - MFI_Periods - 1;

   // --- Pass 1: fill MFI buffer ---
   // We need MFI populated far enough back for BB to reference it
   int mfiLimit = limit + BB_Period + 1;
   if (mfiLimit > rates_total - MFI_Periods - 1)
      mfiLimit = rates_total - MFI_Periods - 1;

   for (int i = mfiLimit; i >= 0; i--)
   {
      if (i < 0 || i >= rates_total) continue;
      MFI[i] = iMFI(NULL, 0, MFI_Periods, i);
   }

   // --- Pass 2: Normalise using Bollinger Bands on MFI buffer ---
   for (int i = limit; i >= 0; i--)
   {
      if (i < 0 || i >= rates_total) continue;

      double tl = iBandsOnArray(MFI, 0, BB_Period, BB_Deviation, 0, MODE_UPPER, i);
      double bl = iBandsOnArray(MFI, 0, BB_Period, BB_Deviation, 0, MODE_LOWER, i);

      double bandwidth = tl - bl;

      // Avoid division by zero when bands collapse
      if (bandwidth < 1e-10)
      {
         Normalized[i] = EMPTY_VALUE;
         continue;
      }

      Normalized[i] = (MFI[i] - bl) / bandwidth;
   }

   return rates_total;
}
//+------------------------------------------------------------------+