How To Work With Time And Date In MQL5?

It is very important for you to master how to work with date and time in when coding expert advisors in MQL5. I hope you read my blog regularly. Did you read my post how to make 1000 pips with USDCHF in a week? When you are trading risk management is very important. Most traders happily open a trade with a big stop loss like 50-100 pips hopping that they will make 50-100 pips. Over the years this is what I have learned. You can reduce the stop loss to something like 10-20 pips. Always go for High Reward and Low Risk trades something like 100 pips with a 10 pip stop loss or even 200 pips with a 10 pip stop loss. This will give you the edge to beat the market. Price is the most important data that we have. We have this price data in the form of a time series. We need to know how to deal with data and time. I remember when I first developed my expert advisor, I put an alert function in it. The alert function will start giving a loud sound continuously. I didn’t know how to stop the sound. Then I realized that the EA is doing the calculation at each tick and since the condition is true for each tick, it will keep on giving the sound. By default, expert advisors are supposed to do all the calculations on each incoming tick. Most of the time we only want the expert advisor to do the calculations after a certain time interval. In this post I will show you how to do it. Did you read the post in which I explain detail a USDCAD sell trade that made 200 pips with a 10 pip stop loss.

MQL5

Datetime MQL5 Data Type

As said above for a financial time series timestamp is very important. We need to associated a date and a time with each currency pair price. This will tell us what was the currency pair price at that time. MQL5 saves the date and time as a UNIX time variable in seconds elapsed since 1st January 1970. Today when I am writing this post, UNIX time in seconds elapse since 1st January 1970 is 1510148342 seconds which translated to 11/8/2017 6:40 PM Local Time. But you don’t have to worry. MQL5 converts this UNIX time automatically for you into the format: yyyy:mm:dd hh:mm:ss. For example you can define present time like this:

// initializing a datetime variable       
datetime Today = D'2017:11:08 18:43:20';      //A

//we can also define today as below
datetime Today = D'';                          //B

// we can also use today time as below
datetime Today= D' 12:00';                     //C

// we can also use the __DATE__ predefined constant
datetime Today=__DATE__;                      //D

// we can also use the __DATETIME__ predefined constant
datetime Today=__DATETIME__                    //E

datetime TimeCurrent();
datetime TimeTradeServer();
datetime TimeLocal();
datetime TimeGMT();
int TimeGMTOffset();  // TimeGMTOffset() = TimeGMT() - TimeLocal()
int TimeDaylightSavings();

First we tell MQL5Compiler that we are defining a datetime data type. In A we explicit mention the date today. But we don’t have to do that. In B we just use the two inverted commas and MQL5 compiler will automatically know it is today. In C, we tell the compiler that we want today at 12 AM. We can also use the predefined __DATE__ constant like in D. Compiler will know it is today. In E we use __DATETIME__. This tells that compiler to use the present date and time. Note the two underscores before and after. TimeCurrent() function returns current server time while TimeTradeServer() returns the current server calculation time. TimeLocal() returns the current computer time. TimeGMT() returns the GMT time. TimeGMTOffset() returns the current time in GMT date and time that includes the day light savings time. TimeGMT() can be used to check for the start of London Market Open as Greenwitch is just outside London. 8:30 AM GMT is the London Market Open Time. If you are getting bored you can watch this Institute of Trading and Portfolio Management South Africa documentary.

MqlDateTime Structure

MQL5 has a number of predefined structures that includes a datetime structure. MqlDateTime structure is defined below:

struct MqlDateTime
{
int year;                  // Year
int mon;                  // Month
int day;                  // Day
int hour;                 // Hour
int min;                 // Minutes
int sec;                 // Seconds
int day_of_week;            // Day of week (0-Sunday, 1-Monday, ... 6-Saturday)
int day_of_year;           // Day number of the year (January 1st = zero)
};


