//+------------------------------------------------------------------+
//|                                             Event_Tracker_V3.mq4 |
//|                                  Copyright © 2009, Kenny Hubbard |
//|                                        http://www.compu-forex.com|
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Kenny Hubbard"
#property link      "http://www.compu-forex.com"

extern string  Note1          = "====Alert Options====";
extern bool    Std_MT4_Alert  = true;
extern bool    Custom_Sound   = false;
extern string  Sound_File     = "alert2.wav";
extern bool    Use_Email      = false;

int 
   Order_State_Prev[][2],
   Order_State_New[][2];

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
   if (Std_MT4_Alert && Custom_Sound){
      Custom_Sound = false;
      Print("Custom_Sound has been de-activated by Std_MT4_Alert option");
   }
}
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
int
   Index,
   Order_Count = Pending_Count();//===================== count the number of pending orders
   ArrayResize(Order_State_New,MathMax(Order_Count,1));//make the fresh order array the same size as the number of pending orders
   Index = 0;
   for(int i=0;i<=OrdersTotal()-1;i++){//load the pending trades into a fresh array(to be copied later for comparison on next tick)
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
            if(OrderType()<2)continue;//not a pending order so move on
            if(OrderType()>5)continue;//not a pending order so move on(covers apparently undocumented ordertypes with val >5)
            Order_State_New[Index][0] = OrderType();
            Order_State_New[Index][1] = OrderTicket();
            Index++;
      }
   }
  if (!Has_Changed(Order_Count)){//if num pending orders is unchanged since last tick>>nothing has changed>>copy array and move on
   ArrayResize(Order_State_Prev,MathMax(Order_Count,1));
   ArrayCopy(Order_State_Prev,Order_State_New,0,0,WHOLE_ARRAY);
   return(0);
   }
   for(int i_2=0;i_2<=Order_Count;i_2++){//num pending orders is less>>>search open orders for known previous pending order ticket no
      if(OrderSelect(Order_State_Prev[i_2][1],SELECT_BY_TICKET)){
         if(OrderType()!=Order_State_Prev[i_2][0]){
            Alert_User(" triggered at " ,OrderTicket(),OrderOpenTime());//prev pending ticket is found as an open order>>alert user
         }
      }
   }
   ArrayResize(Order_State_Prev,MathMax(Order_Count,1));//======copy fresh array to prev order array and wait for new tick
   ArrayCopy(Order_State_Prev,Order_State_New,0,0,WHOLE_ARRAY);
   return(0);
}
//+------------------------------------------------------------------+
int Pending_Count()//counts the number of current pending orders>>dynamic array sizing
{
int cnt = 0;
   for(int i=0;i<=OrdersTotal()-1;i++){
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){
            if(OrderType()<2)continue;//not a pending order so move on
            if(OrderType()>5)continue;//not a pending order so move on(covers apparently undocumented ordertypes with val >5)
            cnt++;
      }
   }
   return(cnt);
}
//+------------------------------------------------------------------+
bool Has_Changed(int Orders_Current)//check for change in num pending orders since last tick
{
static int 
   Prev_Pending_Count;
   
   if (Orders_Current > Prev_Pending_Count){    //pending orders increased>>adjust Prev_Pending_Count for next tick>>return false
      Prev_Pending_Count = Orders_Current;
      return(false);
   }
   if (Orders_Current < Prev_Pending_Count){    //pending orders decreased>>adjust Prev_Pending_Count>>return true
      Prev_Pending_Count = Orders_Current;
      return(true);
   }
   return(false);                               //no change in pending orders
}
//+------------------------------------------------------------------+
void Alert_User(string Type, int order_num, int order_time) //alert user according to preferences
{
string
   Text = StringConcatenate("Pending Order ", order_num, Type, TimeToStr(order_time,TIME_DATE|TIME_MINUTES));
   
   if(Std_MT4_Alert)                                        //standard MT4 alert
      Alert(Text);
   if(Custom_Sound)                                         //custom sound
      PlaySound(Sound_File);
   if(Use_Email)                                            //send email
      SendMail("Pending Order Alert", Text);
}
//+------------------------------------------------------------------+