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

 
Artyom Trishkin #:

Веду у себя отдельный список ссылок на интересные и полезные решения и записываю коды в редакторе в отдельный mqh - точно не потеряется.

Лучше в отдельную ветку, Ваши записи не для всех))) а ветку в избранное и доступ есть)))

 
Valeriy Yastremskiy #:

Лучше в отдельную ветку, Ваши записи не для всех))) а ветку в избранное и доступ есть)))

Так эта ветка для этого и создана. Зачем ещё одну?

 
Artyom Trishkin #:

Так эта ветка для этого и создана. Зачем ещё одну?

В этой - поиск и обсуждение, а новую - для зафиксированных находок. Ещё бы и с оглавлением в 1 посте.

 
Artyom Trishkin #:

Так эта ветка для этого и создана. Зачем ещё одну?

вроде как да, но ... нет


 

Более быстрая функция TimeToStruct() для декодирования переменных времени суток, чтобы получить все компоненты даты и времени.

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

Бенчмарк:

#define  SIZE 10000000
//+------------------------------------------------------------------+
void OnStart() {
   ulong sum = 0;
   datetime t[];
   ArrayResize(t, SIZE);
   for(int i = 0;i<SIZE;i++) {
      t[i] = datetime(randUlong(ulong(365)*128*3600*24));
   }
   ulong tt = GetMicrosecondCount();
   for(int i=0; i<SIZE; i++) {
      MqlDateTime dt;
      TimeToStruct(t[i], dt);   // <----------------------------- (1)
      //int mm =dt.year+ dt.mon+ dt.day+ dt.hour+ dt.min+ dt.sec+ dt.day_of_week+ dt.day_of_year;
      int mm =dt.mon;
      sum+=mm;
   }
   tt = GetMicrosecondCount()-tt;
   Print("1 - " + DoubleToString(tt*1000.0/SIZE,2) + " ns, контрольная сумма = " + string(sum)+"  // TimeToStruct");
   ///////////
   sum = 0;
   tt = GetMicrosecondCount();
   for(int i=0; i<SIZE; i++) {
      MqlDateTime dt;
      TimeToStructFast(t[i], dt);   // <----------------------------- (2)
      //int mm =dt.year+ dt.mon+ dt.day+ dt.hour+ dt.min+ dt.sec+ dt.day_of_week+ dt.day_of_year;
      int mm =dt.mon;
      sum+=mm;
   }
   tt = GetMicrosecondCount()-tt;
   Print("2 - " + DoubleToString(tt*1000.0/SIZE,2) + " ns, контрольная сумма = " + string(sum)+"  // amrali");
   }
//+------------------------------------------------------------------+
ulong randUlong(ulong max=ULONG_MAX) {
   return(((ulong)rand()<<60)|((ulong)rand()<<45)|((ulong)rand()<<30)|((ulong)rand()<<15)|(ulong)rand())%max;
}
//+------------------------------------------------------------------+
bool TimeToStructFast(datetime time, MqlDateTime& dt_struct)
  {
   int y = 4716   ;
   int j = 1401   ;
   int m = 2      ;
   int n = 12     ;
   int r = 4      ;
   int p = 1461   ;
   int v = 3      ;
   int u = 5      ;
   int s = 153    ;
   int w = 2      ;
   int B = 274277 ;
   int C = -38    ;
   int x = (int)(time / 86400)                           ;  // Unix day
   int J = x + 2440588                                   ;  // Julian day
   int f = J + j + (((4 * J + B) / 146097) * 3) / 4 + C  ;
   int e = r * f + v                                     ;
   int g = (e % p) / r                                   ;
   int h = u * g + w                                     ;
   int D = (h % s) / u + 1                               ;
   int M = (h / s + m) % n + 1                           ;
   int Y = (e / p) - y + (n + m - M) / n                 ;
   int HH  = (int)((time / 3600) % 24)                   ;
   int MM  = (int)((time / 60) % 60)                     ;
   int SS  = (int)(time % 60)                            ;
   int dow = (x + 4) % 7                                 ;
   int doy = x - ((Y * 5844 - 11512676) >> 4)            ;

   // string TimeToStringFast(datetime time)
   //return StringFormat("%.2d/%.2d/%.2d %.2d:%.2d:%.2d",Y,M,D,HH,MM,SS);

   dt_struct.year           = Y;
   dt_struct.mon            = M;
   dt_struct.day            = D;
   dt_struct.hour           = HH;
   dt_struct.min            = MM;
   dt_struct.sec            = SS;
   dt_struct.day_of_week    = dow;
   dt_struct.day_of_year    = doy;

   return (true);
  }