// convert datetime into MqlDateTime structure         //A
datetime dtTime1 = D'2017.11.09 16:36:23';
MqlDateTime timeStruct1;
TimeToStruct(dtTime1,timeStruct1);
int day1 = timeStruct1.day;
int hour1 = timeStruct1.hour;
int dayOfWeek1 = timeStruct1.day_of_week;              //A

// convert MqlDateTime  to datetime
MqlDateTime timeStruct2;                               //B
timeStruct2.year = 2017;
timeStruct2.mon = 11;
timeStruct2.day = 09;
timeStruct2.hour = 2;
timeStruct2.min = 30;
timeStruct2.sec = 0;
datetime dtTime2 = StructToTime(timeStruct2);          //B

As you can see above, MqlDateTime structure provides us with a lot of information like the year, month, day, hour, minutes and seconds as well as which day of the week like Monday, Tuesday etc it is. It also tells us how many days we are since January 1st.  Below the definition in A,  I show you how we can convert any datetime date type into a MqlDateTime structure. We use the TimeToStruct() function to convert datetime into a MqlDateTime structure. In the same manner, we can use StructToTime() to convert an MqlDateTime structure into a datetime  data type. I have shown that how to do that in B. Did I tell you this that MQL5 compiler saves datetime data as a UNIX time and we cannot see it. But we can convert it to a string and it will converted to the usual date and time format that we are familiar with. Risk management is very important as I said at the start of this post. You can watch this 40 minute video tutorial on risk management.

How To Trade On New Bar?

By default an expert advisor does all the calculations on each new tick and will try to open a new order on each new tick until and unless you program it to do otherwise. We will use the Data and Time as a timestamp and save it as a global variable by defining it as a class variable. When the timestamp changes this will inform us that a new bar has been created. When the new bar gets created our expert advisor immediately does all the calculations based on its algorithm using the close of the previous bar. So instead of making the calculations on each tick we program the expert advisor to make the calculations on each new bar. Time series in general and financial time series in particular such as stock prices and currency pair prices have a timestamp associated wit it that identifies the time series order. Without a timestamp we have no way of knowing which is the order of the series. This is what we do. We create a cNewBar class. This is how we do it:

// class declaration for CBarNew class

class CBarNew                                    //A
{
       private:
              datetime aTime[], lastTime;
       public:
              void CBarNew();
              bool CheckBarNew(string fSymbol, ENUM_TIMEFRAMES fTimeframe);
};

//class constructor
void CBarNew::CBarNew(void)                      //B
{
               ArraySetAsSeries(aTime,true);
}

// function to check the start of new bar
bool CBarNew::CheckBarNew(string fSymbol, ENUM_TIMEFRAMES fTimeframe)      //C
{
               bool Run = false, BarNew = false;
               CopyTime(fSymbol,fTimeframe,0,2,aTime);
               if(lastTime == 0) firstRun = true;
               if(Time[0] > lastTime)
              {
                   if(firstRun == false) BarNew = true;
                   lastTime = aTime[0];
              }
       return(newBar);
}

In A, we define the CBarNew class. It has two datetime variables. One is an array aTime[]. aTime[] saves the timestamp of the current bar and previous bars. The other datetime variable lastTime saves the timestamp of the most recently checked bar. In B, we define the constructor for the class CBarNew. The constructor sets the datetime arrary aTime[] as a series array. CheckBarNew() checks the opening of a new bar in C. This is what we do. We define a local boolean variable Run and BarNew. We the function runs for the first time, it sets Run to false and the BarNew to false. Then it copes the timestamps to our aTime[] array. Then checks whether lastime variable is zero. If it is, it sets firstRun to true. Next it checks the timestamps. If aTime[0] is greater than the lastTime, we have the new bar and we copy the lastTime to aTime[0]. This is how we are going to use this BarNew class in our expert advisor!

// Include file and object declaration
#include <Timer.mqh>   // this is the file where we define the CBarNew class
CBarNew NewBar;

// Input variables
input bool TradeNewBar = true;

// OnTick() event handler
bool newBar = true;
int barShift = 0;
if(TradeNewBar == true)
{
              newBar = NewBar.CheckBarNew(_Symbol,_Period);
              barShift = 1;
}
if(newBar == true)
{
             // code for the new order
}

