Особенности языка mql5, тонкости и приёмы работы - страница 253

 
Nikolai Semko #:

Я как-то говорил, что хорошая идея год начинать с 1 марта, а не с 1 января. Тогда кривой февраль становится последним месяцем. 
Тогда можно будет применить для нахождения месяца формулу:

Посмотрите эту реализацию.

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Особенности языка mql5, тонкости и приёмы работы

fxsaber, 2024.04.16 18:31

Легкий для понимания исходник.

// https://github.com/NewYaroslav/xtime_cpp/blob/master/src/xtime.hpp
struct MqlDateTime 
  { 
   int year;           // uint32_t get_year(const timestamp_t timestamp = get_timestamp())
   int mon;            // uint32_t get_month(const timestamp_t timestamp = get_timestamp())
   int day;            // uint32_t get_day_month(const timestamp_t timestamp = get_timestamp())
   int hour;           // uint32_t get_hour_day(const timestamp_t timestamp = get_timestamp())
   int min;            // uint32_t get_minute_hour(const timestamp_t timestamp = get_timestamp())
   int sec;            // uint32_t get_second_minute(const timestamp_t timestamp = get_timestamp())
   int day_of_week;    // uint32_t get_weekday(const timestamp_t timestamp = get_timestamp())
   int day_of_year;    // uint32_t get_day_year(const timestamp_t timestamp = get_timestamp())
  };
 
fxsaber #:

Посмотрите эту реализацию.

Ха-ха, там сильно не заморочились, а просто влупили массив на 365 (или 366) элементов

возможно это оправдано

 
Nikolai Semko #:

Ха-ха, там сильно не заморочились, а просто влупили массив на 365 (или 366) элементов

возможно это оправдано

Если скорость выше альтернатив - оправдано 100%.

 
fxsaber #:

Если скорость выше, чем у альтернативных вариантов, она оправдана на 100%.

Решения с использованием таблиц поиска часто оказываются самыми быстрыми, особенно в критичных по времени участках кода.

Иногда лучше не быть таким умным :)

Редактировать:
Это напоминает мне о самых быстрых алгоритмах вычисления int logs и clz.
 
Nikolai Semko #:
Я как-то говорил, что хорошая идея год начинать с 1 марта, а не с 1 января.

Возможно, так и было когда-то. Не зря говорят, что у славян новый год был в марте.

Смотрите латинский/санскрит: 7 - septem/сапта, 8 - octo/ашта, 9 - novem/нава, 10 - decem/даша. Соответственно, 11 месяц был январь, а 12 - февраль.

 
Nikolai Semko #:

Да, я тоже проверил.

результат:

время расчета функции 1-3 нс. Свет за это время проходит 30 см - 1 метр :)))

Я изменил название GetMonthTime4 на более описательное:

//+------------------------------------------------------------------+
//| Create a datetime value from the given year, month and day.      |
//| https://www.mql5.com/en/forum/393227/page251#comment_53067868    |
//+------------------------------------------------------------------+
datetime CreateDateTime(const int iYear, const int iMonth, const int iDay)
  {
// MqlDateTime dt = {iYear, iMonth, iDay}
// return StructToTime(dt);

   static const int dm[] = {0, 0, 31, 59, 90, 120, 151, 181, 212,243, 273, 304, 334};
   int leap_days = (iYear - 1968) / 4 - (iYear % 4 == 0 && iMonth < 3);
   return datetime((iYear - 1970) * 365 + leap_days + dm[iMonth] + iDay - 1) * 86400;
  }

benchmark:

void OnStart()
  {
   int k = 5000;
   ulong sum1 = 0;
   ulong sum2 = 0;
   uint start = GetTickCount();
   for(int i = 0; i < k; i++)
      for(int y = 1970; y <= 2099; y++)
         for(int m = 1; m <= 12; m++)
            for(int d = 1; d <= 28; d++)
              {
               MqlDateTime st = {y, m, d};
               sum1 += StructToTime(st);  // <-------------------
              }
   PrintFormat("StructToTime() -> %u msec", GetTickCount()-start);
   start = GetTickCount();
   for(int i = 0; i < k; i++)
      for(int y = 1970; y <= 2099; y++)
         for(int m = 1; m <= 12; m++)
            for(int d = 1; d <= 28; d++)
              {
               sum2 += CreateDateTime(y, m, d);  // <-------------------
              }
   PrintFormat("CreateDateTime() -> %u msec", GetTickCount()-start);
//--- Display results.
   Print("sum1: ", sum1);
   Print("sum2: ", sum2);
  }

Результаты:

2024.04.18 02:50:07.953 benchmark_CreateDateTime (EURUSD,H1)    StructToTime() -> 6688 msec
2024.04.18 02:50:08.010 benchmark_CreateDateTime (EURUSD,H1)    CreateDateTime() -> 62 msec
2024.04.18 02:50:08.010 benchmark_CreateDateTime (EURUSD,H1)    sum1: 447943668480000000
2024.04.18 02:50:08.010 benchmark_CreateDateTime (EURUSD,H1)    sum2: 447943668480000000

Вау! В 100 раз быстрее, чем нативный способ.

Забудьте о StringToTime(). Она чрезвычайно медленная!
 
amrali #:

Я изменил имя GetMonthTime4 на более описательное:

benchmark:

Результаты:

Вау! В 100 раз быстрее, чем родной способ.

Я хочу попробовать запустить это. Чему равно 'DAY'?

'DAY' - undeclared identifier
 
Vladislav Boyko #:

Я хочу попробовать запустить это. Чему равно 'DAY'?

исправлено.

 
amrali #:

Я изменил имя GetMonthTime4 на более описательное:

benchmark:

Результаты:

Вау! В 100 раз быстрее, чем нативный способ.

Забудьте о StringToTime(). Она чрезвычайно медленная!

Ваш код хорошо подходит для оптимизации компилятором.

Максимальная оптимизация:

StructToTime() -> 13421 msec
CreateDateTime() -> 125 msec
sum1: 447943668480000000
sum2: 447943668480000000

Нет оптимизации:

StructToTime() -> 12937 msec
CreateDateTime() -> 1860 msec
sum1: 447943668480000000
sum2: 447943668480000000

Я просто делюсь результатами своих экспериментов.

 
amrali #:

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

Файлы:
Причина обращения: