//+------------------------------------------------------------------+
//|                                     Short RSI of EMA - Bicolor.mq4 |
//+------------------------------------------------------------------+
#property copyright ""
#property link      ""
#property strict

#property indicator_separate_window
#property indicator_buffers 9
#property indicator_color1 clrLightGreen
#property indicator_color2 clrDarkRed
#property indicator_color3 clrLime
#property indicator_color4 clrRed
#property indicator_color5 clrGreen
#property indicator_color6 clrRed
#property indicator_color7 clrRed  // Above-Zero Threshold Line
#property indicator_color8 clrRed  // Below-Zero Threshold Line
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
#property indicator_width4 2
#property indicator_width5 3
#property indicator_width6 3
#property indicator_width7 1       // Threshold Line Width
#property indicator_width8 1       // Threshold Line Width
#property indicator_style7 STYLE_DOT // Above-Zero Threshold Line Style
#property indicator_style8 STYLE_DOT // Below-Zero Threshold Line Style

// Input parameters for EMA, RSI, and thresholds
extern int short_l1 = 5;  // Short - L1 (First EMA Period)
extern int short_l2 = 20; // Short - L2 (Second EMA Period)
extern int short_l3 = 15; // Short - RSI Period (RSI Smoothing)
extern double Above_Threshold = 5.0; // Above-zero threshold level
extern double Below_Threshold = -5.0; // Below-zero threshold level

// Buffers for Short RSI Histogram and Line
double shortTermXtrender1[];     // Positive histogram
double shortTermXtrender2[];     // Negative histogram
double shortRSILine[];           // Continuous RSI line
double shortRSILinePositive[];   // Positive slope (lime)
double shortRSILineNegative[];   // Negative slope (red)

// Buffers for dots
double zeroCrossBuy[];           // Green dot (buy signal)
double zeroCrossSell[];          // Red dot (sell signal)

// Buffers for thresholds
double AboveThresholdLine[];     // Above-zero threshold line
double BelowThresholdLine[];     // Below-zero threshold line

// Buffers for internal calculations
double ema1[], ema2[], src1[], rsi1[], rsi2[];

