//+------------------------------------------------------------------+
//|                                ATR_Adjusted_GainLoss_EMA_Mid.mq5 |
//|                                                  Helpful AI Team |
//+------------------------------------------------------------------+
#property copyright "https://forex-station.com/"
#property version   "1.10"
#property description "Belongs to Forex Station"

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   3

//--- Plot 1: Bull Power (Adjusted Gain)
#property indicator_label1  "Bull Power (Gain)"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrLime
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

//--- Plot 2: Bear Power (Adjusted Loss)
#property indicator_label2  "Bear Power (Loss)"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

//--- Plot 3: EMA Midline
#property indicator_label3  "EMA Midline"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrBlack
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1

//--- Inputs
input string spacer1 = "--- Core Periods ---";
input int    InpRSIPeriod     = 14;    // Gain/Loss Smoothing Period (Wilder's)
input int    InpATRPeriod     = 14;    // ATR Normalization Period
input int    InpEMAMidPeriod  = 14;    // Midline EMA Period

input string spacer2 = "--- Visuals ---";
input double InpScaleMult     = 100.0; // Scale Multiplier (keeps numbers readable)

//--- Indicator Buffers
double BufferGain[];
double BufferLoss[];
double BufferMid[];
double BufferRawMid[]; // Hidden buffer for math

//--- Handles
int atrHandle;
double atrArray[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   // Set up indicator buffers
   SetIndexBuffer(0, BufferGain, INDICATOR_DATA);
   SetIndexBuffer(1, BufferLoss, INDICATOR_DATA);
   SetIndexBuffer(2, BufferMid, INDICATOR_DATA);
   SetIndexBuffer(3, BufferRawMid, INDICATOR_CALCULATIONS);
   
   // Note: We DO NOT use ArraySetAsSeries here. Everything is kept strictly 
   // chronological (0 = oldest bar) so arrays always align perfectly.
   
   // Initialize ATR handle
   atrHandle = iATR(_Symbol, _Period, InpATRPeriod);
   if(atrHandle == INVALID_HANDLE)
     {
      Print("Failed to load ATR indicator handle");
      return(INIT_FAILED);
     }
     
   // Name the indicator window
   string short_name = "ATR Adj Gain/Loss (" + IntegerToString(InpRSIPeriod) + ") + EMA Mid (" + IntegerToString(InpEMAMidPeriod) + ")";
   IndicatorSetString(INDICATOR_SHORTNAME, short_name);
   
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(atrHandle);
  }

//+------------------------------------------------------------------+
//| 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[])
  {
   // Ensure we have enough data to calculate
   if(rates_total < MathMax(InpRSIPeriod, InpEMAMidPeriod))
      return(0);

   // Safely fetch ATR data. By copying from 0 to rates_total, 
   // we guarantee atrArray[i] perfectly aligns with close[i]
   if(CopyBuffer(atrHandle, 0, 0, rates_total, atrArray) != rates_total)
     {
      // Wait for MT5 to finish building the ATR history
      return(0);
     }

   // Determine where to start calculating to save CPU
   int start = prev_calculated - 1;
   if(start < 1)
     {
      start = 1; // Start at 1 because we need close[i-1]
      BufferGain[0] = 0;
      BufferLoss[0] = 0;
      BufferRawMid[0] = 0;
      BufferMid[0] = 0;
     }

   // EMA Alpha for the Midline
   double alphaMid = 2.0 / (InpEMAMidPeriod + 1.0);

   // Main Calculation Loop
   for(int i = start; i < rates_total; i++)
     {
      // 1. Calculate Raw Point Change
      double change = close[i] - close[i-1];
      
      // 2. Fetch perfectly aligned ATR
      double atr = atrArray[i];
      
      // Robust Failsafe: Avoid division by zero if ATR is broken on a tick
      if(atr <= 0.0 || atr == EMPTY_VALUE) 
        {
         if(i > 0 && atrArray[i-1] > 0) atr = atrArray[i-1]; // Use previous
         else atr = _Point * 10; // Extreme fallback
        }
      
      // 3. Separate and Normalize Gains/Losses
      double gain = (change > 0) ? (change / atr) * InpScaleMult : 0.0;
      double loss = (change < 0) ? (-change / atr) * InpScaleMult : 0.0;
      
      // 4. Smooth the Data
      if(i == 1)
        {
         // Initial anchor values for the very first bar on chart
         BufferGain[i]   = gain;
         BufferLoss[i]   = loss;
         BufferRawMid[i] = (gain + loss) / 2.0;
         BufferMid[i]    = BufferRawMid[i];
        }
      else
        {
         // Wilder's Smoothing for Gains and Losses (Standard RSI Math)
         BufferGain[i] = (BufferGain[i-1] * (InpRSIPeriod - 1) + gain) / (double)InpRSIPeriod;
         BufferLoss[i] = (BufferLoss[i-1] * (InpRSIPeriod - 1) + loss) / (double)InpRSIPeriod;
         
         // Calculate True Midpoint of the forces
         BufferRawMid[i] = (BufferGain[i] + BufferLoss[i]) / 2.0;
         
         // Standard Exponential Smoothing (EMA) for the Midline baseline
         BufferMid[i] = (BufferRawMid[i] - BufferMid[i-1]) * alphaMid + BufferMid[i-1];
        }
     }

   // Return the rates_total to track calculation state on the next tick
   return(rates_total);
  }
//+------------------------------------------------------------------+