Библиотеки: TicksShort - страница 6

 
fxsaber #:

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


Пример такого изменения.

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

Всплеск спреда хорошо идентифицирует время ролловера. На нижней половине видно, что DST-смещения не повлияли на время ролловера - полночь.

Очень ценно, спасибо!
 

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

Библиотеки: TicksShort

fxsaber, 2025.07.24 15:34

#define TICKS_SHORT_ALTERNATIVE
#include <fxsaber\TicksShort\TicksShort_using_digits.mqh> // https://www.mql5.com/ru/forum/490384/page2#comment_57616652

Compressed 789285600 bytes into 78928776 bytes ==> 10.00%
Compress performance: 3594 MB/s
Compress performance: 62.8 Ticks (millions)/sec.
Compress performance criterion: 628.1
Decompress performance: 2994 MB/s
Decompress performance: 52.3 Ticks (millions)/sec.
Decompress performance criterion: 523.3
Correct = true


Сделал элементарное сжатие, чтобы посмотреть почти максимальную скорость распаковки.

struct TICK24
{
  double bid;
  double ask;
  long time_msc;
  
  void Set( const MqlTick &Tick )
  {
    this.bid = Tick.bid;
    this.ask = Tick.ask;
    this.time_msc = Tick.time_msc;
    
    return;
  }
  
  void Get( MqlTick &Tick ) const
  {
    Tick.bid = this.bid;
    Tick.ask = this.ask;;
    Tick.time_msc = this.time_msc;
    
    Tick.time = (datetime)(Tick.time_msc / 1000);
    
    return;
  }
};


int Compress( const MqlTick &TicksIn[], TICK24 &TicksOut[] )
{
  const int Size = ::ArrayResize(TicksOut, ::ArraySize(TicksIn));
  
  for (int i = 0; i < Size; i++)
    TicksOut[i].Set(TicksIn[i]);
    
  return(Size);
}

int Decompress( const TICK24 &TicksIn[], MqlTick &TicksOut[] )
{
  const int Size = ::ArrayResize(TicksOut, ::ArraySize(TicksIn));
  
  for (int i = 0; i < Size; i++)
    TicksIn[i].Get(TicksOut[i]);
    
  return(Size);
}


А скорость возросла всего лишь на 20% при компрессии в четыре раза хуже.

Compressed 60000000 bytes into 24000000 bytes ==> 40.00%
Compress performance: 5817 MB/s
Compress performance: 101.7 Ticks (millions)/sec.
Compress performance criterion: 254.2
Decompress performance: 3654 MB/s
Decompress performance: 63.9 Ticks (millions)/sec.
Decompress performance criterion: 159.6
Correct = true
 
fxsaber #:

Сделал элементарное сжатие, чтобы посмотреть почти максимальную скорость распаковки.

Compressed 60000000 bytes into 60000000 bytes ==> 100.00%
Compress performance: 3807 MB/s
Compress performance: 66.5 Ticks (millions)/sec.
Compress performance criterion: 66.5
Decompress performance: 3893 MB/s
Decompress performance: 68.0 Ticks (millions)/sec.
Decompress performance criterion: 68.0
Correct = true

MqlTick[] -> MqlTick[]. Удручающе.

 
fxsaber # :

MqlTick[] -> MqlTick[]. Удручающе.

Ничто в этом мире не идеально.
 
fxsaber #:

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

Интересно, как замена деления на умножение влияет на производительность.
  int PriceToInteger( const double &Price ) const
  {
//    return((int)(Price / this.Pow + 0.1));
    return((int)(Price * this.Pow2 + 0.1));
  }


Было.

Compressed 1084618260 bytes into 108461958 bytes ==> 10.00%
Compress performance: 3386 MB/s
Compress performance: 59.2 Ticks (millions)/sec.
Compress performance criterion: 591.8


Стало.

Compressed 1084618260 bytes into 108461958 bytes ==> 10.00%
Compress performance: 4785 MB/s
Compress performance: 83.6 Ticks (millions)/sec.
Compress performance criterion: 836.2


Абсолютно бесплатно поднялась производительность компрессии почти на 40%!

 
fxsaber # :

Apparently, the division operation is significantly more expensive than the multiplication operation.

This statement needs more clarification:

  • Divisions by runtime variables cannot be optimized by the compiler, that is why these are slow than multiplications.
  • Divisions by compile-time constants can actually be optimized by the compiler into multiplications by the reciprocals, so that these are as fast as multiplications (see here).
    return((int)(Price * this.Pow2 + 0.1));
Since, this.Pow2 is a variable (not a compile-time constant), so that using multiplication (Price * this.Pow2) is faster than (Price / this.Pow), because the compiler cannot optimize that division into mult. (you have to do it yourself).
 
amrali #:

This statement needs more clarification:

Спасибо за подробности!
 
В статье автор использует Zstandart, возможно сможет помочь с тестами.
 
Rorschach #:
В статье автор использует Zstandart, возможно сможет помочь с тестами.

Не могу редактировать коменты

https://facebook.github.io/zstd/


 
Rorschach # :

I can't edit comments.

https://facebook.github.io/zstd/


All of these libraries provide general-purpose compression similar to zip compression (with variable performance).

For specific compression of time-series data (like MQL rates/ticks), delta-encoding (+/- VLQ encoding) achieves even higher compression ratios and speeds than those libraries above.

The author's library achieves 14000 MB/s for compression (and ratio = 10.0) in my tests.