Библиотеки: MathTicker - генератор тиков в математическом режиме - страница 4

 
Forester #:
Вот думаю, что если так компактно получилось - то можно сохранить всю историю за 5-6 лет и через инпуты указывать интервал тестирования. Ну и дать имена в виде названий инструментов. Подумаю...
Сделал сохранение всех тиков в файлы по годам и тестирование по заданным в инпутах датам. Описание и файл обновил.
 
Forester #:

быстрее всего с вашим скриптом распаковка  идет при int ticks_per_block=600000;.

Много времени уходит на ArrayCopy. Чем больше блок, тем меньше вызовов ArrayCopy.

Проверьте разные

Результат очень интересный по степени сжатия и скорости распаковки. Вы почти изобрели VLQ-сжатие тиков. Показатели примерно одинаковые.

Медленная компрессия в скрипте, скорее всего, вызвана частыми ArrayResize и ArrayCopy.


Понравилась статистика, что выдается в Тестере при записи тиков.


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

      if ((r < len - 4) && isFirstRead){//первый тик записан полностью
         r=0;
         this.tp=ArrToLong(m,r); T[tick].time_msc=this.tp; T[tick].time=(datetime)(T[tick].time_msc / 1000);
         this.ap=ArrToLong(m,r); T[tick].ask     =ToPrice(this.ap);
         this.bp=ArrToLong(m,r); T[tick].bid     =ToPrice(this.bp);
         if(this._TickItems > 1){v=ArrToLong(m,r); T[tick].volume_real=ToVolume(v); T[tick].volume=(ulong)round(T[tick].volume_real);}
         if(this._TickItems==3){
            this.lp=ArrToLong(m,r); T[tick].last=ToPrice(this.lp);
            T[tick].flags=ArrToUint(m,r); 
         } else {
            #ifdef RestoreFlags
               T[tick].flags=GetFlag(this.ap,this.bp,v);vp=v;//восстановить флаг
            #endif            
         }
         isFirstRead=false; tick++;
      }      

Аналогично выносить switch из-под while.

CBitBuffer Class - Data Serialization in MQL5
CBitBuffer Class - Data Serialization in MQL5
  • 2025.07.20
  • www.mql5.com
A class for reading and writing individual bits or bit sequences to and from a buffer.
 

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

Удивило, что zip-распаковка замедляет распаковку менее, чем в два раза.

 
-------------------- Statistics: --------------------
3 bytes: 86.6%, 62644158 ticks
4 bytes: 0.6%, 412167 ticks

Четыре байта может быть только при 229 <= dt <= 255?

 
fxsaber #:

Четыре байта может быть только при 229 <= dt <= 255?

да

fxsaber #:

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

Да, в вашем скрипте по 600000 тиков в блоке, у меня по 30000 - можно подобрать по скорости чтения. У вас тесты с BidAsk, а я еще и c Volume сжимал + чтение из файла, возможно поэтому разные размеры блоков оказались лучшими.
И не ZIP блоков тоже. Чтобы в едином стиле/коде было.

fxsaber #:Для скорости декомпрессии логично выносить условия из циклов. Например, делать так.

Аналогично выносить switch из-под while.

Согласен. Завтра сделаю и сравню скорость.

 
Forester #:
Сделал сохранение всех тиков в файлы по годам и тестирование по заданным в инпутах датам.
Наверное, не стоит лишать возможности оптимизировать и даты.
sinput datetime Start_Date ;//Start Date to read from full archive
sinput datetime End_Date ;//End Date to read from full archive
 
fxsaber #:

выносить switch из-под while.

После этого скорость распаковки сравнялась с моим вариантом.


TicksShort.

Compressed 1084618260 bytes into 108461958 bytes ==> 10.00%
Compress performance: 4071 MB/s
Compress performance: 71.1 Ticks (millions)/sec.
Compress performance criterion: 711.4
Decompress performance: 2634 MB/s
Decompress performance: 46.0 Ticks (millions)/sec.
Decompress performance criterion: 460.3
Correct = true


TickCompressor.

Compressed 1084618260 bytes into 66319666 bytes ==> 6.11%
Compress performance: 821 MB/s
Compress performance: 14.4 Ticks (millions)/sec.
Compress performance criterion: 234.7
Decompress performance: 2603 MB/s
Decompress performance: 45.5 Ticks (millions)/sec.
Decompress performance criterion: 744.1
Correct = true


Только у второго гораздо сильнее сжатие.

 
fxsaber #:

После этого скорость распаковки сравнялась с моим вариантом.


TicksShort.


TickCompressor.


Только у второго гораздо сильнее сжатие.

