//+------------------------------------------------------------------+
//|                                    gator-oscillator-alert.mq5      |
//|  Plots the Gator Oscillator (the Alligator's Jaw-Teeth and         |
//|  Teeth-Lips spread, as two histograms) and alerts when both        |
//|  histograms are growing at the same time as the Alligator's        |
//|  Jaw/Teeth/Lips lines are fanned out in order - the "Gator waking   |
//|  up and feeding" signal.                                            |
//|  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_HISTOGRAM
#property indicator_color1  clrLimeGreen
#property indicator_label1  "Gator Upper"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrOrangeRed
#property indicator_label2  "Gator Lower"
#property indicator_level1  0

input int                JawPeriod    = 13;
input int                JawShift     = 8;
input int                TeethPeriod  = 8;
input int                TeethShift   = 5;
input int                LipsPeriod   = 5;
input int                LipsShift    = 3;
input ENUM_MA_METHOD      MAMethod     = MODE_SMMA;
input ENUM_APPLIED_PRICE  AppliedPrice = PRICE_MEDIAN;
input bool                EnableAlert  = true;
input bool                EnablePush   = false;

double UpperBuffer[];
double LowerBuffer[];

int gatorHandle = INVALID_HANDLE;
int alligatorHandle = INVALID_HANDLE;
int lastSignal = 0; // 0 = none, 1 = bullish fan growing, -1 = bearish fan growing

int OnInit()
{
   SetIndexBuffer(0, UpperBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, LowerBuffer, INDICATOR_DATA);
   ArraySetAsSeries(UpperBuffer, true);
   ArraySetAsSeries(LowerBuffer, true);

   gatorHandle     = iGator(_Symbol, _Period, JawPeriod, JawShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MAMethod, AppliedPrice);
   alligatorHandle = iAlligator(_Symbol, _Period, JawPeriod, JawShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MAMethod, AppliedPrice);

   IndicatorSetString(INDICATOR_SHORTNAME, "Gator Oscillator Alert");
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   IndicatorRelease(gatorHandle);
   IndicatorRelease(alligatorHandle);
}

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

   CopyBuffer(gatorHandle, 0, 0, rates_total, UpperBuffer); // upper histogram value
   CopyBuffer(gatorHandle, 2, 0, rates_total, LowerBuffer); // lower histogram value

   CheckGrowSignal();
   return(rates_total);
}

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

   double upperArr[], lowerArr[];
   ArraySetAsSeries(upperArr, true);
   ArraySetAsSeries(lowerArr, true);
   if (CopyBuffer(gatorHandle, 0, 0, 3, upperArr) < 3) return;
   if (CopyBuffer(gatorHandle, 2, 0, 3, lowerArr) < 3) return;

   double upperPrev = upperArr[2];
   double upperLast = upperArr[1];
   double lowerPrev = lowerArr[2];
   double lowerLast = lowerArr[1];

   bool growing = (MathAbs(upperLast) > MathAbs(upperPrev)) && (MathAbs(lowerLast) > MathAbs(lowerPrev));
   if (!growing)
   {
      lastSignal = 0; // reset so the next growing episode can alert again
      return;
   }

   double jawArr[], teethArr[], lipsArr[];
   ArraySetAsSeries(jawArr, true);
   ArraySetAsSeries(teethArr, true);
   ArraySetAsSeries(lipsArr, true);
   if (CopyBuffer(alligatorHandle, 0, 0, 2, jawArr) < 2) return;
   if (CopyBuffer(alligatorHandle, 1, 0, 2, teethArr) < 2) return;
   if (CopyBuffer(alligatorHandle, 2, 0, 2, lipsArr) < 2) return;

   double jaw   = jawArr[1];
   double teeth = teethArr[1];
   double lips  = lipsArr[1];

   int signal = 0;
   if (lips > teeth && teeth > jaw)
      signal = 1;  // bullish fan, both Gator histograms growing
   else if (lips < teeth && teeth < jaw)
      signal = -1; // bearish fan, both Gator histograms growing

   if (signal != 0 && signal != lastSignal)
   {
      string msg = (signal == 1)
         ? _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": Gator waking up (both histograms growing) with a bullish Alligator fan"
         : _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": Gator waking up (both histograms growing) with a bearish Alligator fan";

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

      lastSignal = signal;
   }
}
