OnTimer() has a very large delay. How to solve it? - page 3

 
Longsen Chen #:

Thanks again for your outline.

I am using different symbols in two charts.

I understand your idea and method. My real work within OnTimer() includes open trades and close trades. It may take no time in case of no trade or long time to make several orders. It's difficult to manage the execution time for such tasks inside OnTimer();

Anyway, your work is valuable.

You could use OrderSendAsync to cut down the execution time of your OnTimer() function. Stil lyou would need to deal with varying execution times. - Why would you have code for placing orders in OnTimer? This seems out of concept.

Whats the reasinging behind such an approach?

 
Dominik Christian Egert #:
OrderSendAsync

OrderSendAsync is a function in MT5. My EA has two versions for MT4 and MT5. I keep the same code as possible.

Actually the main trading work was done not in the timer thread but in the ChartEvent().

Timer thread in the receiving side checkes the connection with the sender periodically. If there is no keep-alive message between two sides, the sender will time-out the receiver and send no message to the receiver, which causes a big problem.

 
Longsen Chen #:

OrderSendAsync is a function in MT5. My EA has two versions for MT4 and MT5. I keep the same code as possible.

Actually the main trading work was done not in the timer thread but in the ChartEvent().

Timer thread in the receiving side checkes the connection with the sender periodically. If there is no keep-alive message between two sides, the sender will time-out the receiver and send no message to the receiver, which causes a big problem.

How about a receiver-relogin function?

Make the receiver be able to register with the sender.

I suspect, you are using multiple EAs, right?

For MT5 you could use a service, which you could easily copy to an EA. Although you would need some "trick" on making it continuously run, for MT4 compatibility.

Anyways, I think there is an underlying design issue, that leads you into this issue in the first place.

 
Longsen Chen #:

I need to test for 24 hours. it will print 24*3600 logs. It's very hard to find out if some seconds are missed.

Not 24 hours yet but...

The issue relies on your side, either something on the computer/OS, on the platform (MT4 is obsolete), on the workload or possibly in your code. You need to investigate if you want a solution, complaining is useless.

 
Dominik Christian Egert #:
How about a receiver-relogin function?

Make the receiver be able to register with the sender.

I suspect, you are using multiple EAs, right?

For MT5 you could use a service, which you could easily copy to an EA. Although you would need some "trick" on making it continuously run, for MT4 compatibility.

Anyways, I think there is an underlying design issue, that leads you into this issue in the first place.

The sender is to notify the receiver to open a trade. At the moment the receiver is timed out. Several minutes passed, the receiver is re-connected but the order is missed. That's the consequence.

My underlying design is made with the assumption that timer is reliable.

 
Alain Verleyen #:

Not 24 hours yet but...

The issue relies on your side, either something on the computer/OS, on the platform (MT4 is obsolete), on the workload or possibly in your code. You need to investigate if you want a solution, complaining is useless.

Thank you for your advice. MT4 is obsolete, but some brokers only support MT4, or charge less commision for MT4 account than MT5 account. I don't know why.

 
Longsen Chen #:

The sender is to notify the receiver to open a trade. At the moment the receiver is timed out. Several minutes passed, the receiver is re-connected but the order is missed. That's the consequence.

My underlying design is made with the assumption that timer is reliable.

I don't fully agree on this, honestly.

If you want to solve it in such way that it is reliable, then you must adapt your structure.

Find the right execution environments for the tasks you are doing. Usually, if I understand this correctly, you need to build your hookup process according to the needs, not what is comfy for you.

In a client server concept, the client is the "master" or initiator of the connection, the server needs to listen to the client.

In your process, if I understand this correctly, you need to turn the responsibilities around. Your receiver is the crucial part here, make it be as aggressive as you when google isn't loading... Hope you get what I mean.
 

I'm going to measure the execution time of each event handler to find out which part using CPU time.

Each MT4 starts two charts with two EAs. I guess MT4 gives the timer event to two EAs at the same time. One EA takes long execution time in some event handler may delay timer event. They are not fully independent.

 

I made a clean environment. I started only one EA(Timer.EX4) in MT4, which is compiled from the codes as attached.

But I had a log shows 6 seconds delay. This really puzzled me.


#property version   "1.0"
#property copyright "Copyright 2022, Ksana Trading Corp."
#property link      "https://www.ksanatrading.com"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   if(!EventSetTimer(1))
      return (INIT_FAILED);
   string msg;
   msg = "Monitoring timer delay...";
   Comment(msg);
   Print(msg);
//--- succeed
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer();   
}
//+------------------------------------------------------------------+

void OnTimer()
{
   static datetime last_call=0;
   static int gap_max=0;
   datetime now = TimeLocal();
   if(last_call != now)
   {
      if(last_call>0)
      {
         int gap = (int)(now-last_call);
         if(gap>gap_max)
         {
            gap_max=gap;
            string msg;
            msg = StringFormat("Max Delay=%d (s), at %s",gap_max,
               TimeToString(TimeLocal(),TIME_DATE|TIME_SECONDS));
            Comment(msg);
            Print(msg);
         }
      }
      last_call = now;
   }
}
Files:
Timer.mq4  3 kb
 
Longsen Chen #:

I had a log shows 6 seconds delay. This really puzzled me.

Try this.

#property strict

#define TOSTRING(A) #A + " = " + (string)(A) + " "

int OnInit()
{
  return(!EventSetMillisecondTimer(1000));
}

void OnTimer ()
{   
  static ulong PrevTime = GetMicrosecondCount();
  static ulong MaxInterval = 0;
  static int Amount = 0;
  
  const ulong NewTime = GetMicrosecondCount();
  Amount++;
  
  if (NewTime - PrevTime >= MaxInterval)
    Alert(TOSTRING(MaxInterval = NewTime - PrevTime) +
          TOSTRING(Amount));
  
  PrevTime = NewTime;   
}