//+------------------------------------------------------------------+
//|                                            ma-cross-alert.mq5     |
//|  Plots a fast and slow Moving Average and alerts on cross events. |
//|  Source: web-forex (educational, free to use and modify)          |
//+------------------------------------------------------------------+
#property copyright "web-forex"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_label1  "MA Fast"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrOrangeRed
#property indicator_label2  "MA Slow"

input int                FastPeriod   = 20;
input int                SlowPeriod   = 50;
input ENUM_MA_METHOD      MAMethod     = MODE_EMA;
input ENUM_APPLIED_PRICE  AppliedPrice = PRICE_CLOSE;
input bool                EnableAlert  = true;
input bool                EnablePush   = false;

double FastBuffer[];
double SlowBuffer[];

int fastHandle = INVALID_HANDLE;
int slowHandle = INVALID_HANDLE;
int lastSignal = 0; // 0 = none, 1 = golden cross, -1 = death cross

int OnInit()
{
   SetIndexBuffer(0, FastBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, SlowBuffer, INDICATOR_DATA);
   ArraySetAsSeries(FastBuffer, true);
   ArraySetAsSeries(SlowBuffer, true);

   fastHandle = iMA(_Symbol, _Period, FastPeriod, 0, MAMethod, AppliedPrice);
   slowHandle = iMA(_Symbol, _Period, SlowPeriod, 0, MAMethod, AppliedPrice);

   IndicatorSetString(INDICATOR_SHORTNAME, "MA Cross Alert (" + IntegerToString(FastPeriod) + "/" + IntegerToString(SlowPeriod) + ")");
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   IndicatorRelease(fastHandle);
   IndicatorRelease(slowHandle);
}

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(fastHandle) < rates_total || BarsCalculated(slowHandle) < rates_total)
      return(0);

   CopyBuffer(fastHandle, 0, 0, rates_total, FastBuffer);
   CopyBuffer(slowHandle, 0, 0, rates_total, SlowBuffer);

   CheckCrossSignal();
   return(rates_total);
}

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

   double fastArr[], slowArr[];
   ArraySetAsSeries(fastArr, true);
   ArraySetAsSeries(slowArr, true);
   if (CopyBuffer(fastHandle, 0, 0, 3, fastArr) < 3) return;
   if (CopyBuffer(slowHandle, 0, 0, 3, slowArr) < 3) return;

   double fastPrev = fastArr[2];
   double slowPrev = slowArr[2];
   double fastLast = fastArr[1];
   double slowLast = slowArr[1];

   int signal = 0;
   if (fastPrev <= slowPrev && fastLast > slowLast)
      signal = 1;  // Golden Cross
   else if (fastPrev >= slowPrev && fastLast < slowLast)
      signal = -1; // Death Cross

   if (signal != 0 && signal != lastSignal)
   {
      string msg = (signal == 1)
         ? _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": Golden Cross (MA" + IntegerToString(FastPeriod) + " > MA" + IntegerToString(SlowPeriod) + ")"
         : _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": Death Cross (MA" + IntegerToString(FastPeriod) + " < MA" + IntegerToString(SlowPeriod) + ")";

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

      lastSignal = signal;
   }
}
