Download MetaTrader 5
To add comments, please log in or register
They are making profit already using Freelance service. You can join them!
Peter Maxwell
75
Peter Maxwell 2011.09.06 07:42 

At the moment, I'm preparing an EA for the Championship and although time is now very tight, it looks hopeful that I may at least have an entry this year.  The problem I am currently having is optimisation.

I am a competent in other languages (C/C++/PHP/etc) and as such have a good understanding of how to optimise code.  Despite my best efforts and two days of work, I cannot get the prototype incarnation of my EA to run in an acceptable time during backtest.  This concerns me as the code is not complex at all and there is still a lot additional code to be added, not to mention having the same code run on another five currency pairs, which will inevitably extend the execution time by at least 500%.

At the moment, I have already implemented a handler to only execute the main body of code if the price has moved more than a certain number of points or exceeded a time limit.  I've also ensured the critical path is as short as possible and there are conditional checks to see whether the code can return before hitting the more resource intensive sections.  I've used the OnTick() handler, as that is the only way I can see of checking for rapid price movements.

Something which I suspect is slowing things down is the high number of transactions made (in the prototype roughly 3000 over a three month period).  Would that cause a backtest to run slow?

The MetaTrader terminal is being run in a Virtualbox installation of WinXP (so it will run slower than expected), I am wondering whether that explains the poor performance.


If anybody has some non-trivial suggestions of how to improve execution speed, it would be useful.


Also, if somebody in MetaQuotes could confirm the following it may help:

i. does a "Sleep()" call affect backtest execution speed?

ii. what sort of penalty is there in a function call as compared to inlining code (and does the compiler automatically inline short functions)?

iii. is there a rough guideline of hardware that the EAs get tested on (CPU, number of cores), or am I better uploading a prototype just now to see how long it runs?

iv. in multiple use scenarios, what sort of time penalty is there in calling a SymbolInfo() or PositionGetDouble() type call as opposed to calling it once and storing the result in a local scope variable?

v. what is generally faster for conditionals, an "if" statement or the ternary operator?

vi. with executing trade operations, I have a small "Sleep()" to avoid the code returning too quickly and then a potential re-invocation soon after, hence performing actions on inconsistent Deal data - is it wiser to return immediately and try to code more defensively elsewhere?


Thanks

Documentation on MQL5: Standard Constants, Enumerations and Structures / Trade Constants / Order Properties
  • www.mql5.com
Standard Constants, Enumerations and Structures / Trade Constants / Order Properties - Documentation on MQL5
Peter Maxwell
75
Peter Maxwell 2011.09.06 07:53  


It seems using OnTimer() with say, 120secs, is *significantly* faster (as expected), although the results are slightly different.





balazs321
168
balazs321 2011.09.06 13:08  

One very trivial thing I realized is that it is better to declare the variables as global ones. In the documentation there is an example code:

void OnTick()
  {
   MqlTick last_tick;
//---
   if(SymbolInfoTick(Symbol(),last_tick))
     {
      Print(last_tick.time,": Bid = ",last_tick.bid,
            " Ask = ",last_tick.ask,"  Volume = ",last_tick.volume);
     }
   else Print("SymbolInfoTick() failed, error = ",GetLastError());
//---
  }
 

 But you just do not have to redeclare the variable "last_tick" everytime a new tick arrives, so it is better to place it outside OnTick():

MqlTick last_tick;

void OnTick()
  {
//---
   if(SymbolInfoTick(Symbol(),last_tick))
     {
      Print(last_tick.time,": Bid = ",last_tick.bid,
            " Ask = ",last_tick.ask,"  Volume = ",last_tick.volume);
     }
   else Print("SymbolInfoTick() failed, error = ",GetLastError());
//---
  }
 

Same result but faster. And so you do not have to pass the current bid and ask to functions, because they can get them from last_tick. 

You can do that with all of your variables.

 

Please write if whether that helped or not, because I have other suggestions as well.

Peter Maxwell
75
Peter Maxwell 2011.09.08 04:41  
balazs321:

One very trivial thing I realized is that it is better to declare the variables as global ones. In the documentation there is an example code:

 But you just do not have to redeclare the variable "last_tick" everytime a new tick arrives, so it is better to place it outside OnTick():

Same result but faster. And so you do not have to pass the current bid and ask to functions, because they can get them from last_tick. 

You can do that with all of your variables.

 

Please write if whether that helped or not, because I have other suggestions as well.


Thanks balazs321, but there's far too much to have all variables in global scope (all the persistent objects are already global).  What can be global, I've already got there and have cached what I can as member variables for each class.

It's a fair bit better now that I'm using the OnTimer() but I'm slightly concerned it will miss fast - and usually important - price movements.  I may try rewritting the bit of code I used to check for price movements later on, see if I can't get it working faster. 

There's still efficiency issues though, which I suspect can be solved... just now sure how yet.  I'll get the rest of the functionality coded first then come back to this I suppose.



/
To add comments, please log in or register