function sleep alternative

 

Hello MQL4 community,

I've encountered an issue while running an EA including the function Sleep() in the strategy tester. Apparently the tester won't run the EA properly with the inclusion of function Sleep() embedded in the code.

Have any coders present discovered an alternative method from function Sleep() to code an EA to "wait" a certain amount of time while the EA is being run in the tester?


Thank you

 
WhooDoo22:

Hello MQL4 community,

I've encountered an issue while running an EA including the function Sleep() in the strategy tester. Apparently the tester won't run the EA properly with the inclusion of function Sleep() embedded in the code.

Have any coders present discovered an alternative method from function Sleep() to code an EA to "wait" a certain amount of time while the EA is being run in the tester?

There is no logical reason for sleep() to work in the Strategy Tester . . .  what are you trying to do ?  if you are trying to time an event then use time and don't just try to pause for the required time,  that isn't what sleep() is for.
 

Simon,

A reason I chose to use the function 'Sleep()' was because Seconds() returns values from last known server time (retrieving data from last known server time causes seconds to skip and/or pause). I wish for reliability, not generality.

What say you to this?


Thank you

 
WhooDoo22:

Simon,

A reason why I chose to use the function 'Sleep()' was because Seconds() returns values from last known server time (retrieving data from last known server time causes seconds to skip and/or pause). 

What is your evidence for this ?  you can only "see" time for times that have ticks,  if there are no ticks for 30 seconds then you will see a skip of 30 seconds . . . there is nothing you can do about this,  it's how it is. Times for ticks in the Strategy Tester should be reasonable uniform as the ticks are not real but synthesised. 
 

Simon,

So you write, a reason I may be calling these "skips" &/or "pauses" in seconds is because no ticks are created between [seconds x] and [seconds y]. In layman's terms, a tick is created, now 'seconds x' is saved. No tick is created for three seconds then a tick is created. Now 'seconds y' is saved. ('seconds y' = (seconds x +three seconds)) as ('seconds x' = (seconds y-three seconds)).

What say you to this?


I'll be considering my options for the time being.

Many thanks for your responses.

 
  1. Until you return from start. No ticks are EVER created in the tester. Save the TimeCurrent() in a static/common(global) variable. Next tick int deltaSec = TimeCurrent() - previous.
  2. https://www.mql5.com/en/forum/127483 reported that DayOfWeek() always returns 5 in tester (definitely not the same in indicators, as is Ask and Bid) . I never use ANY of the Seconds(), DayOfWeek() etc. because you do not want the current server time, you want the time of the tick of the tester. now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) ..
 
WhooDoo22:

Simon,

So you write, a reason I may be calling these "skips" &/or "pauses" in seconds is because no ticks are created between [seconds x] and [seconds y]. In layman's terms, a tick is created, now 'seconds x' is saved. No tick is created for three seconds then a tick is created. Now 'seconds y' is saved. ('seconds y' = (seconds x +three seconds)) as ('seconds x' = (seconds y-three seconds)).

What say you to this?

Yep,  there could easily be 3 seconds between ticks,  just like in the real world,  take a look at any currency pair at Midnight GMT,  you will see plenty of large multi second times between ticks . . .  you can even get no ticks for over a minute and missing M1 bars . . .  it's not a rare thing.
 

William,

Many thanks for your response.

1. Until you return from start. No ticks are EVER created in the tester. Save the TimeCurrent() in a static/common(global) variable. Next tick int deltaSec = TimeCurrent() - previous.

I don't understand what you mean by, "Until you return from start". Could you please expound?


"No ticks are EVER created in the tester"

Don't you mean, no real ticks are EVER created in the tester. Wouldn't you agree artificial ticks are created in the tester?


"Save the TimeCurrent() in a static/common(global) variable. Next tick int deltaSec = TimeCurrent() - previous."

Save TimeCurrent() to a variable. When the next tick arrives, int deltaSec =TimeCurrent() - previous.

Wouldn't the "previous" variable be the variable TimeCurrent() is saved to...

deltaSec = TimeCurrent() - (TimeCurrent() saved to a variable previously)

please clarify William.


https://www.mql5.com/en/forum/127483 reported that DayOfWeek() always returns 5 in tester. I never use ANY of the Seconds(), DayOfWeek() etc. because you do now want the current server time, you want the time of the tick of the tester. now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) ..