First we make a file Time.mqh where we define the CBarNew class. At the top we tell the compiler that it should look into this file for the definition of CBarNew class. Then we define a newBar object. We also define a boolean variable TradeNewBar. We set it to true so that our expert advisor only trades on a new bar. Rest of the code is easy to understand. Just keep this in mind. The bar is determined by the timeframe. So if we are trading on H4 timeframe, newBar means a new H4 candle. In the same manner if we are trading on M5 timeframe, a newBar means a new 5 minute candle. Did you watch the Million Dollar Mentoring Program Caribbean documentary? Learning MQL5 is a good idea. As a trader, you have a lot of ideas but you don’t know how to code them. Learning MQL5 will give you the skills to code your trading ideas into indicators and expert advisors. As a trader you cannot monitor the charts 24 hours. It is always a good idea to code your trading strategy into an indicator. Let the indicator monitor the charts and alert you when there is a good trade. Let’s create a function that returns the current date.

datetime createDateTime(int fHour = 0, int fMinute = 0)
{
        MqlDateTime timeStructure;
        TimeToStruct(TimeCurrent(),timeStructure);
        timeStructure.hour = fHour;
        timeStructure.min = fMinute;
        datetime currentTime = StructToTime(timeStructure);
        return(currentTime);
}

In the above code we tell the function to convert the hour and minute into a current date. We first create an MqlDateTime structure. Then we convert the TimeCurrent() predefined function into this structure and then we convert this structure to time. You might be wondering what is the use of this function. The purpose of this function is to help us create dates on which the expert advisor can open a trade as well as dates on which the expert advisor cannot open the trade. We can use this function to create different datetime for current date. How do we create different datetime for different dates. i show you how to do that below but that you can learn how to trade headline news and financial magazine cover stories. Can you code this strategy? I am sure this strategy cannot be coded.

// define a startTime and endTime variables
datetime startTime = createDateTime(23,0);
datetime endTime = createDateTime(10,0);
Print("Start: ",startTime,", End: ",endTime);

#define TIME_ADD_MINUTE 60    // 60 seconds
#define TIME_ADD_HOUR 3600    // 3600 seconds
#define TIME_ADD_DAY 86400    //86400 seconds
#define TIME_ADD_WEEK 604800  //604800 seconds

//if we want to add one day
endTime += TIME_ADD_DAY;
Print("Start: ",startTime," End: ",endTime);

//if we want to add 2 days
endTime += 2*TIME_ADD_DAY;

In the above code we define two times startTime which is today at 2300 hours and endTime and which is 1000 hours. Did you notice startTime is later than the endTime. Below we add some constants that are global. We use Time_ADD_DAY to add a day to the end time. Did you notice that the time is ins seconds. If you have read this post carefully I have said datetime is saved ins seconds since 1st January 1970. So if we want to add a day or two we will have to calculate how many seconds there are in a day and then add that to the datetime.

How To Create A Trade Timer Class?

We want our expert advisor to open trades during certain times of the day. How can we do that? In MQL5, it is easy to do. I will create a cTimer class that will check whether the time falls within the allowed range. If time falls within the allowed range, it will open a trade otherwise it will not open a trade.

class cTimer
{
            public:
            bool checkTimer(datetime fStartTime, datetime fEndTime, bool fLocalTime = false);
};

// now we define the checkTimer function
bool cTimer::checkTimer(datetime fStartTime, datetime fEndTime, bool fLocalTime = false)
{
         if(fStartTime >= fEndTime)
    {
                Alert("Error: Invalid start or end time");
                return(false);
     }
         datetime currentTime;
        if(fLocalTime == true) currentTime = TimeLocal();
        else currentTime = TimeCurrent();

        bool timerON = false;
       if(currentTime >= fStartTime && currentTime < fEndTime)
    {
            timerON = true;
    }
return(timerOn);
} 

