//+------------------------------------------------------------------+
//|                                   bulls-bears-power-alert.mq5     |
//|  Plots Bulls Power and Bears Power against a zero line and alerts |
//|  when either loses control (crosses zero).                       |
//|  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  "Bulls Power"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrOrangeRed
#property indicator_label2  "Bears Power"
#property indicator_level1  0

input int  Period_     = 13;
input bool EnableAlert = true;
input bool EnablePush  = false;

double BullsBuffer[];
double BearsBuffer[];

int bullsHandle = INVALID_HANDLE;
int bearsHandle = INVALID_HANDLE;
int lastSignal = 0; // 0 = none, 1 = Bears crossed above zero, -1 = Bulls crossed below zero

int OnInit()
{
   SetIndexBuffer(0, BullsBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, BearsBuffer, INDICATOR_DATA);
   ArraySetAsSeries(BullsBuffer, true);
   ArraySetAsSeries(BearsBuffer, true);

   bullsHandle = iBullsPower(_Symbol, _Period, Period_);
   bearsHandle = iBearsPower(_Symbol, _Period, Period_);

   IndicatorSetString(INDICATOR_SHORTNAME, "Bulls/Bears Power Alert (" + IntegerToString(Period_) + ")");
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   IndicatorRelease(bullsHandle);
   IndicatorRelease(bearsHandle);
}

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(bullsHandle) < rates_total || BarsCalculated(bearsHandle) < rates_total)
      return(0);

   CopyBuffer(bullsHandle, 0, 0, rates_total, BullsBuffer);
   CopyBuffer(bearsHandle, 0, 0, rates_total, BearsBuffer);

   CheckZeroCrossSignal();
   return(rates_total);
}

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

   double bullsArr[], bearsArr[];
   ArraySetAsSeries(bullsArr, true);
   ArraySetAsSeries(bearsArr, true);
   if (CopyBuffer(bullsHandle, 0, 0, 3, bullsArr) < 3) return;
   if (CopyBuffer(bearsHandle, 0, 0, 3, bearsArr) < 3) return;

   double bearsPrev = bearsArr[2];
   double bearsLast = bearsArr[1];
   double bullsPrev = bullsArr[2];
   double bullsLast = bullsArr[1];

   int signal = 0;
   if (bearsPrev <= 0 && bearsLast > 0)
      signal = 1;
   else if (bullsPrev >= 0 && bullsLast < 0)
      signal = -1;

   if (signal != 0 && signal != lastSignal)
   {
      string msg = (signal == 1)
         ? _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": Bears Power crossed above zero"
         : _Symbol + " " + EnumToString((ENUM_TIMEFRAMES)_Period) + ": Bulls Power crossed below zero";

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

      lastSignal = signal;
   }
}
