//+------------------------------------------------------------------+
//|                                             BullsBearsVolume.mq5 |
//|                                                           Shovel |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Shovel"
#property link      "http://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1  clrGreen
#property indicator_width1  2 
#property indicator_color2  clrRed
#property indicator_width2  2 
#property strict


//--- input parameters
input int            InpPeriod        = 13;           // Period
input bool           UseRealVolume    = false;        // Use real volume?
input double         delta            = 0.00001;      // delta (flat level)
input bool           alertsOn         = false;        // Alerts on true/false?
input bool           alertsOnCurrent  = true;         // Alerts on open bar true/false?
input bool           alertsMessage    = true;         // Alerts message true/false?
input bool           alertsSound      = false;        // Alerts sound true/false?
input bool           alertsPushNotif  = false;        // Alerts push notification true/false?
input bool           alertsEmail      = false;        // Alerts email true/false?
input string         soundFile        = "alert2.wav"; // Sound file

double    ExtBullsBearsBuffer[],hup[],hdn[],trend[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0,hup,INDICATOR_DATA); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,hdn,INDICATOR_DATA); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,ExtBullsBearsBuffer);
   SetIndexBuffer(3,trend);

   IndicatorSetString(INDICATOR_SHORTNAME,"BullsBearsVolume("+(string)InpPeriod+"  delta: "+(string)delta+") ");
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&     real_volume[],
                 const int&      spread[])

{
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
   int i=rates_total-prev_calculated+1; if (i>=rates_total) i=rates_total-1; 
   for (; i>=0 && !_StopFlag; i--)
   {
      double _bull = high[i]-iMA(NULL,0,InpPeriod,0,MODE_EMA,PRICE_CLOSE,i);
      double _bear =  low[i]-iMA(NULL,0,InpPeriod,0,MODE_EMA,PRICE_CLOSE,i);

      //--- fill indicators buffer
      if(_bull>0 && _bear>0)      ExtBullsBearsBuffer[i] = _bull-_bear;
      else if(_bull<0 && _bear<0) ExtBullsBearsBuffer[i] = -(fabs(_bear)-fabs(_bull));
      else                        ExtBullsBearsBuffer[i] = _bull+_bear;

      double volume = (UseRealVolume) ? (double)real_volume[i] : (double)tick_volume[i];

      //--- add volume to indicators buffer
      ExtBullsBearsBuffer[i]=ExtBullsBearsBuffer[i]*(double)volume*point;

      //--- remove noise 
      if(fabs(ExtBullsBearsBuffer[i])<delta) ExtBullsBearsBuffer[i]=0.0;

      //--- fill indicators color buffer
      trend[i] = 0;
      hup[i] = EMPTY_VALUE;
      hdn[i] = EMPTY_VALUE;
      if(fabs(_bull)>fabs(_bear)) { hup[i] = ExtBullsBearsBuffer[i]; trend[i] = 1; }  // set color Green
      else                        { hdn[i] = ExtBullsBearsBuffer[i]; trend[i] =-1; }  // set color Red
     }
     if (alertsOn)
     {
        int whichBar = (alertsOnCurrent) ? 0 : 1;
        if (trend[whichBar] != trend[whichBar+1])
        {
           if (trend[whichBar] == 1) doAlert(" up");
           if (trend[whichBar] ==-1) doAlert(" down");       
        }         
     }     

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

void doAlert(string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[0]) {
          previousAlert  = doWhat;
          previousTime   = Time[0];

          //
          //
          //
          //
          //

          message = timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" Bulls bears volume "+doWhat;
             if (alertsMessage)     Alert(message);
             if (alertsPushNotif )  SendNotification(message);
             if (alertsEmail)       SendMail(_Symbol+" Bulls bears volume ",message);
             if (alertsSound)       PlaySound(soundFile);
      }
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

