//+------------------------------------------------------------------+
//|  FXEA_Dip_Buyer_Zones.mq5                                       |
//|  RSI pullback zones above a rising trend SMA (long-only).       |
//|                                                                  |
//|  Highlights the setup a dip-buying trend system waits for: an   |
//|  RSI oversold pullback WHILE price is above a long-term SMA.    |
//|  Suited to up-biased instruments (indices). Closed bars only.   |
//+------------------------------------------------------------------+
#property copyright "fxea365.com"
#property link      "https://www.mql5.com/en/users/app.develop.sk/seller"
#property version   "1.00"
#property description "Marks RSI-oversold pullbacks that occur while price is above a rising trend SMA - the long-only dip-buy setup for up-biased markets (e.g. stock indices)."
#property description "Closed bars only, no repainting. It highlights context; it does not tell you to trade. Exits when RSI recovers."
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   2

#property indicator_label1  "Trend SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrOrange
#property indicator_width1  2
#property indicator_label2  "Dip-buy zone"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrLimeGreen
#property indicator_width2  2

input int    TrendSMA     = 200;   // Trend SMA (setups only above a rising SMA)
input int    RSI_Period   = 14;    // RSI period
input double RSI_BuyLevel = 40.0;  // RSI at/below this = oversold pullback
input bool   RequireRising= true;  // Require the SMA to be rising

double SmaBuf[], ZoneBuf[], Calc[];
int    sma_handle = INVALID_HANDLE, rsi_handle = INVALID_HANDLE;

int OnInit()
{
   SetIndexBuffer(0, SmaBuf,  INDICATOR_DATA);
   SetIndexBuffer(1, ZoneBuf, INDICATOR_DATA);
   SetIndexBuffer(2, Calc,    INDICATOR_CALCULATIONS);
   PlotIndexSetInteger(1, PLOT_ARROW, 233);  // up arrow
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);

   sma_handle = iMA(_Symbol, PERIOD_CURRENT, TrendSMA, 0, MODE_SMA, PRICE_CLOSE);
   rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
   if(sma_handle == INVALID_HANDLE || rsi_handle == INVALID_HANDLE){ Print("FXEA: handle failed"); return(INIT_FAILED); }
   IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("FXEA Dip Buyer Zones SMA%d/RSI%d", TrendSMA, RSI_Period));
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   if(sma_handle != INVALID_HANDLE) IndicatorRelease(sma_handle);
   if(rsi_handle != INVALID_HANDLE) IndicatorRelease(rsi_handle);
}

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 need = TrendSMA + RSI_Period + 3;
   if(rates_total < need) return(0);

   double sma[], rsi[]; ArraySetAsSeries(sma, false); ArraySetAsSeries(rsi, false);
   if(CopyBuffer(sma_handle, 0, 0, rates_total, sma) <= 0) return(0);
   if(CopyBuffer(rsi_handle, 0, 0, rates_total, rsi) <= 0) return(0);

   int start = (prev_calculated > need) ? prev_calculated - 1 : need;
   for(int i = start; i < rates_total; i++)
   {
      SmaBuf[i]  = sma[i];
      ZoneBuf[i] = 0.0;

      bool aboveSma = (close[i-1] > sma[i]);
      bool rising   = (!RequireRising) || (sma[i] > sma[i-1]);
      bool oversold = (rsi[i-1] <= RSI_BuyLevel);

      if(aboveSma && rising && oversold)
         ZoneBuf[i] = low[i] * 0.999;  // mark the dip-buy setup below the bar
   }
   return(rates_total);
}
//+------------------------------------------------------------------+
