
//------------------------------------------------------------------
#property copyright "www.forex-station.com"
#property link      "www.forex-station.com"
//------------------------------------------------------------------
#property indicator_separate_window
#property indicator_buffers  2
#property indicator_color1   clrLime
#property indicator_color2   clrRed
#property indicator_width1   2
#property indicator_width2   2
#property indicator_minimum  0
#property indicator_maximum  1
#property strict

//
//
//
//
//
 enum enTimeFrames
{
   tf_cu  = PERIOD_CURRENT, // Current time frame
   tf_m1  = PERIOD_M1,      // 1 minute
   tf_m5  = PERIOD_M5,      // 5 minutes
   tf_m15 = PERIOD_M15,     // 15 minutes
   tf_m30 = PERIOD_M30,     // 30 minutes
   tf_h1  = PERIOD_H1,      // 1 hour
   tf_h4  = PERIOD_H4,      // 4 hours
   tf_d1  = PERIOD_D1,      // Daily
   tf_w1  = PERIOD_W1,      // Weekly
   tf_mn1 = PERIOD_MN1,     // Monthly
   tf_n1  = -1,             // First higher time frame
   tf_n2  = -2,             // Second higher time frame
   tf_n3  = -3              // Third higher time frame
};
//
//
extern enTimeFrames    TimeFrame          = tf_cu;   // Time frame
extern int             AdxPeriod        = 14;                // Adx period
extern bool            alertsOn         = true;              // Turn alerts on?
extern bool            alertsOnCurrent  = false;             // Alerts on current (still opened) bar?
extern bool            alertsMessage    = true;              // Alerts should display a message?
extern bool            alertsSound      = false;             // Alerts should play a sound?
extern bool            alertsEmail      = false;             // Alerts should send an email?
extern bool            alertsNotify     = false;             // Alerts should send notification?
extern string          soundFile        = "alert2.wav";      // Sound file
extern bool            arrowsVisible    = false;             // Arrows visible?
extern bool            arrowsOnNewest   = true;              // Arrows drawn on newest bar of higher time frame bar?
extern string          arrowsIdentifier = "adx Arrows1";     // Unique ID for arrows
extern double          arrowsUpperGap   = 0.5;               // Upper arrow gap
extern double          arrowsLowerGap   = 0.5;               // Lower arrow gap
extern color           arrowsUpColor    = clrLimeGreen;      // Up arrow color
extern color           arrowsDnColor    = clrOrange;         // Down arrow color
extern int             arrowsUpCode     = 159;               // Up arrow code
extern int             arrowsDnCode     = 159;               // Down arrow code

double Up[],Dn[],trend[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,0,AdxPeriod,alertsOn,alertsOnCurrent,alertsMessage,alertsSound,alertsEmail,alertsNotify,soundFile,arrowsVisible,arrowsOnNewest,arrowsIdentifier,arrowsUpperGap,arrowsLowerGap,arrowsUpColor,arrowsDnColor,arrowsUpCode,arrowsDnCode,_buff,_ind)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
{
   IndicatorBuffers(4);  
   SetIndexBuffer(0,Up);  SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,Dn);  SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,trend);
   SetIndexBuffer(3,count);
   
   indicatorFileName = WindowExpertName();
    TimeFrame         = (enTimeFrames)timeFrameValue(TimeFrame);
   
   IndicatorShortName(timeFrameToString(TimeFrame)+" Adx ("+(string)AdxPeriod+")");
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{ 
    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);
    }
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//

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)fmax(limit,fmin(Bars-1,_mtfCall(3,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 adxplus  = iADX(NULL,0,AdxPeriod,PRICE_CLOSE,MODE_PLUSDI, i);
      double adxminus = iADX(NULL,0,AdxPeriod,PRICE_CLOSE,MODE_MINUSDI,i);
      trend[i] = (i<Bars-1) ? (adxplus>adxminus) ? 1 : (adxplus<adxminus) ? -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(" crossing up");
      else  doAlert(" crossing 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("");
}
int timeFrameValue(int _tf)
{
   int add  = (_tf>=0) ? 0 : MathAbs(_tf);
   if (add != 0) _tf = _Period;
   int size = ArraySize(iTfTable); 
      int i =0; for (;i<size; i++) if (iTfTable[i]==_tf) break;
                                   if (i==size) return(_Period);
                                                return(iTfTable[(int)MathMin(i+add,size-1)]);
}


//-------------------------------------------------------------------
//                                                                  
//-------------------------------------------------------------------
//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,bool up)
{
   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_COLOR,theColor);
         if (up)
               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 =  StringConcatenate(Symbol()," ",timeFrameToString(_Period)," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," Adx ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsNotify)  SendNotification(message);
             if (alertsEmail)   SendMail(_Symbol+" Adx ",message);
             if (alertsSound)   PlaySound(soundFile);
      }
}

