//+------------------------------------------------------------------+
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      "www.forex-station.com"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1  clrLimeGreen
#property indicator_color2  clrDarkOrange
#property indicator_width1  2
#property indicator_width2  2
#property indicator_minimum 0
#property indicator_maximum 1
#property strict

//
//
//
//
//

extern ENUM_TIMEFRAMES    TimeFrame              = PERIOD_CURRENT;   // Time frame
extern int                Length                 = 50;               //Length
extern ENUM_APPLIED_PRICE Price                  = PRICE_CLOSE;      // Price to use 
extern int                MaLength               = 10;               // Ma length
extern ENUM_MA_METHOD     MaMethod               = MODE_SMMA;        // Average method    
extern bool               alertsOn               = false;            // Turn alerts on?
extern bool               alertsOnCurrent        = false;            // Alerts on still opened bar?
extern bool               alertsMessage          = true;             // Alerts should display message?
extern bool               alertsSound            = false;            // Alerts should play a sound?
extern bool               alertsNotify           = false;            // Alerts should send a notification?
extern bool               alertsEmail            = false;            // Alerts should send an email?
extern string             soundFile              = "alert2.wav";     // Sound file
extern bool               arrowsVisible          = false;            // Arrows visible?
extern bool               arrowsOnNewest         = false;            // Arrows drawn on newest bar of higher time frame bar?
extern string             arrowsIdentifier       = "mom Arrows1";    // Unique ID for arrows
extern double             arrowsUpperGap         = 1.0;              // Upper arrow gap
extern double             arrowsLowerGap         = 1.0;              // Lower arrow gap
extern color              arrowsUpColor          = clrLimeGreen;     // Up arrow color
extern color              arrowsDnColor          = clrOrange;        // Down arrow color
extern int                arrowsUpCode           = 241;              // Up arrow code
extern int                arrowsDnCode           = 242;              // Down arrow code
extern int                arrowsSize             = 0;                // Arrows size

double Up[],Dn[],mom[],trend[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,Length,Price,MaLength,MaMethod,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsNotify,alertsEmail,soundFile,arrowsVisible,arrowsOnNewest,arrowsIdentifier,arrowsUpperGap,arrowsLowerGap,arrowsUpColor,arrowsDnColor,arrowsUpCode,arrowsDnCode,arrowsSize,_buff,_ind)

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(5);
   SetIndexBuffer(0,Up); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,Dn); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,mom);
   SetIndexBuffer(3,trend);
   SetIndexBuffer(4,count);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = fmax(TimeFrame,_Period);
   
   IndicatorShortName(timeFrameToString(TimeFrame)+" Cumulative momentum ("+(string)Length+","+(string)MaLength+")");
   return(0);
}
int deinit()
{
   string lookFor       = arrowsIdentifier+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i);
         if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

int start() 
{
   int i,counted_bars=IndicatorCounted();
      if(counted_bars<0) return(-1);
      if(counted_bars>0) counted_bars--;
            int limit = MathMin(Bars-counted_bars,Bars-1); count[0] = limit;
            if (TimeFrame != _Period)
            {
               limit = (int)MathMax(limit,MathMin(Bars-1,_mtfCall(4,0)*TimeFrame/Period()));
               for (i=limit; i>=0; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                     Up[i]  = _mtfCall(0,y);
                     Dn[i]  = _mtfCall(1,y);
               }
   return(0);
   }
             
   //
   //
   //
   //
   //
   
   for(i=limit; i>=0; i--)
   {
      double price = iMA(NULL,0,MaLength,0,MaMethod,Price,i);
      mom[i] = 0;
         for (int k=0; k<Length && (i+k)<Bars; k++) mom[i] += price-iMA(NULL,0,MaLength,0,MaMethod,Price,i+k+1);
         trend[i]  = (i<Bars-1) ? (mom[i]>0) ? 1 : (mom[i]<0) ? -1 : trend[i+1] : 0;
         Up[i] = (trend[i] ==  1) ? 1 : EMPTY_VALUE;
         Dn[i] = (trend[i] == -1) ? 1 : EMPTY_VALUE;
         if (arrowsVisible)
         {
           string lookFor = arrowsIdentifier+":"+(string)Time[i]; ObjectDelete(lookFor);            
            if (i<(Bars-1) && trend[i] != trend[i+1])
            {
               if (trend[i] == 1) drawArrow(i,arrowsUpColor,arrowsUpCode,false);
               if (trend[i] ==-1) drawArrow(i,arrowsDnColor,arrowsDnCode, true);
             }
         }
   }
   if (alertsOn)
   {
         int whichBar = 1; if (alertsOnCurrent) whichBar = 0;
         if (trend[whichBar] != trend[whichBar+1])
         if (trend[whichBar] == 1)
               doAlert(" crossed zero up ");
         else  doAlert(" crossed zero down ");       
   }       
return(0);
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

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("");
}

//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,bool tup)
{
   string name = arrowsIdentifier+":"+(string)Time[i];
   double gap  = iATR(NULL,0,20,i);   
   
      //
      //
      //
      //
      //

      datetime time = Time[i]; if (arrowsOnNewest) time += _Period*60-1;      
      ObjectCreate(name,OBJ_ARROW,0,time,0);
         ObjectSet(name,OBJPROP_ARROWCODE,theCode);
         ObjectSet(name,OBJPROP_WIDTH,arrowsSize);
         ObjectSet(name,OBJPROP_COLOR,theColor);
         if (tup)
               ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsUpperGap * gap);
         else  ObjectSet(name,OBJPROP_PRICE1,Low[i]  - arrowsLowerGap * gap);
}

//
//
//
//
//

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)+" cumulative momentum "+doWhat;
          if (alertsMessage) Alert(message);
          if (alertsNotify)  SendNotification(message);
          if (alertsEmail)   SendMail(_Symbol+" cumulative momentum ",message);
          if (alertsSound)   PlaySound(soundFile);
       
   }
}