// how to use the cTimer class in an expert advisor
#include <Timer.mqh>                                          //A
cTimer Timer;
input datetime startTime = D'2017.11.05 10:00';
input datetime endTime = D'2017.11.07 18:00';
// OnTick() event handler
bool timerON = Timer.checkTimer(startTime,endTime,false);
if(timerON == true)
{
// code for opening a new buy/sell order
}

In the above code we have defined a class cTimer class. It has got a checkTimer() function that check whether we are within the dates that we have chosen.If the time is within the two times that we have specified, createTimer() function will return a boolean timerON as true. This is all what we want. In A, I show how to use the cTimer class to create the two datetime and then use it in an expert advisor. As you can see the cTimer class definition is provided into the Timer.mqh files. Watch this Institute of Trading and Portfolio Management Brazil documentary.

Now if you have been trading for a while, you know big moves in the curreny market happen after the London Market Open and during the New York Market Session. Asian Market Session which is also known as the Tokyo Market Session is slow meaning no significant market movement takes place during that time. If you remember two yeas back GBPUSD faced a Flash Crash during the Asian Market Sesion. Now I will show to do it with the cTimer class. Below is the code:

class cTimer
{
       // private variables for the cTimer class
        private:
          datetime StartTime, EndTime;
          bool TimerStarted;
          void printTimerMessage(bool fTimerON);
        public:
       // checkTimer function declaration
          bool checkTimer(datetime fStartTime, datetime fEndTime, bool fLocalTime = false);
       // dailyTimer function declaration   
          bool dailyTimer(int fStartHour, int fstartMinute, int fendHour, int fendMinute,
          bool flocalTime = false);
        // startTime and endTime get methods
          datetime GetStartTime() {return(startTime);};
          datetime GetEndTime() {return(endTime);};
};

//this is how we will define dailyTimer() function:
bool cTimer::dailyTimer(int fstartHour, int fsartMinute, int fendHour, int fendMinute,
bool flocalTime = false)
{
datetime currentTime;
if(flocalTime == true) currentTime = TimeLocal();
else currentTime = TimeCurrent();
startTime = createDateTime(fstartHour,fstartMinute);
endTime = createDateTime(fendHour,fendMinute);


if(endTime <= startTime) { startTime -= TIME_ADD_DAY; if(currentTime > endTime)
{
       startTime += TIME_ADD_DAY;
       endTime += TIME_ADD_DAY;
}
}
       bool timerON = checkTimer(startTime,endTime,flocalTime);
       printTimerMessage(timerON);
       return(timerON);
}

// define the printTimerMessage
void CTimer::printTimerMessage(bool fTimerON)
{
        if(fTimerON == true && timerStarted == false)
{
                string message = "Timer started";
                Print(message);
                Comment(message);
                timerStarted = true;
}
        else if(fTimerON == false && timerStarted == true)
{
                string message = "Timer stopped";
                Print(message);
                Comment(message);
                timerStarted = false;
}
}
//how to use dailyTimer() function in expert advisor
#include <Timer.mqh>
cTimer Timer;
input bool useTimer = false;
input int startHour = 0;
input int startMinute = 0;
input int endHour = 0;
input int endMinute = 0;
input bool useLocalTime = false;

// OnTick() event handler
bool timerON = true;
if(useTimer == true)
{
      timerON = Timer.dailyTimer(startHour,startMinute,endHour,endMinute,useLocalTime);
}
if(timerON == true)
{
      // code for placing the order
}

You can read the above code. We have developed the cTimer class more with the addition of a printTimerMessage() that tells us whether the timer is on or not. With this dailyTimer() function you will be able to control the times when the expert advisor will open a trade or not. Now dailyTimer() function allows you to trade within a time range. But what if you want to trade in a number of time ranges each day or each week avoiding the time when there is a high volatility news. Below we define a timerBlock() structure that will help us do precisely that.

// timerBlock structure 
struct timerBlock                                        //A
{
bool enabled; // Enable or disable timer block
int start_day; // Start day (1: Monday... 5: Friday)
int start_hour; // Start hour
int start_min; // Start minute
int end_day; // End day
int end_hour; // End hour
int end_min; // End minute
};

