Algorithms, solution methods, comparison of their performance - page 22

 

Updated to 2269. Profiler results of a large (non-synthetic) EA.


Tester



Virtual


Probably, profiler makes wrong measurements. Otherwise it turns out that OrderSend five takes 912 ms on average.

 

Any dubbles normalised by the same algorithm (e.g. via NormalizeDouble) can be compared with each other directly.


This obvious fact allows to avoid in many cases costly constructs of comparing real numbers. Which in some tasks may significantly increase performance.

Perhaps one of the most exemplary of these tasks is Tester. Let's analyze it by example.


There is BuyLimit. At each tick, the tester must compare BuyLimit with the Ask price. The standard tester does it this way at present

if (NormalizeDouble(BuyLimit_Price - Ask , Symbol_Digits) >= 0)
  BuyLimit -> Buy;


I.e. any trade level(pending order or SL/TP) triggers one Normalization.


But we can always get by with a very effective comparison construct if prices have been normalized beforehand (before the backtest).

if (BuyLimit_Price >= Ask)
  BuyLimit -> Buy;


Let's try a comparison. I have run this robot in the tester through Virtual.

#include <MT4Orders.mqh>

#define  VIRTUAL_TESTER // Запуск в виртуальном торговом окружении
#include <fxsaber\Virtual\Virtual.mqh>

#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

input int inAmountOrders = 10;
input int inFakeRange = 0;

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun)
  {
    for (int i = 0; i < inAmountOrders; i++)    
      OrderSend(_Symbol, OP_BUYLIMIT, 0.1, Ask - 10000 * _Point, 0, 0, 0);
      
    FirstRun = false;
  }
}


Comparison of prices through normalization.

pass 0 returned result 100000.000000 in 0:00:01.578
pass 1 returned result 100000.000000 in 0:00:00.759
pass 2 returned result 100000.000000 in 0:00:00.894
pass 3 returned result 100000.000000 in 0:00:00.769
pass 4 returned result 100000.000000 in 0:00:00.806
pass 5 returned result 100000.000000 in 0:00:00.772
pass 6 returned result 100000.000000 in 0:00:01.253
pass 7 returned result 100000.000000 in 0:00:01.200
pass 8 returned result 100000.000000 in 0:00:01.089
pass 9 returned result 100000.000000 in 0:00:00.780
pass 10 returned result 100000.000000 in 0:00:01.258
optimization finished, total passes 11
optimization done in 0 minutes 11 seconds
shortest pass 0:00:00.759, longest pass 0:00:01.578, average pass 0:00:01.014


Without normalization.

pass 0 returned result 100000.000000 in 0:00:01.743
pass 1 returned result 100000.000000 in 0:00:00.844
pass 2 returned result 100000.000000 in 0:00:00.672
pass 3 returned result 100000.000000 in 0:00:00.817
pass 4 returned result 100000.000000 in 0:00:00.635
pass 5 returned result 100000.000000 in 0:00:00.604
pass 6 returned result 100000.000000 in 0:00:00.867
pass 7 returned result 100000.000000 in 0:00:00.611
pass 8 returned result 100000.000000 in 0:00:00.899
pass 9 returned result 100000.000000 in 0:00:00.649
pass 10 returned result 100000.000000 in 0:00:00.742
optimization finished, total passes 11
optimization done in 0 minutes 09 seconds
shortest pass 0:00:00.604, longest pass 0:00:01.743, average pass 0:00:00.825


We can see that the gain is more than 20% if we don't do normalization when comparing prices.


As a consequence, if the in-house Tester is switched to normalised prices and does not do internal normalisation when comparing prices, a serious performance improvement can be achieved.

 
After direct assignment without matrix operations, too
 
TheXpert:
After direct assignment without mat. operations also

Prefixing, of course, copies the byte representation of the number unchanged.

 

Should we run a test longer than one second for clarity?

There is a spread of 3 times in one version: shortest pass 0:00:00.604, longest pass 0:00:01.743. what do we compare?

 
Andrey Khatimlianskii:

Should we do a test longer than one second for clarity?

There is a spread of 3 times in one version: shortest pass 0:00:00.604, longest pass 0:00:01.743. what do we compare?

Comparing the shortest, of course. I'm used to racing on filtered ticks. Will prepare unfiltered ones later.

 
fxsaber:

Comparing the shortest, of course.

Why? Optimisation does not consist of a single pass. What difference does it make that one pass is so fast, if the average is not much different.


fxsaber:

I'm used to racing on filtered ticks. I will prepare unfiltered ones later.

I can just do a longer interval. At least 30 seconds for the test.

 
Andrey Khatimlianskii:

Why? It's not like optimisation consists of one pass. What difference does it make that one pass is so fast, if the average is not much different.

This parameter is optimized.

input int inFakeRange = 0;

And it does not affect the logic. That's why it is shortest.

 
fxsaber:

This parameter is optimised

And it does not affect the logic. That's why it's shortest.

What does EA logic have to do with it? We are measuring the speed of the tester.

 
Andrey Khatimlianskii:

What's the EA's logic got to do with it? We are measuring the speed of the tester.

This is how one agent works, it consecutively counts the same thing. If you take away all the randomness, the net performance is close to the shortest.

Reason: