//+------------------------------------------------------------------+
//|                             accumulation-distribution-alert.mq4   |
//|  Plots Accumulation/Distribution in a separate window and alerts  |
//|  when A/D crosses its own signal moving average.                  |
//|  Source: web-forex (educational, free to use and modify)          |
//+------------------------------------------------------------------+
#property copyright "web-forex"
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 clrDodgerBlue

extern int    SignalPeriod  = 20;
extern bool   EnableAlert   = true;
extern bool   EnablePush    = false;

double ADBuffer[];

int lastSignal = 0; // 0 = none, 1 = A/D above its SMA, -1 = A/D below its SMA

int OnInit()
{
   SetIndexBuffer(0, ADBuffer);
   SetIndexStyle(0, DRAW_LINE);
   SetIndexLabel(0, "A/D");

   IndicatorShortName("Accumulation/Distribution Alert");
   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 = rates_total - prev_calculated;
   if (start > rates_total - SignalPeriod - 1)
      start = rates_total - SignalPeriod - 1;
   if (start < 0)
      return(rates_total);

   for (int i = start; i >= 0; i--)
      ADBuffer[i] = iAD(NULL, 0, i);

   CheckCrossSignal();
   return(rates_total);
}

double CalcAdSma(int startShift, int period)
{
   double sum = 0;
   for (int i = startShift; i < startShift + period; i++)
      sum += iAD(NULL, 0, i);
   return(sum / period);
}

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

   double adPrev  = iAD(NULL, 0, 2);
   double adLast  = iAD(NULL, 0, 1);
   double smaPrev = CalcAdSma(3, SignalPeriod);
   double smaLast = CalcAdSma(2, SignalPeriod);

   int signal = 0;
   if (adPrev <= smaPrev && adLast > smaLast)
      signal = 1;  // A/D crossed above its own SMA
   else if (adPrev >= smaPrev && adLast < smaLast)
      signal = -1; // A/D crossed below its own SMA

   if (signal != 0 && signal != lastSignal)
   {
      string msg = (signal == 1)
         ? Symbol() + " " + EnumToString((ENUM_TIMEFRAMES)Period()) + ": A/D crossed above its signal average"
         : Symbol() + " " + EnumToString((ENUM_TIMEFRAMES)Period()) + ": A/D crossed below its signal average";

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

      lastSignal = signal;
   }
}