У меня скорость генерации тиков выросла на 10% после этой модификации.
Было:
2025.11.18 10:15:22.670    1 (EURUSD,H1)    Decompress performance: 49.1 Ticks (millions)/sec.
2025.11.18 10:26:22.871    1 (EURUSD,H1)    Decompress performance: 52.0 Ticks (millions)/sec.
Стало:
2025.11.18 10:26:40.381    1 (EURUSD,H1)    Decompress performance: 56.4 Ticks (millions)/sec.
2025.11.18 10:26:53.333    1 (EURUSD,H1)    Decompress performance: 55.7 Ticks (millions)/sec.
Обновлю попозже. Еще одна идея есть.

 
Forester #:

Еще одна идея есть.

Можно избавиться от большого количества NormalizeDouble.
int Amount = 0;
int Count = 0;

int PriceToInteger( const double Price, const double point )
{
  return((int)(Price / point + 0.1));
}

void OnTick()
{
  static const double Point2 = (int)(1 / _Point + 0.1);
  
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))
  {
    if (Tick.bid == PriceToInteger(Tick.bid, _Point) / Point2)
      Count++;

    Amount++;      
  }
}

double OnTester()
{
  return(Count * 100.0 / Amount); // > 99%.
}
Используйте NEW function to replace NormalizeDouble for the prices that are not normalized correctly due to -ve powers of 10.
Используйте NEW function to replace NormalizeDouble for the prices that are not normalized correctly due to -ve powers of 10.
  • 2025.07.13
  • www.mql5.com
Calls to NormalizeDouble can be effectively decreased to the minimum possible even less than you updated version ve powers of 10. The round-off error will be less when you divide N Totally Abandoning NormalizeDouble
 
Странно, что такой вариант не дал ускорения.
                  switch(f){
                     case  0:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToChar (m,r);  this.ap+=ArrToChar (m,r);  break;}
                     case  1:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToChar (m,r);  this.ap+=ArrToChar (m,r);  break;}
                     case  2:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToChar (m,r);  this.ap+=ArrToChar (m,r);  break;}
                  
                     case  3:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToShort (m,r); this.ap+=ArrToChar (m,r);  break;}
                     case  4:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToShort (m,r); this.ap+=ArrToChar (m,r);  break;}
                     case  5:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToShort (m,r); this.ap+=ArrToChar (m,r);  break;}

                     case  6:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToLong (m,r);  this.ap+=ArrToChar (m,r);  break;}
                     case  7:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToLong (m,r);  this.ap+=ArrToChar (m,r);  break;}
                     case  8:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToLong (m,r);  this.ap+=ArrToChar (m,r);  break;}

                     case  9:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToChar (m,r);  this.ap+=ArrToShort (m,r); break;}
                     case 10:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToChar (m,r);  this.ap+=ArrToShort (m,r); break;}
                     case 11:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToChar (m,r);  this.ap+=ArrToShort (m,r); break;}
                  
                     case 12:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToShort (m,r); this.ap+=ArrToShort (m,r); break;}
                     case 13:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToShort (m,r); this.ap+=ArrToShort (m,r); break;}
                     case 14:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToShort (m,r); this.ap+=ArrToShort (m,r); break;}

                     case 15:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToLong (m,r);  this.ap+=ArrToShort (m,r); break;}
                     case 16:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToLong (m,r);  this.ap+=ArrToShort (m,r); break;}
                     case 17:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToLong (m,r);  this.ap+=ArrToShort (m,r); break;}                  

                     case 18:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToChar (m,r);  this.ap+=ArrToLong (m,r);  break;}
                     case 19:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToChar (m,r);  this.ap+=ArrToLong (m,r);  break;}
                     case 20:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToChar (m,r);  this.ap+=ArrToLong (m,r);  break;}
                  
                     case 21:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToShort (m,r); this.ap+=ArrToLong (m,r);  break;}
                     case 22:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToShort (m,r); this.ap+=ArrToLong (m,r);  break;}
                     case 23:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToShort (m,r); this.ap+=ArrToLong (m,r);  break;}

                     case 24:{this.tp+=ArrToUchar (m,r);  this.bp+=ArrToLong (m,r);  this.ap+=ArrToLong (m,r);  break;}
                     case 25:{this.tp+=ArrToUshort (m,r); this.bp+=ArrToLong (m,r);  this.ap+=ArrToLong (m,r);  break;}
                     case 26:{this.tp+=ArrToLong (m,r);   this.bp+=ArrToLong (m,r);  this.ap+=ArrToLong (m,r);  break;}
                  }