1. Excellent compression ratio 10:1 (6 GB ticks.bin can be compressed into 660 MB file).
2. Speed of decompression is very fast.
Bug found:
#property script_show_inputs input datetime inFrom = D'2025.07.01'; input string inSymb = "EURUSD"; #include "TicksShort.mqh" void OnStart() { MqlTick Ticks[]; if (CopyTicksRange(inSymb, Ticks, COPY_TICKS_ALL,(ulong)inFrom * 1000) > 0) { TICK_SHORT Compressed[]; TICKS_SHORT::Compress(Ticks, Compressed); Print("Correct = " + (string)TICKS_SHORT::IsEqual(Ticks, Compressed)); } } // Launching on different charts: // (EURUSD,H1) Correct = true // (USDJPY,H1) Correct = false // (BTCUSD,D1) Correct = false
Bug fix "TicksShort.mqh":
// static int Compress( const MqlTick &TicksIn[], TICK_SHORT &TicksOut[], const int iDigits = INT_MAX ) static int Compress( const MqlTick &TicksIn[], TICK_SHORT &TicksOut[], const int iDigits = -1 ) { // ... }
Это было сделано специально. Когда записываешь в файл, то это обычно большой объем данных, поэтому почти гарантировано будет правильно вычислен Digits, поэтому там iDigits = -1.
А вот с массивами далеко не так. Массив может быть и из одного только элемента. Поэтому важно понимать, что iDigits-параметр нужно задавать почти во всех случаях, кроме текущего символа.
Эти функции работы с файлами и массивами являются просто дополнением основного функционала. Поскольку сжимать тики - это нужно единицам пользователей, то предпочел просто указать ALT+M в описании.
My experimental version with clear code comments and optimized performance.
Uses delta encoding of ticks + zigzag encoding of small negative deltas for more efficient bit-packing.
TicksShort_Performance (EURUSD,H1) Compressed 1411131480 bytes into 141113316 bytes ==> 10.00% TicksShort_Performance (EURUSD,H1) Compress performance: 14004 MB/s TicksShort_Performance (EURUSD,H1) Compress performance: 244.7 Ticks (millions)/sec. TicksShort_Performance (EURUSD,H1) Compress performance criterion: 2447.3 TicksShort_Performance (EURUSD,H1) Decompress performance: 5820 MB/s TicksShort_Performance (EURUSD,H1) Decompress performance: 101.7 Ticks (millions)/sec. TicksShort_Performance (EURUSD,H1) Decompress performance criterion: 1017.1 TicksShort_Performance (EURUSD,H1) Correct = true
My experimental version with clear code comments and optimized performance.
Uses delta encoding of ticks + zigzag encoding of small negative deltas for more efficient bit-packing.
Ваш вариант на 20% быстрее на декомпрессии. И это очень хорошо!
Для моей задачи нужна именно быстрая декомпрессия, поэтому только этот показатель смотрю.
Однако, я не вижу алгоритмических причин быть быстрее.
Ниже ваш вариант.
static void UnpackDeltaTick(const TICK_SHORT &tick, uint &dBid, uint &dAsk, uint &dTime) { // Decode delta tick, 6 bytes dBid = tick.UShort0 & 0x0FFF; // 12 bits dAsk = ((tick.UShort0 >> 12) | // 12 bits (4 + 8) ((tick.UInt1 & 0xFF) << 4)); dTime = tick.UInt1 >> 9; // 23 bits } const bool isDelta = (ticks[i].UInt1 & C_DELTA_FLAG); if (isDelta) { uint dBid = 0, dAsk = 0; uint dTime = 0; UnpackDeltaTick(ticks[i], dBid, dAsk, dTime); // Bit-unpacking bid += ZigzagDecode(dBid); // ZigZag decoding & delta reconstruction ask += ZigzagDecode(dAsk); time_msc += dTime; } result[index].bid = NormalizeDouble(bid * point, digits); // Price conversion to double result[index].ask = NormalizeDouble(ask * point, digits); result[index].time_msc = (long)time_msc; result[index].time = (datetime)(time_msc / 1000);
Мой вариант.
bool Load( int &ShiftBid, int &ShiftAsk, uint &ShiftTime ) const { const bool Res = (this.Struct0.UInt1 & FLAG); if (Res) { ShiftBid = (this.Struct0.UShort0 & 0x0FFF) - SHIFT; ShiftAsk = this.Struct1.Short1 >> 4; ShiftTime = this.Struct0.UInt1 >> 9; } return(Res); } if ((this.FlagLoad = TickIn.Load(ShiftBid, ShiftAsk, ShiftTime))) { TickOut.bid = ::NormalizeDouble((this.PriceBid += ShiftBid) * this.Pow, 7/* this.digits*/); TickOut.ask = ::NormalizeDouble((this.PriceAsk += ShiftAsk) * this.Pow, 7/* this.digits*/); TickOut.time = (datetime)((TickOut.time_msc = (long)(this.Time_Msc += ShiftTime)) / 1000); }
Отметил только те места, что отличают оба варианта. В вашем варианте, вроде, больше вычислений. Более того, видится, что для dAsk можно не использовать ZigZag и получить сразу знаковое значение, как это делается в моем варианте.
Предполагаю, что ускорение достигается за счет оптимизации со стороны компиляции. У меня идет заполнение массива не напрямую, а через внутреннюю функцию. Так специально задумано.
Your version is 20% faster on decompression. And that's very good!
For my task, I need fast decompression, so I only look at this indicator.
However, I don't see any algorithmic reason to be faster.
Below is your option.
My option.
I have only noted the places that distinguish both variants. Your variant seems to have more calculations. Moreover, it seems that for dAsk you can skip ZigZag and get a signed value right away, as is done in my variant.
I assume that the acceleration is achieved through optimization on the compilation side. I fill the array not directly, but through an internal function. This is specially intended.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
TicksShort:
Короткий формат хранения тиков.
Автор: fxsaber