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

 
Более быстрая реализация стандартной функции PeriodSeconds():
int PeriodSecondsFast(ENUM_TIMEFRAMES tf) {
   return (tf>>14==0)?(tf&0x0FFF)*60:(tf>>14==1)?(tf&0x0FFF)*60*60:(tf>>14==2)?60*60*24*7:2419200;
}

 
Nikolai Semko #:
Более быстрая реализация стандартной функции PeriodSeconds():

Посмотрел формат.

template <typename T>
bool IsCorrect( const int Index )
{
  ResetLastError();
  
  return((EnumToString((T)Index) != NULL) && !_LastError);
}

template <typename T>
string ToBits( const T Value )
{
  string Str = NULL;
  
  for(uint i = sizeof(T) << 3; (bool)i--;)
    Str += (string)(int)(!!(Value & (1 << i)));
    
  return(Str);
}

void OnStart()
{
  for (int i = 0; i < 1e7; i++)
    if (IsCorrect<ENUM_TIMEFRAMES>(i))
      Print(ToBits(i) + " - " + EnumToString((ENUM_TIMEFRAMES)i) + ", " + (string)i);
}
00000000000000000000000000000000 - PERIOD_CURRENT, 0
00000000000000000000000000000001 - PERIOD_M1, 1
00000000000000000000000000000010 - PERIOD_M2, 2
00000000000000000000000000000011 - PERIOD_M3, 3
00000000000000000000000000000100 - PERIOD_M4, 4
00000000000000000000000000000101 - PERIOD_M5, 5
00000000000000000000000000000110 - PERIOD_M6, 6
00000000000000000000000000001010 - PERIOD_M10, 10
00000000000000000000000000001100 - PERIOD_M12, 12
00000000000000000000000000001111 - PERIOD_M15, 15
00000000000000000000000000010100 - PERIOD_M20, 20
00000000000000000000000000011110 - PERIOD_M30, 30
00000000000000000100000000000001 - PERIOD_H1, 16385
00000000000000000100000000000010 - PERIOD_H2, 16386
00000000000000000100000000000011 - PERIOD_H3, 16387
00000000000000000100000000000100 - PERIOD_H4, 16388
00000000000000000100000000000110 - PERIOD_H6, 16390
00000000000000000100000000001000 - PERIOD_H8, 16392
00000000000000000100000000001100 - PERIOD_H12, 16396
00000000000000000100000000011000 - PERIOD_D1, 16408
00000000000000001000000000000001 - PERIOD_W1, 32769
00000000000000001100000000000001 - PERIOD_MN1, 49153

Наверное, не ускорить. Слышал, правда, про чудесную скорость switch.

int PeriodSecondsFast( const ENUM_TIMEFRAMES tf )
{
  switch (tf)
  {
    case PERIOD_CURRENT: return(PeriodSecondsFast(_Period));      
    case PERIOD_M1:      return(60);
    case PERIOD_M2:      return(120);
    case PERIOD_M3:      return(180);
    case PERIOD_M4:      return(240);
    case PERIOD_M5:      return(300);
    case PERIOD_M6:      return(360);
    case PERIOD_M10:     return(600);
    case PERIOD_M12:     return(720);
    case PERIOD_M15:     return(900);
    case PERIOD_M20:     return(1200);
    case PERIOD_M30:     return(1800);
    case PERIOD_H1:      return(3600);
    case PERIOD_H2:      return(7200);
    case PERIOD_H3:      return(10800);
    case PERIOD_H4:      return(14400);
    case PERIOD_H6:      return(21600);
    case PERIOD_H8:      return(28800);
    case PERIOD_H12:     return(43200);
    case PERIOD_D1:      return(86400);
    case PERIOD_W1:      return(604800);
    case PERIOD_MN1:     return(2592000);
  }
  
  return(0);
}
 
fxsaber #:

Посмотрел формат.

Наверное, не ускорить. Слышал, правда, про чудесную скорость switch.

выглядит длиннее, но разницы в производительности не заметил.

int PeriodSecondsFast2(ENUM_TIMEFRAMES tf) {
   ushort i_tf= ushort(tf);
   uchar _i =uchar(i_tf>>14);
   int n = i_tf & 0x0FFF;
   switch(_i) {
   case 0: // минуты
      return n*60;
   case 1: // часы
      return n*60*60;
   case 2: // недели
      return 60*60*24*7;
   case 3: // месяцы
      return 2592000;
   }
   return -1;
}

поэтому, думаю, все же предпочтителен однострочный вариант

int PeriodSecondsFast(ENUM_TIMEFRAMES tf) {
   return (tf>>14==0)?(tf&0x0FFF)*60:(tf>>14==1)?(tf&0x0FFF)*60*60:(tf>>14==2)?60*60*24*7:60*60*24*30;
}
 
Nikolai Semko #:

выглядит длиннее

int PeriodSecondsFast( const ENUM_TIMEFRAMES tf )
{
  static const int Mult[] = {60, 60 * 60, 60 * 60 * 24 * 7, 60 * 60 * 24 * 30};
  
  return((tf & 0xFF) * Mult[tf >> 14]);
}
 

