Не могу понять, можно ли решить эту проблему со скоростью тестирования, не используя функции языка MT5. Всплыла проблема давно, но руки добрались разобраться в ней только сейчас.
Билд 3802, __MT4ORDERS__ "2022.07.20"
Условная функция, вызываемая в эксперте на каждом тике. Тест в тестере стратегий мт5.
datetime get_last_order_close_time () {
datetime last_close_time=0;
for ( int i = OrdersHistoryTotal() - 1; i >= 0; i-- ) {
if ( !OrderSelect ( i, SELECT_BY_POS, MODE_HISTORY )) {
continue;
}
last_close_time=OrderCloseTime();
return last_close_time;
}
return last_close_time;
}
Количество сделок в районе 26 тысяч. Время теста около 1 часа 10 минут.
Убираем функцию из кода, время теста стало около 17 минут.
Переписываю эту же функцию с использованием функционала МТ5:
datetime get_last_order_close_timeMT5 () {
datetime last_close_time=0;
HistorySelect(0,TimeCurrent());
for ( int i = HistoryDealsTotal() - 1; i >= 0; i-- ) {
ulong ticket=HistoryDealGetTicket(i);
if((ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket,DEAL_ENTRY)==DEAL_ENTRY_OUT)
{
last_close_time=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
return last_close_time;
}
}
return last_close_time;
}
Время теста в районе 18 минут.
Откатываю библиотеку до версии __MT4ORDERS__ "2020.01.12" и компилю эксперта в билде 2980.
Время работы эксперта с функцией get_last_order_close_time - в районе 20 минут.
fxsaber #: Во всех трех случаях конечный результат совпадает?
Да, конечно.
Это стало происходить после очередного обновления имено терминала. Вашу библиотеку я не менял, и чтобы все работало как раньше компилировал бота в старом терминале.
Это стало происходить после очередного обновления имено терминала. Вашу библиотеку я не менял, и чтобы все работало как раньше компилировал бота в старом терминале.
На каждом inMod-тике открывается и закрывается позиция. И на каждом тике вычисляется OrderCloseTime.
OnTester служит критерием проверки идентичности результатов при разных конфигурациях.
Соответствующие функции работы с историей.
datetime LastCloseTimeMQL4()
{
datetime Res = 0;
for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)
if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderType() <= OP_SELL))
{
Res = OrderCloseTime();
break;
}
return(Res);
}
datetime LastCloseTimeMQL5()
{
datetime Res = 0;
if (HistorySelect(0, INT_MAX))
for (int i = HistoryDealsTotal() - 1; i >= 0; i--)
{
constulong Ticket = HistoryDealGetTicket(i);
if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) != DEAL_ENTRY_IN)
{
Res = (datetime)HistoryDealGetInteger(Ticket, DEAL_TIME);
break;
}
}
return(Res);
}
#define MACROS(A, B) \
datetime A##_2() \
{ \
staticdatetime Res = 0; \
staticint PrevTotal = 0; \
\
constint Total = B; \
\
if (PrevTotal != Total) \
{ \
Res = A(); \
\
PrevTotal = Total; \
} \
\
return(Res); \
}
// LastCloseTimeMQL4_2
MACROS(LastCloseTimeMQL4, OrdersHistoryTotal())
// LastCloseTimeMQL5_2
MACROS(LastCloseTimeMQL5, HistorySelect(0, INT_MAX) ? HistoryDealsTotal() : 0)
Методика.
Одиночный запуск на настройках, как в исходнике (inMod = 5).
2023.07.0623:59:5928179final balance 99996992.20 pips
OnTester result 2761115
EURUSD,M1: 274413 ticks, 70443 bars generated. Environment synchronized in 0:00:00.021. Test passed in 0:00:03.712 (including ticks preprocessing 0:00:00.031).
28K сделок, почти четыре секунды. Поскольку замерять производительность нужно в режиме оптимизации, то все следующие показания производительности делались так.
shortest pass 0:00:02.875, longest pass 0:00:03.094, average pass 0:00:02.919
С обязательной перекомпиляцией перед запуском и включенным только одним Агентом для последовательного выполнения проходов.
Производительность.
Таблица производительности (время выполнения в миллисекундах) для b3815 и b2958.
Тормозит OrderSelect. Связано с тем, что при OrderSelect идет вычисление абсолютно всех данных выбранного ордера из истории (OrderPrint - бесплатный). Это большая комбинация HistoryOrderGet* и HistoryDealGet* функций, с обработкой любой сложности рыночных ситуаций и большого количества подводных камней. Посмотрите MT4ORDERS::GetHistoryPositionData(). Это единая функция для Терминала и для Тестера, но при этом для Тестера специально сделаны ускорения, т.к. многих подводных камней Терминала в Тестере нет. Примеры конфигураций: один, два, три.
Соответственно, нужно добиваться уменьшения вызовов OrderSelect для исторических ордеров. Этого можно добиться способами, что указаны в правых трех столбцах таблицы.
Самая быстрая работа (опережает чистый MQL5) - торговля в виртуальном окружении. Рекомендовал бы оптимизацию делать в виртуальном окружении, а одиночные проходы - вне его.
Производительность Тестера b2958 и b3815 почти идентична.
Не рекомендую логику ТС для Тестера завязывать на историю торговли с обращением к ней. Например, OrderCloseTime своей ТС можно знать без обращения к истории.
Возможно ли, что происходит утечка памяти или использование памяти больше, чем нужно? Может быть, в this.tickets или в this.amount (::ArrayResize) или где-то еще?
Размер массивов только увеличивается со временем. Является ли это обязательным условием? Можно ли их очистить или, возможно, не загружать все предыдущие сделки?
Возможно ли, что происходит утечка памяти или использование памяти больше, чем нужно? Может быть, в this.tickets или в this.amount (::ArrayResize) или где-то еще?
Размер массивов только увеличивается со временем. Является ли это обязательным условием? Можно ли их очистить или, возможно, не загружать все предыдущие сделки?
Библиотека не полностью кэширует исторические данные. Получить нехватку памяти можно только в теории, но не на практике.
Напишите скрипт, который просматривает всю торговую историю с помощью библиотеки, и посмотрите, сколько памяти потребляется.
Не могу понять, можно ли решить эту проблему со скоростью тестирования, не используя функции языка MT5. Всплыла проблема давно, но руки добрались разобраться в ней только сейчас.
Билд 3802, __MT4ORDERS__ "2022.07.20"
Условная функция, вызываемая в эксперте на каждом тике. Тест в тестере стратегий мт5.
Количество сделок в районе 26 тысяч. Время теста около 1 часа 10 минут.
Убираем функцию из кода, время теста стало около 17 минут.
Переписываю эту же функцию с использованием функционала МТ5:
Время теста в районе 18 минут.
Откатываю библиотеку до версии __MT4ORDERS__ "2020.01.12" и компилю эксперта в билде 2980.
Время работы эксперта с функцией get_last_order_close_time - в районе 20 минут.
Не могу понять, можно ли решить эту проблему со скоростью тестирования, не используя функции языка MT5.
Во всех трех случаях конечный результат совпадает?
Да, конечно.
Это стало происходить после очередного обновления имено терминала. Вашу библиотеку я не менял, и чтобы все работало как раньше компилировал бота в старом терминале.
Это стало происходить после очередного обновления имено терминала. Вашу библиотеку я не менял, и чтобы все работало как раньше компилировал бота в старом терминале.
Сделал исследование.
Советник.
На каждом inMod-тике открывается и закрывается позиция. И на каждом тике вычисляется OrderCloseTime.
OnTester служит критерием проверки идентичности результатов при разных конфигурациях.
Соответствующие функции работы с историей.
Методика.
Одиночный запуск на настройках, как в исходнике (inMod = 5).
28K сделок, почти четыре секунды. Поскольку замерять производительность нужно в режиме оптимизации, то все следующие показания производительности делались так.
С обязательной перекомпиляцией перед запуском и включенным только одним Агентом для последовательного выполнения проходов.
Производительность.
Таблица производительности (время выполнения в миллисекундах) для b3815 и b2958.
Везде использовалась MT4Orders от 20.07.2022.
Выводы.
Время теста около 1 часа 10 минут.
Откатываю библиотеку до версии __MT4ORDERS__ "2020.01.12" и компилю эксперта в билде 2980.
Время работы эксперта с функцией get_last_order_close_time - в районе 20 минут.
Попробуйте код выше на старой версии библиотеки (у меня ее нет).
Если будет отличие в производительности, пришлите в ЛС.
Возможно ли, что происходит утечка памяти или использование памяти больше, чем нужно? Может быть, в this.tickets или в this.amount (::ArrayResize) или где-то еще?
Размер массивов только увеличивается со временем. Является ли это обязательным условием? Можно ли их очистить или, возможно, не загружать все предыдущие сделки?
Возможно ли, что происходит утечка памяти или использование памяти больше, чем нужно? Может быть, в this.tickets или в this.amount (::ArrayResize) или где-то еще?
Размер массивов только увеличивается со временем. Является ли это обязательным условием? Можно ли их очистить или, возможно, не загружать все предыдущие сделки?
Библиотека не полностью кэширует исторические данные. Получить нехватку памяти можно только в теории, но не на практике.
Напишите скрипт, который просматривает всю торговую историю с помощью библиотеки, и посмотрите, сколько памяти потребляется.
Библиотека не полностью кэширует исторические данные. Получить нехватку памяти можно только в теории, но не на практике.
Напишите скрипт, который сортирует всю историю торговли с помощью библиотеки, и посмотрите, сколько памяти при этом расходуется.
При тестировании стратегии ea использует 25 ГБ на ядро.
Редактировать: это тест на таймфрейме 1 год, так что не так уж и много.при тестировании стратегии ea использует 25 Гб на ядро.
Редактировать: это тест на таймфрейме 1 год, так что не так уж и много.Библиотека (MT4Orders.mqh) не потребляет такое количество памяти. Вы можете запустить, например, этот советник, чтобы убедиться в этом.
Скорее всего, вы неправильно работаете с индикаторами: создаете новые хэндлы индикаторов, но не удаляете старые.