//+------------------------------------------------------------------+
//|                                                 rsi-alert.mq5     |
//|  Plots RSI in a separate window and alerts on overbought/oversold |
//|  Source: web-forex (educational, free to use and modify)          |
//+------------------------------------------------------------------+
#property copyright "web-forex"
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_label1  "RSI"
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1  30
#property indicator_level2  50
#property indicator_level3  70

input int                RSIPeriod    = 14;
input ENUM_APPLIED_PRICE  AppliedPrice = PRICE_CLOSE;
input double              Overbought   = 70.0;
input double              Oversold     = 30.0;
input bool                EnableAlert  = true;
input bool                EnablePush   = false;

double RSIBuffer[];

int rsiHandle = INVALID_HANDLE;
int lastZone = 0; // 0 = neutral, 1 = overbought, -1 = oversold

int OnInit()
{
   SetIndexBuffer(0, RSIBuffer, INDICATOR_DATA);
   ArraySetAsSeries(RSIBuffer, true);

   rsiHandle = iRSI(_Symbol, _Period, RSIPeriod, AppliedPrice);

   IndicatorSetString(INDICATOR_SHORTNAME, "RSI Alert (" + IntegerToString(RSIPeriod) + ")");
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   IndicatorRelease(rsiHandle);
}

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[])
{
   if (BarsCalculated(rsiHandle) < rates_total)
      return(0);

   CopyBuffer(rsiHandle, 0, 0, rates_total, RSIBuffer);

   CheckZoneSignal();
   return(rates_total);
}

void CheckZoneSignal()
{
   if (!EnableAlert && !EnablePush)
      return;

   double arr[];
   ArraySetAsSeries(arr, true);
   if (CopyBuffer(rsiHandle, 0, 0, 2, arr) < 2)
      return;

   double rsiLast = arr[1];

   int zone = 0;
   if (rsiLast >= Overbought)
      zone = 1;
   else if (rsiLast <= Oversold)
      zone = -1;

   if (zone != 0 && zone != lastZone)
   {
      string msg = (zone == 1)
         ? _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": RSI Overbought (" + DoubleToString(rsiLast, 2) + ")"
         : _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": RSI Oversold (" + DoubleToString(rsiLast, 2) + ")";

      if (EnableAlert)
         Alert(msg);
      if (EnablePush)
         SendNotification(msg);
   }

   if (zone != 0)
      lastZone = zone;
   else if (rsiLast > Oversold + 5 && rsiLast < Overbought - 5)
      lastZone = 0;
}