а теперь всё это ещё перегнать в матрицы и ONX :-)

 
fxsaber #:

ну да. Можно и так. Более читаемо.
производительность на моем ноутбуке та же.

 

fxsaber #:

int PeriodSecondsFast( const ENUM_TIMEFRAMES tf )
{
  static const int Mult[] = {60, 60 * 60, 60 * 60 * 24 * 7, 60 * 60 * 24 * 30};
  
  return((tf & 0xFF) * Mult[tf >> 14]);
}

Кстати, я ошибся в предыдущих постах. Почему-то думал что 28 дней в месяце, а не 30. Не понимаю, где я это взял. 
Не могу уже исправить свои сообщения, возраст которых больше 1 часа. 

Поэтому мой правильный вариант такой:

int PeriodSecondsFast(ENUM_TIMEFRAMES tf) {
   return (tf>>14==0)?(tf&0xFF)*60:(tf>>14==1)?(tf&0xFF)*60*60:(tf>>14==2)?60*60*24*7:60*60*24*30;
}

Впрочем секунды месяца никому не нужны, т.к. месяцы разные по продолжительности

 
Nikolai Semko # :

Кстати, я ошибся в предыдущих постах. Почему-то думал что 28 дней в месяце, а не 30. Не понимаю, где я это взял. 
Не могу уже исправить свои сообщения, возраст которых больше 1 часа. 

Поэтому мой правильный вариант такой:

Впрочем секунды месяца никому не нужны, т.к. месяцы разные по продолжительности

Что заставляет вас думать, что это быстрее, чем PeriodSeconds(x) ?
 
Alain Verleyen #:
Что заставляет вас думать, что это быстрее, чем PeriodSeconds(x) ?

тест с этого поста

достаточно сравнить работу функции getStartTimeOfBar() с  PeriodSeconds() и с PeriodSecondsFast()

Сравнивать нужно на любых TF, кроме MN1

Производительность выше примерно в 2 раза. Может в 3 с учетом того, что мы замеряем всю итерацию.


или достаточно сравнить эти два значения


2023.11.14 22:44:52.581 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H8========
2023.11.14 22:44:52.581 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000623961600, время выполнения 1 иттерации = 6.80 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 22:44:52.581 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000623961600, время выполнения 1 иттерации = 3.40 наносекунд - Быстрый расчет
2023.11.14 22:44:57.734 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000252960000, время выполнения 1 иттерации = 515301.20 наносекунд - Расчет через iBarShift
2023.11.14 22:44:57.734 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 22:45:16.253 timeToStartMonth (EURUSD,M1)    60 ,120 ,180 ,240 ,300 ,360 ,600 ,720 ,900 ,1200 ,1800 ,3600 ,7200 ,10800 ,14400 ,21600 ,28800 ,43200 ,86400 ,604800 ,2592000 ,
2023.11.14 22:45:16.253 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_M4========
2023.11.14 22:45:16.253 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000769600080, время выполнения 1 иттерации = 3.70 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 22:45:16.253 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000769600080, время выполнения 1 иттерации = 1.90 наносекунд - Быстрый расчет
2023.11.14 22:45:16.471 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000394543440, время выполнения 1 иттерации = 21746.60 наносекунд - Расчет через iBarShift
2023.11.14 22:45:16.471 timeToStartMonth (EURUSD,M1)    ========================================================================
2023.11.14 22:45:57.038 timeToStartMonth (EURUSD,M1)    60 ,120 ,180 ,240 ,300 ,360 ,600 ,720 ,900 ,1200 ,1800 ,3600 ,7200 ,10800 ,14400 ,21600 ,28800 ,43200 ,86400 ,604800 ,2592000 ,
2023.11.14 22:45:57.038 timeToStartMonth (EURUSD,M1)    =====LOOP=10000========STEPS=100000 seconds======PERIOD_H1========
2023.11.14 22:45:57.038 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000751999200, время выполнения 1 иттерации = 5.30 наносекунд - Расчет через структуру MqlDateTime
2023.11.14 22:45:57.038 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000751999200, время выполнения 1 иттерации = 3.00 наносекунд - Быстрый расчет
2023.11.14 22:45:57.072 timeToStartMonth (EURUSD,M1)    контрольная сумма - 12000378405600, время выполнения 1 иттерации = 3410.10 наносекунд - Расчет через iBarShift
2023.11.14 22:45:57.072 timeToStartMonth (EURUSD,M1)    ========================================================================

 
Nikolai Semko # :

тест с этого поста

достаточно сравнить работу функции getStartTimeOfBar() с  PeriodSeconds()  и с  PeriodSecondsFast()

Сравнивать нужно на любых TF, кроме MN1

Производительность выше примерно в 2 раза. Может в 3 с учетом того, что мы замеряем всю итерацию.


или достаточно сравнить эти два значения



Возможно, я что-то упускаю, но я использовал ваш скрипт для проверки PeriodSeconds (только).


Файлы:
__.mq5  13 kb
Причина обращения: