Break up a bar into equal intervals. Trigger event at start of new interval.

 

Hello all.  Any help appreciated...

I have a multi-symbol, chart independent EA.

It has many inputs. There's two relevant to this question. Let's call them T = timeframe or bar seconds, and N = "action intervals per bar".

I want to break each bar up into N intervals or blocks of time, and perform an action at the start of each of those intervals.

So for example, if T = 1800 (ie. 30 minute bars), and N = 15, then I want an action to happen every 1800/15 = 120 seconds. (ie. 30 minutes / 15 = every 2 minutes).  It's important that it is in synchronization with the bar -- ie. the start of the bar at, say, 16:00:00 (4pm) starts the first of those 15 two minute intervals and the 15th one ends at exactly 16:30:00 at which time the first interval of the next bar starts.  Another example: T = 300 (seconds = 5 minute bars), N = 10 times per bar, meaning my action would run every 30 seconds.  (If the user enters a number N that doesn't divide evenly into the T, then the strategy won't work, I'll warn the user with an alert, and require them to re-enter appropriate numbers).

I can't just do EventSetTimer() and OnTimer() for a few reasons, but one of those reasons is the above -- there's no guarantee of when each iteration of the timer will start and end. Another reason is that I actually need to do what I'm describing here with multiple intervals at once.  eg. doing something every 30 seconds, something else every two minutes, something else every five minutes, or whatever.

One way I've come up with to achieve this is run the native OnTimer() timer every, say, 100 milliseconds (EventSetMillisecondTimer(100)) and then each iteration of that I could check if we've just started a new interval. Catching the start of each interval within 100 milliseconds will suffice. The end of the interval is irrelevant. This is entirely about triggering the action within a fraction of a second of the interval starting.

However... I can't just figure out how to do the "check if we've just started a new interval" part. How do I do that?  

One way is to compare the start time of the current bar against the current time, and with some math I can figure it out, but maybe I'm missing something... The functions for getting the start time of the current bar (including the iTime() function), give me the bar time in EET timezone as far as I can tell. Meanwhile I can get the current time in my local time zone, the broker's time zone, or UTC time zone, but there doesn't seem to be any reliable way to get the time now in EET time zone. On the flip side I can't find any way to get the current bar's start time in my local time zone. All options I can think of for doing either of those feel like unreliable overkill hacks, and so I'm sure I must have missed something here -- either in getting comparable times in the same time zone, or in the bigger picture of getting the start of each interval.

I'd welcome any direction!  Thanks!

 
DetnatorOne way I've come up with to achieve this is run the native OnTimer() timer every, say, 100 milliseconds (EventSetMillisecondTimer(100)) and then each iteration of that I could check if we've just started a new interval. Catching the start of each interval within 100 milliseconds will suffice. The end of the interval is irrelevant. This is entirely about triggering the action within a fraction of a second of the interval starting. However... I can't just figure out how to do the "check if we've just started a new interval" part. How do I do that?  

There is no true real solution to the problem. You will have to depend on a fixed frequency OnTimer event handling. You can simply use a datetime of the current time (e.g. TimeTradeServer) and divide (integer division) that datetime by your timer duration and the resulting value will only change on the desired synchronised interval.

 
Detnator:

Hello all.  Any help appreciated...

I have a multi-symbol, chart independent EA.

It has many inputs. There's two relevant to this question. Let's call them T = timeframe or bar seconds, and N = "action intervals per bar".

I want to break each bar up into N intervals or blocks of time, and perform an action at the start of each of those intervals.

So for example, if T = 1800 (ie. 30 minute bars), and N = 15, then I want an action to happen every 1800/15 = 120 seconds. (ie. 30 minutes / 15 = every 2 minutes).  It's important that it is in synchronization with the bar -- ie. the start of the bar at, say, 16:00:00 (4pm) starts the first of those 15 two minute intervals and the 15th one ends at exactly 16:30:00 at which time the first interval of the next bar starts.  Another example: T = 300 (seconds = 5 minute bars), N = 10 times per bar, meaning my action would run every 30 seconds.  (If the user enters a number N that doesn't divide evenly into the T, then the strategy won't work, I'll warn the user with an alert, and require them to re-enter appropriate numbers).