"you want the time of the tick of the tester."

Yes, I BELIEVE this is EXACTLY what I want when testing an EA in the strategy tester due to Simon's post describing the reasoning behind why seconds appear to skip and/or pause.


now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) ..

In other words...

sec = TimeSeconds(TimeCurrent());  and DOW = TimeDayOfWeek(TimeCurrent());

What say you to this?


Thank you
 
WhooDoo22:

now = TimeCurrent(), sec = TimeSeconds(now); int DOW=TimeDayOfWeek(now) ..

In other words...

sec = TimeSeconds(TimeCurrent());  and DOW = TimeDayOfWeek(TimeCurrent());

Take a look at what TimeSeconds() gives you,  then think about what TimeCurrent() gives you . . .  which one do you need and why ?
 
WhooDoo22:

I don't understand what you mean by, "Until you return from start". Could you please expound?"

No ticks are EVER created in the tester" Don't you mean, no real ticks are EVER created in the tester. Wouldn't you agree artificial ticks are created in the tester?

  1. int start(){
       // do something
       return; // Return from start.
    }
    int start(){
       // do something
       // Fall off the end is a Return from start.
    }

  2. No ticks of any kind are created until you return and it creates the next one and calls your start(). If you compute for 5 minutes and return the volume (tick count) on the next call will be +1. In a live chart, if you compute for 5 minutes, then you will miss 5 minutes of ticks and on the M1 several new bars will have formed.
 
RaptorUK:
There is no logical reason for sleep() to work in the Strategy Tester ...

be careful with such a statement. there's always a logical reason to run sleep(). in Tester and even in indicators. right, for the OP's use case you should not play with sleep but you cannot generalize that for all MQL.

when do we need to sleep in Tester? if, for example, i test a script that interacts with an EA under test i might have the need to synchronize state. i'm talking about mutexes. to aquire a mutex in a clean way both parts need the ability to wait, ie. to use sleep.

same is true for indicators. it doesn't matter that the indicator runs in the UI thread. if two threads need to synchronize both need the ability to "sleep". and sleep() is the only clean solution if you have to wait for a given amount of CPU cycles, "for" constructs just demonstrate a lack of knowledge.

ok, let's give a practical example: my EA's can display order state (self drawn arrows etc). they do it by responding to external commands "sent" through text descriptions of chart objects (1-pending orders, 2-open positions, 3-closed trades, 4-all together), that's why i call it chart commands. or they can start/stop/resume sequences of trades by responding to other commands ("start", "stop", "resume"). in order to read the commands they need to synchronize access to those chart objects (create chart object + set text property is not one atomic operation). and of course i'd like to test this behaviour in Tester, so i need sleep() for waiting.

same for indicators running in Tester or online. if they do something similar i "have to" stop the UI thread to get a clean state, 10 miiliseconds don't matter. btw: a clean mutex implementation checks the time it's already waiting, breaks out of the loop and signals an error if it can't get a synchronization lock after let's say a few seconds.

int seconds;

// run until the lock is aquired
while (true) {
   ...
   // warn every second and cancel after 10 seconds
   duration = GetTickCount() - startTime;
   if (duration >= seconds*1000) {
      if (seconds >= 10)
         return(_false(catch("AquireLock(5)   failed to get lock for mutex \""+ mutexName +"\" after "+ DoubleToStr(duration/1000.0, 3) +" sec., giving up", ERR_RUNTIME_ERROR)));
      warn(StringConcatenate("AquireLock(6)   couldn't get lock for mutex \"", mutexName, "\" after ", DoubleToStr(duration/1000.0, 3), " sec., retrying..."));
      seconds++;
   }
   //debug("AquireLock()   couldn't get lock for mutex \""+ mutexName +"\", retrying...");

   if (IsTesting() || IsIndicator()) SleepEx(100, true);          // expert or indicator under test
   else                              Sleep(100);
}

i use those commands by writing a script and assigning a hot key to it. then, if i want to control an expert/indicator i just need to hit a key, for ex. ALT-O for toggling order display mode between all possible values. or i have a "start" and a "stop" script in the favourites and start/stop/resume an ea by a mouse click.

in tester for ex. an ea with VisualMode=On in full speed will almost immediately crash if not properly synchronized.