Setting Trading Times

 

Hi all, a week into coding in MQL5 and struggling with setting trading times. For this particular strategy i only want it trading the US open, so need it to start at 9:30am local time, and finish at 9:45am (i prefer using local time as i am in a different time zone so don't want to have to account for daylight savings changes etc). The code i have so far is below, and i am aware it is completely useless and feels to be a long way off. Any ideas? 


TIA


   bool TimeToTrade()
   {

      datetime tm=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
      if(tm >= 09:30 && tm < 09:45)
         return(true);
      return(false);

  }
//here is other code i have working checking other values

//Code to trade

bool  Buy_Condition_1 = (TimeToTrade() = true);

if (Buy_Condition_1)
 {
//etc
 

09:30 is not a valid MQL5 formate! Read about the way time is treated in MQ: https://www.mql5.com/en/docs/dateandtime.

You can even read my articles about time:

https://www.mql5.com/en/articles/9926
https://www.mql5.com/en/articles/9929

Documentation on MQL5: Date and Time
Documentation on MQL5: Date and Time
  • www.mql5.com
Date and Time - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
  1. When dealing with time, a lot of people use strings; they can not be optimized. Using (int) seconds or (double) hours and fraction can be inputs.

    invalid
          datetime tm=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
          if(tm >= 09:30 && tm < 09:45)
             return(true);
          return(false);
    
    Try
          const int HR0930=34200, HR0945=35100; // (9*3600+45*60)
          datetime tm=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
          int          now=time(tm);
          return now >= HR0930 && now < HR0945;
    

    See also Dealing with Time (Part 1): The Basics - MQL5 Articles (2021.10.01)
    Dealing with Time (Part 2): The Functions - MQL5 Articles (2021.10.08)
    MQL5 Programming Basics: Time - MQL5 Articles (2013.04.26)

  2. bool  Buy_Condition_1 = (TimeToTrade() = true);

    You should be able to read your code out loud and have it make sense. You would never write if( (2+2 == 4) == true) would you? if(2+2 == 4) is sufficient. So don't write if(bool == true), just use if(bool) or if(!bool). Code becomes self documenting when you use meaningful variable names, like bool isLongEnabled where as Long_Entry sounds like a trigger price or a ticket number and “if long entry” is an incomplete sentence.

 
Carl Schreiber #:

09:30 is not a valid MQL5 formate! Read about the way time is treated in MQ: https://www.mql5.com/en/docs/dateandtime.

You can even read my articles about time:

https://www.mql5.com/en/articles/9926
https://www.mql5.com/en/articles/9929

Hi Carl, thanks for your response. I've been working on this the past few days with varying success. My main issue though is i'm wondering if there is any method to define a local time period? In other coding languages such as ProRealCode you are able to globally set, for example, a local time to match the market you are trading. Thus, no allowances need to be made for daylight savings time or similar as it runs the backtest as if in local market hours. 

I'd assumed that using the SYMBOL_TIME function would return this local market time but on closer inspection its actually returning the local time for the server it comes from (UTC+2), and not for east coast America (UTC-5).

Is there any function or way of doing this that i'm missing or will i really have to manually alter trading times to adjust for DST twice a year? Live trading is not the issue as i am able to start and stop the system on a daily basis (so could use my local time), so instead its important for back testing purposes. Clearly only trading a significantly small window means the times need to be very accurate or the results will be meaningless.

 
William Roeder #:
  1. When dealing with time, a lot of people use strings; they can not be optimized. Using (int) seconds or (double) hours and fraction can be inputs.

    invalid
    Try

    See also Dealing with Time (Part 1): The Basics - MQL5 Articles (2021.10.01)
    Dealing with Time (Part 2): The Functions - MQL5 Articles (2021.10.08)
    MQL5 Programming Basics: Time - MQL5 Articles (2013.04.26)

  2. You should be able to read your code out loud and have it make sense. You would never write if( (2+2 == 4) == true) would you? if(2+2 == 4) is sufficient. So don't write if(bool == true), just use if(bool) or if(!bool). Code becomes self documenting when you use meaningful variable names, like bool isLongEnabled where as Long_Entry sounds like a trigger price or a ticket number and “if long entry” is an incomplete sentence.

Hi William, thanks for your response. Similar as with Carl's response i've spent a few days working on your solution but being new to MQL5 i found it returned endless errors I was too novice to solve. I have however adapted it as below.

As for point 2 concerning bools this was very helpful and i've changed my code to follow, and will certainly make use of this in future also.

The issue i now have is that it doesn't seem to want to open any trades at all in back testing and I'm banging my head against the wall trying to figure out why. The code below compiles fine but doesnt seem to do anything. Again, this isn't the entirety of my code as i'm doing it in stages to ensure its working.. lucky, given it isnt :(  Any help would be appreciated! 

TIA

input char   Lot=25;

double p_close;
int STP, TKP;

double CheckHigh;
double CheckLow;
double Distance;

string symbol="US30.cash";

//Trading times
datetime tm=(datetime)SymbolInfoInteger(symbol,SYMBOL_TIME);
int now=tm;
string today=TimeToString(tm,TIME_DATE);
datetime tm2=StringToTime(today); //i'm aware converting to string then back to time isnt efficient but i cant figure out the code
int now2=tm2;    //I'm essentially finding the seconds up to 00:00 today then adding on the required seconds for opening
const int HR0930=34200, HR0945=35100;
int open=now2+HR0930, close=now2+HR0945;

#include <Trade/Trade.mqh>
CTrade trade;

      //--Determining when it can trade
bool TimeToTrade()
{  
   if (now>=open && now<close)
            return(true);
   return(false);
}
   
void OnDeinit(const int reason)
{}

void OnTick()
  {
  
    MqlRates mrate[];
    ArraySetAsSeries(mrate,true);
    
    if(CopyRates(symbol,_Period,0,8,mrate)<0)
     {
      Alert("Error copying rates/history data - error:",GetLastError(),"!!");
      return;
     }     
     
    CheckHigh = mrate[4].high; //check the high from 8:30
    CheckLow = mrate[1].low; //check the low from 9:15
    Distance = CheckHigh-CheckLow;
        

    int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
    double bid=SymbolInfoDouble(symbol,SYMBOL_BID);
    double SL=bid-5000*point;
    double TP=bid+5000*point; 

   bool Buy_Condition_1 = (TimeToTrade()); //checks trading time
   bool Buy_Condition_2 = (PositionSelect(symbol) == false); //check theres no open positions
   bool Buy_Condition_3 = (Distance<150); //checks there hasnt been a significant move lower since 8:30am (when news generally comes out)

   if(Buy_Condition_1) // && Buy_Condition_2 && Buy_Condition_3)
     {
      if(Buy_Condition_2)
         {
            if(Buy_Condition_3)
                {
         
               trade.Buy(Lot,symbol,0.0,SL,TP,"");

                }
         }
     }
  }
         

 


 

 
//i'm aware converting to string then back to time isnt efficient but i cant figure out the code
The first link I previously gave has that code.
 
William Roeder #:
The first link I previously gave has that code.

Hi William, apologies i'm sure this is all rather trivial for you but i'm afraid i'm still not getting it. When i use your code i get the errors that 'time' is an undeclared identifier and that for 'tm' some operator is expected..?

As for the provided link I notice that Time is shown in PINK however its in black in my code - i dont know what this means? I'm clearly missing something obvious...

Also, any ideas why the rest of the code isn't producing any trades in back testing? Anything stand out as wrong?

TIA

 
JimboDiggity #: When i use your code i get the errors that 'time' is an undeclared identifier and that for 'tm' some operator is expected..?

Do you really expect an answer? There are no mind readers here and our crystal balls are cracked. Always post all relevant code (using Code button) or attach the source file.

We can't see your broken code.

 

Here is a function you can use for the check .

The comments outnumber the code a bit but its for describing the steps you take.

Enjoy 

🍺

 

/*
Basic stuff you already know probably time in meta trader is in seconds since 1970.1.1
So if you say i have a variable integer and you call it timeA=0; then mt4 knows you are talking about 
1970
So you can neatly play with this and ignore the time shifts or daylight savings.
If there is a clock , for instance , your pc and it goes back one hour (automatically) 
then when you request the time from meta trader it will have shifted one hour backwards or 3600 seconds toward the past
Why on earth does it matter ? 
Let's see , you want a function that tells you true or false when your local time is within a time window.
As william said , you need to return a boolean (true/false)
And for simplicity's sake lets have the function receive 4 integers that represent your time limits 
(since you don't care about days , so far)
So , it should return a boolean : 
*/
bool isThisTimeInMyTimeWindow(datetime this_time,//the first thing you need which time is checked 
                                   int from_hours,//we are keeping it simple here 24 h format tho
                                   int from_minutes,//
                                   int to_hours,//hour to , 24 h format again
                                   int to_minutes){
  bool example_prints=true;
  if(example_prints)
    {
    Print("------");
    Print("Received Time "+TimeToString(this_time,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
    Print("---to be tested from ("+IntegerToString(from_hours)+":"+IntegerToString(from_minutes)+":00)");
    Print("------------------to ("+IntegerToString(to_hours)+":"+IntegerToString(to_minutes)+":00)");
    }
//now your function has received everything it needs , and , it's name is clear as day     
/*so if your significant other were to find this function they would say "this probably tells me if this time is in a time window"
  and i have to provide the time , the start of the window and the end of the window , awesome .
  And about now is the time to dribble the ball.
  You know that this_time is a number of seconds regardless of timezones and shifts .
  If this number arrived in this function we are only concerned with one thing alone .
  Is it in the time window ?
  How it got here or why you sent it here or improving on what you send here , or whether or not this would crash the cpu on a jumbo jet 747
  from 60 years ago is another discussion :)
  
  So ,if we have the number 13 and we want to know on which digit its sitting on but we don't really need to know how 
      many decades (sets of 10's) is it sitting on (so it could be 13 23 33) what would we do? 
  We would divide it by 10 , floor it and then subtract the result x 10 by the original . We would get 3 ! 
  We can do the same with days , a day is , hold on , 86400 seconds .
  So if we divide the seconds of the timestamp (which is what it is ,seconds) by 86400 
  and then we floor the result we will get the number of days in this_time .
  like so :
*/                 //so we need an int of the Floor of the timestamp by the days seconds
  
  int days_in_time=(int)MathFloor(((double)this_time)/86400.0);     
  if(example_prints){Print("Days in time : "+IntegerToString(days_in_time));}              
  //can it be done better ? always
  /*
  you now know the days in this_time
  and this calculation will always point to the start of this day magically.(since it measures completed days of 86400 seconds)
  Which means , if you subtract (days_in_time x 86400) from your timestamp (this_time) you will be left with how 
  many seconds have passed so far in this_time up to the moment the function received it .
  Pair that with william's seconds check and you have what you need 
  So 
  */
  int seconds_in_this_time=((int)this_time)-(days_in_time*86400);
  if(example_prints){Print("Left seconds in this time : "+IntegerToString(seconds_in_this_time));}
  //you turn the from into seconds too 
  int seconds_from=from_hours*3600+from_minutes*60;//easy right ?
  int seconds_to=to_hours*3600+to_minutes*60;//
  if(example_prints)
    {
    Print("Seconds From : "+IntegerToString(seconds_from));
    Print("Seconds To   : "+IntegerToString(seconds_to));
    }
  /* Then you compare your seconds_in_this_time if its within the seconds from and seconds to 
     But at this point you may realize that there is a potential issue 
     What happens if the starting time is 23:00 and the ending time is 05:00 (of the next day)
     well ,you can detect that . 
     If the seconds to is smaller than the seconds from then this is a separate case 
     Let's write up the easy one first : 
  */
  //if normal second comparison
    if(seconds_to>=seconds_from){
      if(example_prints){Print("Normal Comparison Used");}
    //just being in between is enough 
      if(seconds_in_this_time>=seconds_from&&seconds_in_this_time<=seconds_to){
      if(example_prints){Print("Valid");}
      return(true);//that part is done 
      }
    }
  //and the hard part
    else{//so if seconds_to is smaller than seconds from 
      if(example_prints){Print("Weird Comparison Used");}
    /*
    we consider what we do , we "flatten" the time to the start of the day
    which means if the limits are 23:00->05:00 and its Tuesday
    then the time will be valid between 23:00:00 and 23:59:59 on Tuesday 
    and 00:00:00 to 05:00:00 on Wednesday
    That means we can compare the from as if it were ending at the end of the day and the to as if it were starting at 
    the start of the day.
    handy so the end of the day in seconds is , 86400 , easy and the start is 0 
    
    */ 
    if((seconds_in_this_time>=seconds_from&&seconds_in_this_time<=86400)||(seconds_in_this_time>=0&&seconds_in_this_time<=seconds_to)){
    //so if at the end of the day portion or start of the day portion , return valid 
    if(example_prints){Print("Valid");}
    return(true);
    }}
//anything else return false . done now you just call it with the TimeLocal and see what it says
if(example_prints){Print("NOT Valid");}
return(false);
}
int OnInit()
  {
  //tests 
    bool is_valid_time=isThisTimeInMyTimeWindow(TimeLocal(),9,30,9,45);//09:30 to 09:45
         is_valid_time=isThisTimeInMyTimeWindow(TimeLocal(),13,0,21,0);//13:00 to 21:00
         is_valid_time=isThisTimeInMyTimeWindow(TimeLocal(),23,0,4,0);//23:00 to 04:00 
    
  return(INIT_SUCCEEDED);
  }
 
William Roeder #:

Do you really expect an answer? There are no mind readers here and our crystal balls are cracked. Always post all relevant code (using Code button) or attach the source file.

We can't see your broken code.

Mind readers? As mentioned i used your code but will repost..

      const int HR0930=34200, HR0945=35100; // (9*3600+45*60)
      datetime tm=(datetime)SymbolInfoInteger(_Symbol,SYMBOL_TIME);
      int          now=time(tm);
      return now >= HR0930 && now < HR0945;

As i say, i get the error that 'time' is an undeclared identifier and that for 'tm' some operator is expected (all related to the third line).

Then, again using the link you provided, Time is shown in Pink font colour.. Is this anything to do with it as its black on mine? What does the pink mean?

Find bar of the same time one day ago - How to find the date of one day ago at the same time?
Find bar of the same time one day ago - How to find the date of one day ago at the same time?
  • 2017.10.06
  • www.mql5.com
Save the time, find yesterday date, find the correct time. I have a log function which logs date of day and time of day when oncalculate is called. So what i expected was: date of day time[rates_total-1-0) = 2014
 
Lorentzos Roussos #:

Here is a function you can use for the check .

The comments outnumber the code a bit but its for describing the steps you take.

Enjoy 

🍺

 

Hi Lorentzos, thanks for your detailed explanation. Reading it however makes me think i'm perhaps looking at the back testing data incorrectly..

To be fully clear on my issue; i am trying to back test my strategy, and it needs to trade within the window 9:30am-9:45am UTC-5. I am currently in UTC+4, and my broker provides data UTC+2.

I guess the question is, when running a back test where does the data come from? Is it provided by MetaTrader in local times to the market/symbol, or does it come from my broker? I.e. to run a back test on the US30.Cash will i need to adjust the code you provided to local UTC-5 times (i.e. its provided from my broker and therefore DST will also need to be adjusted for), or can i code it as you describe and it will understand it is for the UTC-5 timezone because that's the timezone of the market (US30)?

A bit wordy but hopefully that's clear..?

Reason: