//+------------------------------------------------------------------+
//|                                                demarker-alert.mq5 |
//|  Plots DeMarker 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  "DeMarker"
#property indicator_minimum 0
#property indicator_maximum 1
#property indicator_level1  0.3
#property indicator_level2  0.7

input int    DeMarkerPeriod = 14;
input double Overbought     = 0.7;
input double Oversold       = 0.3;
input bool   EnableAlert    = true;
input bool   EnablePush     = false;

double DeMarkerBuffer[];

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

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

   deMarkerHandle = iDeMarker(_Symbol, _Period, DeMarkerPeriod);

   IndicatorSetString(INDICATOR_SHORTNAME, "DeMarker Alert (" + IntegerToString(DeMarkerPeriod) + ")");
   return(INIT_SUCCEEDED);
}

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

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

   CopyBuffer(deMarkerHandle, 0, 0, rates_total, DeMarkerBuffer);

   CheckZoneSignal();
   return(rates_total);
}

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

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

   double demLast = arr[1];

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

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

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

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