// Algorithm: https://en.wikipedia.org/wiki/Julian_day#Julian_or_Gregorian_calendar_from_Julian_day_number

// Branchless code: check it here https://godbolt.org/z/hYbr6h45P

Результаты:

2024.04.21 03:31:26.019 TimeToStructFast (EURUSD,H1)    1 - 18.16 ns, контрольная сумма = 65174992  // TimeToStruct
2024.04.21 03:31:26.060 TimeToStructFast (EURUSD,H1)    2 - 4.10  ns, контрольная сумма = 65174992  // amrali
2024.04.21 03:31:26.995 TimeToStructFast (EURUSD,H1)    1 - 18.26 ns, контрольная сумма = 65184753  // TimeToStruct
2024.04.21 03:31:27.037 TimeToStructFast (EURUSD,H1)    2 - 4.10  ns, контрольная сумма = 65184753  // amrali
2024.04.21 03:31:29.114 TimeToStructFast (EURUSD,H1)    1 - 18.08 ns, контрольная сумма = 65197160  // TimeToStruct
2024.04.21 03:31:29.157 TimeToStructFast (EURUSD,H1)    2 - 4.31  ns, контрольная сумма = 65197160  // amrali
Файлы:
 
amrali #:

Более быстрая функция TimeToStruct() для декодирования переменных времени суток, чтобы получить все компоненты даты и времени.

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

Бенчмарк:

Результаты:

Очень круто! Особенно то, что не используются статические массивы. Можно взять эту функцию за основу. 
Спасибо @amrali за проделанное исследование и работу.

Только важно понимать, что после оптимизации компилятора, код функции упроститься и не будут расчитываться те значения структуры MqlDateTime, которые не принимают участия в расчете контрольной суммы. 
Поэтому объективный результат все же будет с таким расчетом:

uint mm =dt.year+ dt.mon+ dt.day+ dt.hour+ dt.min+ dt.sec+ dt.day_of_week+ dt.day_of_year;
sum+=mm;

результат:

2024.04.20 22:47:04.405 TestDate3 (EURUSD,M1)   1 - 23.31 ns, контрольная сумма = 23112112280  // TimeToStruct
2024.04.20 22:47:04.530 TestDate3 (EURUSD,M1)   2 - 12.49 ns, контрольная сумма = 23112112280  // amrali
2024.04.20 22:47:05.622 TestDate3 (EURUSD,M1)   1 - 22.53 ns, контрольная сумма = 23112276291  // TimeToStruct
2024.04.20 22:47:05.740 TestDate3 (EURUSD,M1)   2 - 11.79 ns, контрольная сумма = 23112276291  // amrali
2024.04.20 22:47:06.724 TestDate3 (EURUSD,M1)   1 - 22.54 ns, контрольная сумма = 23111452828  // TimeToStruct
2024.04.20 22:47:06.850 TestDate3 (EURUSD,M1)   2 - 12.56 ns, контрольная сумма = 23111452828  // amrali
 
Nikolai Semko #:

Только важно понимать, что после оптимизации компилятора код функции будет упрощен и те значения структуры MqlDateTime, которые не участвуют в вычислении контрольной суммы, вычисляться не будут.
Поэтому объективный результат все равно будет с этим вычислением:

result:

Ты голый гений!
Я не понял, почему такая задержка при вычислении контрольной суммы от всех членов.
 
amrali #:
Я не понял, почему такая задержка при вычислении контрольной суммы от всех членов.

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

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

fxsaber, 2024.04.16 17:56

К сожалению, исходный код StructToTime не анализируется компилятором, а подключается в виде имфортируемой функции. Поэтому StructToTime при каждом вызове считает все поля структуры.

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


MQ неоднократно говорили, что включат исходный код штатных функций при компиляции. К сожалению, со StructToTime этого не произошло.

 
fxsaber #:

Приятно это слышать!

Спасибо.

 
Nikolai Semko #:

Можно резюмировать 
Набор быстрых функций без применения структуры для получения параметров даты и времени до 2100 года по одному входному параметру datetime:

Для полноты GetWeekOfYear никто не хочет добавить?

Причина обращения: