//+------------------------------------------------------------------+
//|      RSI Sniper Arrows v2 - Binary Signal Indicator for MT4      |
//|    Now with RSI Cross Logic, Trend Tolerance, Alerts, Panel      |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Lime      // Buy Arrow
#property indicator_color2 Red       // Sell Arrow

//---- input parameters
input int     RSI_Period            = 3;
input double  Overbought            = 70;
input double  Oversold              = 30;
input int     MA_Period             = 50;
input ENUM_MA_METHOD MA_Method      = MODE_EMA;
input double  MA_Tolerance_Points   = 10;   // Allow signals near MA
input int     BarsBack              = 300;

input bool    UseCandleConfirmation = true;

input bool    ShowStatsPanel        = true;
input bool    EnableSoundAlert      = false;
input bool    EnablePushAlert       = false;
input bool    EnableEmailAlert      = false;

//---- NEW: arrow offsets (in points)
input int     BuyArrowOffset        = 100;   // vertical distance below low
input int     SellArrowOffset       = 100;   // vertical distance above high

//---- buffers
double BuyBuffer[];
double SellBuffer[];

//---- stats
int totalSignals = 0, totalWins = 0;
string panelName = "RSISniperStats";

//+------------------------------------------------------------------+
int OnInit()
{
   SetIndexBuffer(0, BuyBuffer);
   SetIndexStyle(0, DRAW_ARROW);
   SetIndexArrow(0, 233); // Up arrow

   SetIndexBuffer(1, SellBuffer);
   SetIndexStyle(1, DRAW_ARROW);
   SetIndexArrow(1, 234); // Down arrow

   ArrayInitialize(BuyBuffer, EMPTY_VALUE);
   ArrayInitialize(SellBuffer, EMPTY_VALUE);

   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[])
{
   int start = MathMax(2, rates_total - BarsBack);

   totalSignals = 0;
   totalWins    = 0;

   for (int i = start; i >= 1; i--)
   {
      BuyBuffer[i]  = EMPTY_VALUE;
      SellBuffer[i] = EMPTY_VALUE;

      double rsi     = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, i);
      double rsiPrev = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, i + 1);
      double ma      = iMA(NULL, 0, MA_Period, 0, MA_Method, PRICE_CLOSE, i);
      double tol     = MA_Tolerance_Points * Point;

      bool bull = (close[i] > open[i]);
      bool bear = (close[i] < open[i]);

      // BUY Signal
      if (rsiPrev < Oversold && rsi >= Oversold &&
          close[i] >= ma - tol &&
          (!UseCandleConfirmation || bull))
      {
         // place arrow BuyArrowOffset points below low
         BuyBuffer[i] = low[i] - BuyArrowOffset * Point;

         if (i == 1) TriggerAlert("CALL", time[1]);

         totalSignals++;
         if (close[i - 1] > open[i - 1]) totalWins++;
      }

      // SELL Signal
      if (rsiPrev > Overbought && rsi <= Overbought &&
          close[i] <= ma + tol &&
          (!UseCandleConfirmation || bear))
      {
         // place arrow SellArrowOffset points above high
         SellBuffer[i] = high[i] + SellArrowOffset * Point;

         if (i == 1) TriggerAlert("PUT", time[1]);

         totalSignals++;
         if (close[i - 1] < open[i - 1]) totalWins++;
      }
   }

   if (ShowStatsPanel) DrawPanel();

   return rates_total;
}

//+------------------------------------------------------------------+
void TriggerAlert(string signalType, datetime sigTime)
{
   static datetime lastAlertTime = 0;
   if (TimeCurrent() == lastAlertTime) return;

   string msg = "RSI Sniper Signal: " + signalType + " @ " + TimeToString(sigTime, TIME_SECONDS);
   if (EnableSoundAlert) Alert(msg);
   if (EnablePushAlert) SendNotification(msg);
   if (EnableEmailAlert) SendMail("RSI Sniper Signal", msg);

   lastAlertTime = TimeCurrent();
}

//+------------------------------------------------------------------+
void DrawPanel()
{
   string pnl = panelName;
   int    x   = 10, y = 10;

   double winRate = (totalSignals > 0) ? (double)totalWins / totalSignals * 100.0 : 0;

   string text =
      "RSI Sniper Stats\n" +
      "Signals: " + totalSignals + "\n" +
      "Wins: " + totalWins + "\n" +
      "Win Rate: " + DoubleToString(winRate, 2) + "%";

   if (!ObjectCreate(pnl, OBJ_LABEL, 0, 0, 0))
      ObjectSet(pnl, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetText(pnl, text, 11, "Arial", clrWhite);
   ObjectSet(pnl, OBJPROP_XDISTANCE, x);
   ObjectSet(pnl, OBJPROP_YDISTANCE, y);
}