sinput string Block1; // Timer Block 1--what is this sinput read the explanation below
input bool useTimer1 = true;                                //B
input ENUM_DAY_OF_WEEK startDay1 = 5;
input int startHour1 = 8;
input int startMinute1 = 0;
input ENUM_DAY_OF_WEEK endDay1 = 5;
input int endHour1 = 12;
input int endMinute1 = 25;


sinput string Block2; // Timer Block 2--another sinput
input bool useTimer2 = true;                                //C
input ENUM_DAY_OF_WEEK startDay2 = 5;
input int startHour2 = 13;
input int startMinute2 = 0;
input ENUM_DAY_OF_WEEK endDay2 = 5;
input int endHour2 = 18;
input int endMinute2 = 0;
input bool ueLocalTime = false;

In the above code did you notice sinput? Input variable allows us to set external program parameters when starting the expert advisor. These input parameters are also uses in Strategy Tester optimization. When we want the input parameters to be excluded from being used in Strategy Tester optimization we use sinput modifier. In A we define the timerBlock structure. It has a boolean variable that sets the timerBlock on and off. Then we have the start day and the end day. We can define many timerBlock structures. In B we define the first timerBlock structure. This timerBlock starts on Friday at 8000 hours and ends at 1200 hours. In C, we define a second timerBlock structure. This timerBlock also starts on Friday but at 1300 hours and ends at 1800 hours. So there is only one hour gap between the two timerBlocks. Maybe during the one when the timerBlocks are off, we have NFP report. We don’t want to trade it as most of the time market is highly volatile during this time.

// we tell the compiler to include the following file
#include <Timer.mqh>

// first we define global variables
timerBlock Block[2];

// OnInit() event handler
Block[0].enabled = useTimer;
Block[0].start_day = startDay;
Block[0].start_hour = startHour;
Block[0].start_min = startMinute;
Block[0].end_day = endDay;
Block[0].end_hour = endHour;
Block[0].end_min = endMinute;
Block[1].enabled = useTimer2;
Block[1].start_day = startDay2;
Block[1].start_hour = startHour2;
Block[1].start_min = startMinute2;
Block[1].end_day = endDay2;
Block[1].end_hour = endHour2;
Block[1].end_min = endMinute2;

// OnTick() event handler
bool timerON = true;
if(useTimer == true)
{
timerON = Timer.blockTimer(Block,useLocalTime);
}

bool cTimer::blockTimer(TimerBlock &fBlock[], bool fLocalTime = false)
{
MqlDateTime today;
bool timerON = false;
int timerCount = ArraySize(fBlock);


for(int i = 0; i < timerCount; i++)
{
    if(fBlock[i].enabled = false) continue;
    startTime = createDateTime(fBlock[i].start_hour, fBlock[i].start_min);
    endTime = createDateTime(fBlock[i].end_hour, fBlock[i].end_min);
    TimeToStruct(StartTime,today);
    int dayShift = fBlock[i].start_day - today.day_of_week;
    if(dayShift != 0) startTime += TIME_ADD_DAY * dayShift;
    TimeToStruct(endTime,today);
    dayShift = fBlock[i].end_day - today.day_of_week;
    if(dayShift != 0) endTime += TIME_ADD_DAY * dayShift;
    timerON = checkTimer(startTime,endTime,flocalTime);
    if(timerON == true) break;
}
 PrintTimerMessage(timerON);
 return(timerON);
}

Above is the MQL5 code in which we use the timerBlock structure. First we include the TImer.mqh files that has all the definitions. After that we define a Block[] array and declare it as timerBlock structure. Now in the above code we have been using OnTick() event handler. When we use OnTick() event handler, our expert advisor will do all the calculations on each new tick. We can also use OnTimer() event handler. Learning MQL5 is a good idea. By learning MQL5, you get the skills to code your own trading strategies. Don’t hesitate. Start learning MQL5 today!