Here is a solution to the falsly behaving MQL5 function:
//+------------------------------------------------------------------+ //| Playground.mq5 | //| Copyright 2020, Freie Netze UG (haftunbgsbeschränkt) | //| https://www.freie-netze.de/ | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ ulong _GetTickCount64() { // Static init static ulong offset_ms = NULL; if(offset_ms != NULL) { return((GetMicrosecondCount() / 1000) + offset_ms); } // Local init ulong start_ms = NULL; ulong start_mc = NULL; ulong stop_ms = 1; ulong stop_mc = 1; while( (((stop_mc - start_mc) / 1000) != (stop_ms - start_ms)) && (!_StopFlag) ) { start_ms = GetTickCount64(); start_mc = GetMicrosecondCount(); while((start_mc + 250000) > GetMicrosecondCount()); stop_mc = GetMicrosecondCount(); stop_ms = GetTickCount64(); } offset_ms = stop_ms - (stop_mc / 1000); // Return return((GetMicrosecondCount() / 1000) + offset_ms); } #define GetTickCount64 _GetTickCount64 //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { EventSetMillisecondTimer(1000); GetTickCount64(); // Return return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { printf("%s", "OnInit()"); // Return return; } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Return return; } //+------------------------------------------------------------------+ //| Expert timer function | //+------------------------------------------------------------------+ void OnTimer() { printf("OnTimer()"); ulong enter = GetTickCount64(); ulong enter_mc = GetMicrosecondCount(); ulong mics = GetMicrosecondCount(); while(mics + 500000 > GetMicrosecondCount()); //Sleep(500); mics = GetMicrosecondCount() - mics; ulong exit_mc = GetMicrosecondCount(); ulong exit = GetTickCount64(); printf("Exec time: %llu; %llu", exit - enter, exit_mc - enter_mc); #undef GetTickCount64 printf("Sys: %llu; Own: %llu", GetTickCount64(), _GetTickCount64()); // Return return; }
Proof:
It's in the documentation. The resolution or accuracy is only 10-16 millisecond.
The counter is limited to the accuracy of the system timer, which usually returns a result with the 10-16 millisecond precision. Unlike GetTickCount, which is of uint type and the contents of which overflow every 49.7 days in the case of continued computer operation, GetTickCount64() can be used for the unlimited computer operation time and is not subject to overflow.
Now that you have posted, I remember reading that. - Still, as you can see, its not very hard to create a reliable function with consistent output.
I dont understand why this needs to be done by the user. - Well, its documented, therefore it seems not to be a bug, but a feature.
Anyways, thank you for clarification.And while we are at it, Sleep is as unreliable as GetTickCount64()...
Here would be a fix for that as well:
void _Sleep(const int milliseconds) { // Local init const ulong stop = GetMicrosecondCount() + (milliseconds * 1000); // Sleep while( (stop > GetMicrosecondCount()) && (!_StopFlag) ); // Return return; } #define Sleep _Sleep
Giving this as result:
Although this function also works in indicators and a check for that would need insertion:
void _Sleep(const int milliseconds) { // Environment check const static bool is_indicator = ((ENUM_PROGRAM_TYPE)MQLInfoInteger(MQL_PROGRAM_TYPE) == PROGRAM_INDICATOR); if(is_indicator) { return; } // Local init const ulong stop = GetMicrosecondCount() + (milliseconds * 1000); // Sleep while( (stop > GetMicrosecondCount()) && (!_StopFlag) ); // Return return; } #define Sleep _Sleep
Above code gives a fully valid drop-in replacement to the original function, although, I could imagine, there wont be a "nop" to the CPU and therefore the OS will not put the executing thread to sleep, but thats just a side-effect, as far as I am concerned.
And while we are at it, Sleep is as unreliable as GetTickCount64()...
Here would be a fix for that as well:
Giving this as result:
Although this function also works in indicators and a check for that would need insertion:
Above code gives a fully valid drop-in replacement to the original function, although, I could imagine, there wont be a "nop" to the CPU and therefore the OS will not put the executing thread to sleep, but thats just a side-effect, as far as I am concerned.
In case it is relevant, there is a standard sleep function - I made the mistake of writing my own only to discover this later :)
- www.mql5.com
In case it is relevant, there is a standard sleep function - I made the mistake of writing my own only to discover this later :)
Thank you, but the issue is not the "standard" availability, but its flawed behaviour, especially if you try to synchornize your execution thread to RTC. It just doesnt do the job as shown in my previous post. - It hovers around with a blurr of over 50 milliseconds.
Thank you, but the issue is not the "standard" availability, but its flawed behaviour, especially if you try to synchornize your execution thread to RTC. It just doesnt do the job as shown in my previous post. - It hovers around with a blurr of over 50 milliseconds.
Noted, thanks
Thank you, but the issue is not the "standard" availability, but its flawed behaviour, especially if you try to synchornize your execution thread to RTC. It just doesnt do the job as shown in my previous post. - It hovers around with a blurr of over 50 milliseconds.
Hello there ,
Sorry for being late at that, but here we go: The "problem" we are seeing on your post, i.e. sometimes you get 485ms sometimes 500, is not a flaw but rather a feature :) Joke aside , it's all due to the OS system clock, which in the case of Windows is usually 1/64sec - or 15.625ms, hence the difference we are seeing.. You can find some topics of the web of course, but here are a couple of quick links related to the subject :
https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep 
https://vvvv.org/contribution/windows-system-timer-tool
greets
- 2021.10.13
- karl-bridge-microsoft
- docs.microsoft.com
The real question is why do you care? Why do you need a timer?
How To Ask Questions The Smart Way. (2004)
The XY Problem
Nothing has changed. Return from OnTick/OnCalculate and wait for a change.
The real question is why do you care? Why do you need a timer?
How To Ask Questions The Smart Way. (2004)
The XY Problem
Nothing has changed. Return from OnTick/OnCalculate and wait for a change.
Yes, I was wondering about the relevance of this too...
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
A simple attempt to synchronize the OnTimer() call to TimeLocal to be called at around the next second has revealed a question, I cannot wrap my head around.
So I tried to analyze the behaviour and found that GetTickCount64() and GetMicrosecondCount() give confusing results, as can be seen in the screenshot.
Here is the code to reproduce the output:
Can anyone explain why there are such differences? I would expect some drift, maybe even up to a millisecond, but over 10 milliseconds? how is that possible?
I consider this to be a bug.