//+------------------------------------------------------------------+
//|                                                     rvi-alert.mq5 |
//|  Plots the Relative Vigor Index main line and signal line, and    |
//|  alerts on crossovers.                                            |
//|  Source: web-forex (educational, free to use and modify)          |
//+------------------------------------------------------------------+
#property copyright "web-forex"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_label1  "RVI"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrOrangeRed
#property indicator_label2  "Signal"

input int  RVIPeriod   = 10;
input bool EnableAlert = true;
input bool EnablePush  = false;

double RVIBuffer[];
double SignalBuffer[];

int rviHandle = INVALID_HANDLE;
int lastSignal = 0; // 0 = none, 1 = RVI above Signal, -1 = RVI below Signal

int OnInit()
{
   SetIndexBuffer(0, RVIBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, SignalBuffer, INDICATOR_DATA);
   ArraySetAsSeries(RVIBuffer, true);
   ArraySetAsSeries(SignalBuffer, true);

   rviHandle = iRVI(_Symbol, _Period, RVIPeriod);

   IndicatorSetString(INDICATOR_SHORTNAME, "RVI Alert (" + IntegerToString(RVIPeriod) + ")");
   return(INIT_SUCCEEDED);
}

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

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(rviHandle) < rates_total)
      return(0);

   CopyBuffer(rviHandle, 0, 0, rates_total, RVIBuffer);
   CopyBuffer(rviHandle, 1, 0, rates_total, SignalBuffer);

   CheckCrossSignal();
   return(rates_total);
}

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

   double rviArr[], signalArr[];
   ArraySetAsSeries(rviArr, true);
   ArraySetAsSeries(signalArr, true);
   if (CopyBuffer(rviHandle, 0, 0, 3, rviArr) < 3) return;
   if (CopyBuffer(rviHandle, 1, 0, 3, signalArr) < 3) return;

   double rviPrev    = rviArr[2];
   double signalPrev = signalArr[2];
   double rviLast     = rviArr[1];
   double signalLast  = signalArr[1];

   int signal = 0;
   if (rviPrev <= signalPrev && rviLast > signalLast)
      signal = 1;
   else if (rviPrev >= signalPrev && rviLast < signalLast)
      signal = -1;

   if (signal != 0 && signal != lastSignal)
   {
      string msg = (signal == 1)
         ? _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": RVI crossed above its Signal line"
         : _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": RVI crossed below its Signal line";

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

      lastSignal = signal;
   }
}