I can't just do EventSetTimer() and OnTimer() for a few reasons, but one of those reasons is the above -- there's no guarantee of when each iteration of the timer will start and end. Another reason is that I actually need to do what I'm describing here with multiple intervals at once.  eg. doing something every 30 seconds, something else every two minutes, something else every five minutes, or whatever.

One way I've come up with to achieve this is run the native OnTimer() timer every, say, 100 milliseconds (EventSetMillisecondTimer(100)) and then each iteration of that I could check if we've just started a new interval. Catching the start of each interval within 100 milliseconds will suffice. The end of the interval is irrelevant. This is entirely about triggering the action within a fraction of a second of the interval starting.

However... I can't just figure out how to do the "check if we've just started a new interval" part. How do I do that?  

One way is to compare the start time of the current bar against the current time, and with some math I can figure it out, but maybe I'm missing something... The functions for getting the start time of the current bar (including the iTime() function), give me the bar time in EET timezone as far as I can tell. Meanwhile I can get the current time in my local time zone, the broker's time zone, or UTC time zone, but there doesn't seem to be any reliable way to get the time now in EET time zone. On the flip side I can't find any way to get the current bar's start time in my local time zone. All options I can think of for doing either of those feel like unreliable overkill hacks, and so I'm sure I must have missed something here -- either in getting comparable times in the same time zone, or in the bigger picture of getting the start of each interval.

I'd welcome any direction!  Thanks!

That's a lot of text to ask about a coding issue. Please post your attempt if you need coding help.

You need to synchronize your timer with the broker server time. If you don't need millisecond precision it's perfectly doable, at worst you will have a shift of 1 second.

 
Alain Verleyen #:

That's a lot of text to ask about a coding issue. Please post your attempt if you need coding help.

Well... I don't really see it as a coding issue. The only coding question there as far as I can tell, comes down to: "are there any function(s) to give me bar time in my time zone or current time in EET time zone?"  Other than that the entire thing is an algorithm/logic question, isn't it?

I've tried multiple attempts from different angles, and if I'd posted the code for all of those, it would have been a LOT more text.  So I summarized the main approaches in a lot less words. 😉 

You need to synchronize your timer with the broker server time. If you don't need millisecond precision it's perfectly doable, at worst you will have a shift of 1 second.

I've thought about what you might mean here, but maybe I'm missing something. How is that possibly (logically, aside from code) when I need the equivalent of multiple timers, and MQL only allows one timer? Logically, ie. by definition, the only answer can be that somehow we have to simulate multiple timers, right?  So how might one do that? (Again, I don't need someone to write or debug my code. I need a design/logic/algorithm answer (that fits within MQL5's code limitations, like "only one timer possible")). 

 
Detnator #: I've thought about what you might mean here, but maybe I'm missing something. How is that possibly (logically, aside from code) when I need the equivalent of multiple timers, and MQL only allows one timer? Logically, ie. by definition, the only answer can be that somehow we have to simulate multiple timers, right?  So how might one do that? (Again, I don't need someone to write or debug my code. I need a design/logic/algorithm answer (that fits within MQL5's code limitations, like "only one timer possible")). 

You did not read my post! I gave you the answer, but I guess I will have to spell it out for you!

Example code. Not compiled or tested! You will have to structure the logic into a class or something depending on your need for multiple timers.
int
   nTimer1 = 15, // 15 seconds
   nTimer2 = 23; // 23 seconds

datetime
   dtDateTime = TimeTradeServer();

static long
   nCount1Curr = WRONG_VALUE,
   nCount2Curr = WRONG_VALUE;
   
long
   nCount1Prev = nCount1Curr, 
   nCount2Prev = nCount2Curr;

   nCount1Curr = (long) dtDateTime / nTimer1; 
   nCount2Curr = (long) dtDateTime / nTimer2;
   
bool
   bInterval1 = nCount1Curr != nCount1Prev,
   bInterval2 = nCount2Curr != nCount2Prev;
   
if( bInterval1 ) { /* New Timer 1 Interval Event */ };
if( bInterval2 ) { /* New Timer 2 Interval Event */ };