//+------------------------------------------------------------------+
//| Initialization                                                   |
//+------------------------------------------------------------------+
int init() {
   IndicatorBuffers(9);

   // Validate thresholds
   if (Above_Threshold <= 0) {
      Print("Invalid Above_Threshold value. Adjusted to 10.0 (default positive value).");
      Above_Threshold = 10.0; // Ensure it is positive
   }
   if (Below_Threshold >= 0) {
      Print("Invalid Below_Threshold value. Adjusted to -10.0 (default negative value).");
      Below_Threshold = -10.0; // Ensure it is negative
   }

   // Setup buffers for the histogram
   SetIndexBuffer(0, shortTermXtrender1); SetIndexStyle(0, DRAW_HISTOGRAM); SetIndexLabel(0, "Short RSI Up");
   SetIndexBuffer(1, shortTermXtrender2); SetIndexStyle(1, DRAW_HISTOGRAM); SetIndexLabel(1, "Short RSI Down");

   // Setup buffers for the RSI line
   SetIndexBuffer(2, shortRSILine); SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 1, clrMagenta); SetIndexLabel(2, "Short RSI Line");

   // Setup buffers for the RSI line with dynamic colors
   SetIndexBuffer(3, shortRSILinePositive); SetIndexStyle(3, DRAW_LINE, STYLE_SOLID, 2, clrLime); SetIndexLabel(3, "RSI Line Positive");
   SetIndexBuffer(4, shortRSILineNegative); SetIndexStyle(4, DRAW_LINE, STYLE_SOLID, 2, clrRed); SetIndexLabel(4, "RSI Line Negative");

   // Setup buffers for dots
   SetIndexBuffer(5, zeroCrossBuy); SetIndexStyle(5, DRAW_ARROW, STYLE_SOLID, 7, clrAqua); SetIndexArrow(5, 159); SetIndexLabel(5, "Buy Signal");
   SetIndexBuffer(6, zeroCrossSell); SetIndexStyle(6, DRAW_ARROW, STYLE_SOLID, 7, clrYellow); SetIndexArrow(6, 159); SetIndexLabel(6, "Sell Signal");

   // Setup buffers for thresholds
   SetIndexBuffer(7, AboveThresholdLine); SetIndexStyle(7, DRAW_LINE, STYLE_DOT, 1, clrRed); SetIndexLabel(7, "Above Threshold");
   SetIndexBuffer(8, BelowThresholdLine); SetIndexStyle(8, DRAW_LINE, STYLE_DOT, 1, clrRed); SetIndexLabel(8, "Below Threshold");

   // Internal calculation buffers
   SetIndexBuffer(9, ema1); SetIndexStyle(9, DRAW_NONE);
   SetIndexBuffer(10, ema2); SetIndexStyle(10, DRAW_NONE);

   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Calculation 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[]) {
   int limit;

   // Resize arrays to match the number of bars
   ArrayResize(ema1, rates_total);
   ArrayResize(ema2, rates_total);
   ArrayResize(src1, rates_total);
   ArrayResize(rsi1, rates_total);
   ArrayResize(rsi2, rates_total);
   ArrayResize(shortTermXtrender1, rates_total);
   ArrayResize(shortTermXtrender2, rates_total);
   ArrayResize(shortRSILine, rates_total);
   ArrayResize(shortRSILinePositive, rates_total);
   ArrayResize(shortRSILineNegative, rates_total);
   ArrayResize(zeroCrossBuy, rates_total);
   ArrayResize(zeroCrossSell, rates_total);
   ArrayResize(AboveThresholdLine, rates_total);
   ArrayResize(BelowThresholdLine, rates_total);

   // Calculate the starting point for recalculation
   if (prev_calculated == 0) {
      // Initialize arrays with default values
      ArrayInitialize(shortTermXtrender1, EMPTY_VALUE);
      ArrayInitialize(shortTermXtrender2, EMPTY_VALUE);
      ArrayInitialize(shortRSILine, EMPTY_VALUE);
      ArrayInitialize(zeroCrossBuy, EMPTY_VALUE);
      ArrayInitialize(zeroCrossSell, EMPTY_VALUE);
      limit = rates_total - 1; // Start calculation from the first bar
   } else {
      limit = rates_total - prev_calculated;
   }

   // Main Calculation Loop
   for (int i = limit - 1; i >= 0; i--) {
      if (i + 1 >= rates_total) continue;

      // Calculate EMAs and Source
      ema1[i] = ema(ema1, close, short_l1, i); 
      ema2[i] = ema(ema2, close, short_l2, i); 
      src1[i] = ema1[i] - ema2[i];
      shortRSILine[i] = rsi(rsi1, rsi2, src1, short_l3, i) - 50;

      
      ////
      
       // Populate the RSI Line Buffers with dynamic colors
      if (shortRSILine[i] > shortRSILine[i + 1]) { // Positive slope
         shortRSILinePositive[i] = shortRSILine[i];
         shortRSILineNegative[i] = EMPTY_VALUE;
      } else { // Negative slope
         shortRSILinePositive[i] = EMPTY_VALUE;
         shortRSILineNegative[i] = shortRSILine[i];
      }
            
      ////
      
      // Threshold Crossing Logic
      if (shortRSILine[i] < Above_Threshold && shortRSILine[i + 1] >= Above_Threshold) {
         zeroCrossBuy[i] = EMPTY_VALUE;
         zeroCrossSell[i] = Above_Threshold;
      } else if (shortRSILine[i] > Below_Threshold && shortRSILine[i + 1] <= Below_Threshold) {
         zeroCrossBuy[i] = Below_Threshold;
         zeroCrossSell[i] = EMPTY_VALUE;
      } else {
         zeroCrossBuy[i] = EMPTY_VALUE;
         zeroCrossSell[i] = EMPTY_VALUE;
      }

      // Populate Histogram Buffers
      if (shortRSILine[i] > 0) {
         shortTermXtrender1[i] = shortRSILine[i]; // Positive RSI (Green Histogram)
         shortTermXtrender2[i] = EMPTY_VALUE;
      } else {
         shortTermXtrender1[i] = EMPTY_VALUE;
         shortTermXtrender2[i] = shortRSILine[i]; // Negative RSI (Red Histogram)
      }

      // Populate Threshold Buffers
      AboveThresholdLine[i] = Above_Threshold;
      BelowThresholdLine[i] = Below_Threshold;
   }

   return (rates_total);
}

//+------------------------------------------------------------------+
//| Exponential Moving Average (EMA)                                |
//+------------------------------------------------------------------+
double ema(const double &ma[], const double &value[], int length, int i) {
   double alpha = 2.0 / (length + 1);
   return alpha * value[i] + (1 - alpha) * ma[i + 1];
}

//+------------------------------------------------------------------+
//| Relative Strength Index (RSI)                                   |
//+------------------------------------------------------------------+
double rsi(double &rsi_ma1[], double &rsi_ma2[], double &ma1[], int length, int i) {
   double uu = MathMax(ma1[i] - ma1[i + 1], 0); // Upward change
   double dd = MathMax(ma1[i + 1] - ma1[i], 0); // Downward change
   rsi_ma1[i] = (uu + (length - 1) * rsi_ma1[i + 1]) / length;
   rsi_ma2[i] = (dd + (length - 1) * rsi_ma2[i + 1]) / length;
   double rs = rsi_ma2[i] == 0 ? 0 : rsi_ma1[i] / rsi_ma2[i];
   return (100 - 100 / (1 + rs)); // Standard RSI formula
}