Новая версия платформы MetaTrader 5 build 2265: Функции DirectX для 3D-визуализации в MQL5 и настройка инструментов в тестере стратегий - страница 19

 
fxsaber:

В Визуализаторе Debug-EX5 приходится долго ждать первого тика (на чарте написано  Ожидание обновления)

В логе пометил это место в три секунды. На некоторых советниках жду >10 секунд каждый раз!

При этом Release-EX5 в Визуализаторе идут без этой паузы. Дайте знать, пожалуйста, воспроизводится или нет.

Если я правильно понял, это регулярно и очень давно. попробуйте остановить отладку в функции OnInit() и пошагово перейти к первому тику. То-есть перейти из OnInit() в OnTick()

 

запустил у себя профилировщик билд 2267 Вин10-64

в блоке работы с ордерами ожидал, что подсчет ордеров и обращение к свойствам ордера (использую библиотеку MT4Orders.mqh автор @fxsaber) будет занимать больше всего времени, оказалось, что там наименьший расход процессорного времени, а вот банальная нормализация обьема ордера оказалась у меня самая дорогая, количество обращений к методу  calcNormVol  1170 раз, занимает процессорного времени (223) 63.5%


вот код

//+------------------------------------------------------------------+
double COrder::calcNormVol(const double value) const
{
   return(NormalizeDouble(fmax(fmin(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP) * round(value / SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP)),
                                    SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX)),  SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)), O_DigitsInVolumeStep));
}
//+------------------------------------------------------------------+

хотя даже расчет кол-ва знаков после запятой вынес в статик переменную, чтобы в оптимизаторе быстрее работало

static int     O_DigitsInVolumeStep;
int OnInit()
{
   O_DigitsInVolumeStep = GetDigitsInVolumeStep();
}
//____________________________________________________________________
int GetDigitsInVolumeStep()
{
   int result = 0;
   long i = 10000000, k = long(::SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP) / 0.0000001);
   while(result < 7 && k % i > 0) {
      i /= 10;
      result++;
   }
   return(result);
}
//+------------------------------------------------------------------+


метод calcNormVol использую при отправке ордера и при оценке маржинальных требований


по моему такие простые функции как fmax , fmin , round должны работать быстрее пользовательских функций, но профилировщик показывает обратное


UPD: для сравнения вот этот код:

if(!OrderSelect(o_ticket, SELECT_BY_TICKET)) return;
o_profit = OrderProfit() + OrderCommission() + OrderSwap();

выполняется каждый тик и вызывается 10 468 296 раз и выполняется быстрее в 2 раза по данным профилировщика

 
Igor Makanu:

вот код

В нем неявно создается четыре string-переменные.

 
Igor Makanu:

запустил у себя профилировщик билд 2267 Вин10-64

в блоке работы с ордерами ожидал, что подсчет ордеров и обращение к свойствам ордера (использую библиотеку MT4Orders.mqh автор @fxsaber) будет занимать больше всего времени, оказалось, что там наименьший расход процессорного времени, а вот банальная нормализация обьема ордера оказалась у меня самая дорогая, количество обращений к методу  calcNormVol  1170 раз, занимает процессорного времени (223) 63.5%


вот код

хотя даже расчет кол-ва знаков после запятой вынес в статик переменную, чтобы в оптимизаторе быстрее работало


метод calcNormVol использую при отправке ордера и при оценке маржинальных требований


по моему такие простые функции как fmax , fmin , round должны работать быстрее пользовательских функций, но профилировщик показывает обратное

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

 
fxsaber:

В нем неявно создается четыре string-переменные.

как оптимизировать код? 

про string вообще не могу понять откуда они в математических вычислениях


Artyom Trishkin:

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

при отправке ордера идет нормализация лота, обычная практика, лот ордера изменяется в зависимости от предыдущего ордера, общее количество ордеров тоже разное, у меня это десяток ордеров, каждый из которых работает по своей ТС, но обьем зависит от результата предыдущих трейдов, в общем не удобно что то менять, тогда проще для оптимизатора переписать участок кода с нормализации ордера, вообще табличные значения рассчитать и занести... но вопрос пока про  fmax , fmin , round  - не понятно почему они ресурсы требуют

 
Igor Makanu:

как оптимизировать код? 

про string вообще не могу понять откуда они в математических вычислениях


при отправке ордера идет нормализация лота, обычная практика, лот ордера изменяется в зависимости от предыдущего ордера, общее количество ордеров тоже разное, у меня это десяток ордеров, каждый из которых работает по своей ТС, но обьем зависит от результата предыдущих трейдов, в общем не удобно что то менять, тогда проще для оптимищатора перепать участок кода с нормализацие ордера, вообще табличные значения рассчитать и занести... но вопрос пока про  fmax , fmin , round  - не понятно почему они ресурсы требуют

Попробуй получение данных от сервера SymbolInfoXXX убрать из функции. Эти данные - получаемые от символа - неизменны.

 
Igor Makanu:

как оптимизировать код? 

double COrder::calcNormVol2(const double value) const
{
  // Оверхед https://www.mql5.com/ru/forum/170952/page152#comment_14131263
  static const double Res = MQLInfoInteger(MQL_TESTER) ? this.calcNormVol : 0;
  
  return(Res ? Res : this.calcNormVol);
}

про string вообще не могу понять откуда они в математических вычислениях

В функцию передается _Symbol.

 
Artyom Trishkin:

Попробуй получение данных от сервера SymbolInfoXXX убрать из функции. Эти данные - получаемые от символа - неизменны.

я замерял несколько месяцев назад скорость работы с SymbolInfoXXX() - они ничего не весят, время почти один в один как доступ к глобально описанной переменной, чуть позже проверю их еще в 2267 билде, но все равно подозрение на работу математических функций  fmax , fmin , round


fxsaber:

В функцию передается _Symbol.

я где то отстал от обсуждения, моя нормализация лота, ну это некая классика которая 10+ лет уже как по все статьям и примерам, в общем нужно поэкспериментировать

 
Igor Makanu:

я где то отстал от обсуждения, моя нормализация лота, ну это некая классика которая 10+ лет уже как по все статьям и примерам, в общем нужно поэкспериментировать

В общем, в Тестере всегда одно и то же правило: никогда не вычислять повторно одно и то же.

 
fxsaber:

В общем, в Тестере всегда одно и то же правило: никогда не вычислять повторно одно и то же.

запустил профилировщик на таком коде, вызовов/время 1170 / 456 (94.21%)

//+------------------------------------------------------------------+
double COrder::calcNormVol(const double value) const
{
   const string sym = _Symbol;
   return(
   NormalizeDouble(fmax(fmin(SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP) * round(value / SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP)),SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX)),  SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN)), O_DigitsInVolumeStep)
   );
}

потом профилировщик на таком коде, вызовов/время 1170 / 464 (89.92%)

//+------------------------------------------------------------------+
double COrder::calcNormVol(const double value) const
{
   const string sym = _Symbol;
   return(NormalizeDouble(fmax(fmin(SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP) * round(value / SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP)),
                                    SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX)),  SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN)), O_DigitsInVolumeStep));
}
//+------------------------------------------------------------------+


по моему разницы особой то и нет

вот по вызовам функций раскидал