Break up a bar into equal intervals. Trigger event at start of new interval.
Break up a bar into equal intervals. Trigger event at start of new interval.
  • 2022.03.01
  • www.mql5.com
Hello all. Any help appreciated... I have a multi-symbol, chart independent EA. It has many inputs. There's two relevant to this question...
 
Fernando Carreiro #:

There is no true real solution to the problem. You will have to depend on a fixed frequency OnTimer event handling. You can simply use a datetime of the current time (e.g. TimeTradeServer) and divide (integer division) that datetime by your timer duration and the resulting value will only change on the desired synchronised interval.

Hi Fernando.  Thanks.  This seems promising, though there might be a piece I'm missing.

CurrentTime(), numerically, returns number of seconds since 1/1/1970 0:00:00 but is not timezone specific, right?  

Consider this: 

void OnStart() {
    Print(TimeCurrent(),     ", ", (int)(TimeCurrent()).    );
    Print(TimeTradeServer(), ", ", (int)(TimeTradeServer()) );
    Print(TimeLocal(),       ", ", (int)(TimeLocal()).      );
    Print(TimeGMT(),         ", ", (int)(TimeGMT()).        );
}

I'm in USA Central time zone (GMT -6) and at this moment my output from that is: 

TimeCurrent,     2022.03.02 00:08:12, 1646179692
TimeTradeServer, 2022.03.02 00:08:12, 1646179692
TimeLocal,       2022.03.01 16:08:12, 1646150892
TimeGMT,         2022.03.01 22:08:12, 1646172492

The main problem here, I think, is that none of these are EET, which is what the bars seem to be based on, so there's no (easy) reliable way to get the current time in the same timezone as the bars time, meaning that there are at least some situations where I just can't line it up...?

 
Fernando Carreiro #:

You did not read my post! I gave you the answer, but I guess I will have to spell it out for you!

Example code. Not compiled or tested! You will have to structure the logic into a class or something depending on your need for multiple timers.


Hi Fernando.  I'm sorry.  I did read it, I was replying to your post after responding to Alain's.  😊   I've reviewed your code, and I see how it illustrates what you were trying to say.  It's possible I'm still missing something, but I still see an issue relating to the EET timezone described in my first reply to you above.

Break up a bar into equal intervals. Trigger event at start of new interval.
Break up a bar into equal intervals. Trigger event at start of new interval.
  • 2022.03.01
  • www.mql5.com
Hello all. Any help appreciated... I have a multi-symbol, chart independent EA. It has many inputs. There's two relevant to this question...
 
Detnator #:

Hi Fernando.  Thanks.  This seems promising, though there might be a piece I'm missing.

CurrentTime(), numerically, returns number of seconds since 1/1/1970 0:00:00 but is not timezone specific, right?  

Consider this: 

I'm in USA Central time zone (GMT -6) and at this moment my output from that is: 

Two things to note: 

The main problem here, I think, is that none of these are EET, which is what the bars seem to be based on, so there's no (easy) reliable way to get the current time in the same timezone as the bars time, meaning that there are at least some situations where I just can't line it up...?

CurrentTime() returns time as per the Trade Server timezone. However, it only updates when a new tick arrives. So if no tick arrives, time gets "stuck".  So as an alternative TimeTradeServer() is syncronised with CurrentTime() but the seconds keep on ticking even when no tick data comes in.

If the bars are based on EET, then that is trade server time CurrentTime() / TimeTradeServer() .

 
Detnator #: The main problem here, I think, is that none of these are EET

TimeCurrent,     2022.03.02 00:08:12, 1646179692
TimeTradeServer, 2022.03.02 00:08:12, 1646179692
TimeLocal,       2022.03.01 16:08:12, 1646150892
TimeGMT,         2022.03.01 22:08:12, 1646172492

The above times for the server are EET = GMT+2. It is correct!

EDIT: Daylight savings are still not in effect until end of March when it becomes EEST = GMT+3.

 
Fernando Carreiro #:

The above times for the server are EET = GMT+2. It is correct!

EDIT: Daylight savings are still not in effect until end of March when it becomes EEST = GMT+3.

Indeed.  It seems you're right. I was just looking into this again... Not quite sure what went wrong in my head (I think).

