//+------------------------------------------------------------------+
//|                                                     mfi-alert.mq5 |
//|  Plots the Money Flow Index 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  "MFI"
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1  20
#property indicator_level2  80

input int    MFIPeriod    = 14;
input double Overbought   = 80.0;
input double Oversold     = 20.0;
input bool   EnableAlert  = true;
input bool   EnablePush   = false;

double MFIBuffer[];

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

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

   mfiHandle = iMFI(_Symbol, _Period, MFIPeriod, VOLUME_TICK);

   IndicatorSetString(INDICATOR_SHORTNAME, "MFI Alert (" + IntegerToString(MFIPeriod) + ")");
   return(INIT_SUCCEEDED);
}

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

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

   CopyBuffer(mfiHandle, 0, 0, rates_total, MFIBuffer);

   CheckZoneSignal();
   return(rates_total);
}

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

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

   double mfiLast = arr[1];

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

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

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

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