//+------------------------------------------------------------------+ 
//|                                          Smooth Trend.mq4        |
//+------------------------------------------------------------------+

#property version   "1.00"

//--- Draw the indicator on the main chart window
#property indicator_chart_window

//--- Only one indicator buffer is used (for Price)
#property indicator_buffers 1
#property indicator_color1 clrWhite
#property indicator_width1 2
#property indicator_style1 STYLE_SOLID

//--- External input parameters
extern int NormPeriod   = 200; // Lookback period for normalization
extern int SmoothPeriod = 50; // Period for simple moving average smoothing
extern int maxbars = 1000; 

//--- Indicator buffer
double PriceBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   // Ensure the input periods are at least the minimum values
   if(NormPeriod < 2) NormPeriod = 14;
   if(SmoothPeriod < 1) SmoothPeriod = 1;
   
   IndicatorBuffers(1);
   SetIndexBuffer(0, PriceBuffer);
   SetIndexStyle(0, DRAW_LINE);
   SetIndexLabel(0, "Smoothed Price");
   IndicatorShortName("Smoothed Price (" + NormPeriod + ", " + SmoothPeriod + ")");
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator calculation function                            |
//+------------------------------------------------------------------+
int start()
  {
   // Determine how many bars are already calculated
   int counted_bars = IndicatorCounted();
   if(counted_bars < 0)
      return(-1);
   if(counted_bars > 0)
      counted_bars--;  // avoid recalculating the last fully closed bar

   // Limit processing to a maximum of 200 closed bars to reduce resource usage.
   int limitBars = maxbars;
   // The most recent closed bar is at index 1. If there are fewer than 200, process all.
   int firstBar = (Bars - 1 < limitBars ? Bars - 1 : limitBars);

   // Clear the buffer
   for(int i = 0; i < Bars; i++)
      PriceBuffer[i] = EMPTY_VALUE;

   // Loop only through the last 'limitBars' closed bars (from firstBar down to 1)
   for( i = firstBar; i >= 1; i--)
   {
      double sumNormPrice = 0.0;
      
      // For smoothing, average the normalized price over SmoothPeriod bars.
      for(int j = 0; j < SmoothPeriod; j++)
      {
         int index = i + j;
         if(index >= Bars)
            break;
         
         // --- NORMALIZED PRICE ---
         // For bar "index", find the highest high and lowest low over NormPeriod bars.
         int highIndex = iHighest(NULL, 0, MODE_HIGH, NormPeriod, index);
         int lowIndex  = iLowest(NULL, 0, MODE_LOW, NormPeriod, index);
         double maxPrice = High[highIndex];
         double minPrice = Low[lowIndex];
         double rawPrice = 0.5; // default if there is no variation
         if(maxPrice != minPrice)
            rawPrice = (Close[index] - minPrice) / (maxPrice - minPrice);
         
         sumNormPrice += rawPrice;
      }
      
      // Compute the simple moving average of the normalized price values.
      double smoothNormPrice = sumNormPrice / SmoothPeriod;
      
      // --- RESCALE TO PRICE SPACE ---
      // For the current bar i, use the NormPeriod high/low to convert the normalized value
      // back into an actual price value.
      int highIndex_i = iHighest(NULL, 0, MODE_HIGH, NormPeriod, i);
      int lowIndex_i  = iLowest(NULL, 0, MODE_LOW, NormPeriod, i);
      double maxPrice_i = High[highIndex_i];
      double minPrice_i = Low[lowIndex_i];
      
      PriceBuffer[i] = smoothNormPrice * (maxPrice_i - minPrice_i) + minPrice_i;
   }

   // Do not draw the current (forming) bar.
   PriceBuffer[0] = EMPTY_VALUE;
   
   return(0);
  }
//+------------------------------------------------------------------+