I could have sworn when I was doing this last night I was getting different times for TradeServer/Current vs iTime(...).  At this point, it's very possible I'm remembering this wrong. So now, I just tried running the following: 

void OnStart() {
    Print("TimeGMT,         ", TimeGMT(), ", ", (int)(TimeGMT()));
    Print("TimeLocal,       ", TimeLocal(), ", ", (int)(TimeLocal()));
    Print("TimeCurrent,     ", TimeCurrent(), ", ", (int)(TimeCurrent()));
    Print("TimeTradeServer, ", TimeTradeServer(), ", ", (int)(TimeTradeServer()));
    Print("iTime M1,        ", iTime(_Symbol, PERIOD_M1, 0), ", ", (int)(iTime(_Symbol, PERIOD_M1, 0)));
    Print("iTime H1,        ", iTime(_Symbol, PERIOD_H1, 0), ", ", (int)(iTime(_Symbol, PERIOD_H1, 0)));
    Print("iTime H4,        ", iTime(_Symbol, PERIOD_H4, 0), ", ", (int)(iTime(_Symbol, PERIOD_H4, 0)));
    Print("iTime D1,        ", iTime(_Symbol, PERIOD_D1, 0), ", ", (int)(iTime(_Symbol, PERIOD_D1, 0)));
    Print("iTime W1,        ", iTime(_Symbol, PERIOD_W1, 0), ", ", (int)(iTime(_Symbol, PERIOD_W1, 0)));
}

The result: 

TimeGMT,         2022.03.01 23:12:29, 1646176349
TimeLocal,       2022.03.01 17:12:29, 1646154749
TimeCurrent,     2022.03.02 01:12:27, 1646183547
TimeTradeServer, 2022.03.02 01:12:29, 1646183549
iTime M1,        2022.03.02 01:12:00, 1646183520
iTime H1,        2022.03.02 01:00:00, 1646182800
iTime H4,        2022.03.02 00:00:00, 1646179200
iTime D1,        2022.03.02 00:00:00, 1646179200
iTime W1,        2022.02.27 00:00:00, 1645920000

Notably, the fourth and fifth lines do indeed show the same minute, meaning iTime and TimeTradeServer, at least here, are in EET time zone.

Also notably, the last two lines show the start of the day and the start of the week as 00:00:00 time, which is correct for EET, of course.

So ok, remaining questions then:

Based on what you said, I presume this is because my broker's server happens to be in EET time zone...?  What will I get if my broker's server is in a different time zone?

Or to put it another way: Does iTime() return EET results here because iTime() always return EET results regardless of the server?  Or does iTime() return EET results here because it returns the bar times in the broker's server and my broker's server happens to be in EET?  If my broker's server is in NY, USA or London, England or Sydney, Australia, iTime() will return results based on those time zones?

Yes, that's about five different ways to ask more or less the same question. 😉. Just being thorough. I'm pretty sure the answer is "yes, iTime() returns broker's server time zone" based on what you said, but just want to double check (if you (or anyone) knows for sure).


PS. Thanks for all your replies.  I appreciate you working through this with me.  Very helpful!
 
Detnator #: Based on what you said, I presume this is because my broker's server happens to be in EET time zone...?  What will I get if my broker's server is in a different time zone?

Or to put it another way: Does iTime() return EET results here because iTime() always return EET results regardless of the server?  Or does iTime() return EET results here because it returns the bar times in the broker's server and my broker's server happens to be in EET?  If my broker's server is in NY, USA or London, England or Sydney, Australia, iTime() will return results based on those time zones?

Yes, that's about five different ways to ask more or less the same question. 😉. Just being thorough. I'm pretty sure the answer is "yes, iTime() returns broker's server time zone" based on what you said, but just want to double check (if you (or anyone) knows for sure).

PS. Thanks for all your replies.  I appreciate you working through this with me.  Very helpful!

Stop thinking in terms of EET. You keep ignoring what I have said and what the documentation states, it's "Broker's Server Time", irrespective of what that is, be it given by iTime, CurrentTime, TimeTradeServer, time[], tick time, or what ever function or data, returns the datetime of the server or the bar data or the tick data.

It also does not matter where the Broker is located. It is their choice of what timezone to use for their servers.

Reason: