Алгоритмы, методы решений, сравнение их производительности - страница 22

 

Обновил до 2269. Результаты профилировщика большого (не синтетического) советника.


Tester



Virtual


Наверное, профилировщик делает неверные замеры. Иначе получается, что пятерочный OrderSend в среднем забирает 912 мс.

 

Любые нормализованые одним алгоритмом (например, через NormalizeDouble) даблы можно сравнивать между собой напрямую.


Данное очевидное обстоятельство позволяет во многих случаях избежать дорогостоящих конструкций сравнения вещественных чисел. Что в некоторых задачах может существенно поднять производительность.

Наверное, одна из самых показательных из таких задач - Тестер. Разберем на примере.


Стоит BuyLimit. Тестер обязан на каждом тике сравнивать BuyLimit с ценой Ask. Штатный Тестер сейчас делает это так

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


Т.е. любой торговый уровень (отложенный ордер или SL/TP) порождает вызов одной Нормализации.


Но можно всегда обойтись очень эффективной конструкцией сравнения, если цены предварительно (до начала бэктеста) были нормализованы.

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


Попробуем сравнить. Запустил этого робота в Тестере через 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;
  }
}


Сравнение цен через нормализацию.

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


Без нормализации.

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


Видно, что выигрышь более 20%, если не делать нормализацию при сравнении цен.


Как следствие, если штатный Тестер перевести на нормализованные цены и отказаться от внутренней нормализации при сравнении цен, то можно достичь серьезного повышения производительности.

 
После прямого присвоения без мат. операций тоже
 
TheXpert:
После прямого присвоения без мат. операций тоже

Присвовение, конечно, копирует байтовое представление числа без изменений.

 

Может, провести тест длительностью больше одной секунды для наглядности?

Тут в одном варианте разброс в 3 раза: shortest pass 0:00:00.604, longest pass 0:00:01.743. что сравниваем?

 
Andrey Khatimlianskii:

Может, провести тест длительностью больше одной секунды для наглядности?

Тут в одном варианте разброс в 3 раза: shortest pass 0:00:00.604, longest pass 0:00:01.743. что сравниваем?

Сравниваем shortest, конечно. Привык на фильтрованных тиках гонять. Подготовлю нефильтрованные попозже.

 
fxsaber:

Сравниваем shortest, конечно.

Почему??? Оптимизация же не из одного прохода состоит. Какая разница, что один проскочил так быстро, если среднее не сильно отличается.


fxsaber:

Привык на фильтрованных тиках гонять. Подготовлю нефильтрованные попозже.

Можно просто более длинный интервал. Чтобы хотя бы секунд 30 тест шел.

 
Andrey Khatimlianskii:

Почему??? Оптимизация же не из одного прохода состоит. Какая разница, что один проскочил так быстро, если среднее не сильно отличается.

Этот параметр оптимизируется

input int inFakeRange = 0;

А он не влияет на логику. Поэтому и shortest.

 
fxsaber:

Этот параметр оптимизируется

А он не влияет на логику. Поэтому и shortest.

При чем здесь логика советника? Замеряем же скорость тестера.

 
Andrey Khatimlianskii:

При чем здесь логика советника? Замеряем же скорость тестера.

Так один Агент работает, последовательно считает одно и то же. Если убрать всякие случайности, то чистая производительность близка именно к shortest.