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

 

После починки кодобазы будет доступен CopyTicksRange, который потребляет на порядок меньше памяти (чем штатный) и работает быстрее.


Пример.

#include <fxsaber\TicksShort\LotsTicks.mqh> // https://www.mql5.com/ru/code/61126

// Пример, как можно фильтровать тики.
void Filter( LOTS_TICKS &LotsTicks, const int Reserve = 0 )
{
  int Count = 0;
  MqlTick Tick;

  LotsTicks.Init(); // Сбросили указатель тиков на начало.
    
  while (LotsTicks.NextTick(Tick)) // Запрашиваем последовательно тики.
    if (!(Count++ & 1))  // Срабатывает на каждом втором.
      LotsTicks += Tick; // Нужные тики записываем.
      
  LotsTicks.Resize(Reserve); // Корректируем размер под записанные нужные тики. -1 - физическое перераспределение памяти.
  
  return;
}

#define PRINT(A) Print(#A + " = " + (string)(A) + "\n");

void OnStart()
{
  LOTS_TICKS LotsTicks;
  PRINT(MQLInfoInteger(MQL_MEMORY_USED)); // Сколько памяти потребляет программа.
    
  // Получили соответствующий интервал тиков.
  const long Size = LotsTicks.CopyTicksRange(_Symbol, COPY_TICKS_ALL, D'2020.03.01' * 1000, D'2025.09.01' * 1000);
  Print("ArraySize(MqlTick[]) = " + (string)((Size * sizeof(MqlTick)) >> 20) + " MB");  // Сколько памяти занимает MqlTick[].
  PRINT(MQLInfoInteger(MQL_MEMORY_USED)); // Сколько памяти потребляет программа.
  
  // Фильтрация полученных тиков.
  Print("\nFiltering...");
  Filter(LotsTicks, -1); // Применили фильтр тиков.
  PRINT(MQLInfoInteger(MQL_MEMORY_USED));  // Сколько памяти потребляет программа.

  const string Name = "CUSTOM_" + _Symbol;  // Название кастомного символа.
  
  // Работа с кастомным символом.
  CustomSymbolCreate(Name, NULL, _Symbol); // Создали кастомный символ.  
  LotsTicks.CustomTicksReplace(Name);      // Записали тики в кастомный символ.
}

Заодно показан сразу дешевый по памяти сброс тиков в кастомный символ.


Результат.

MQLInfoInteger(MQL_MEMORY_USED) = 0

XAUUSD.pro ticks request: 2020.03.01 00:00:00.000 - 2025.09.01 00:00:00.000, Length = 5 Years 6 Months
...
XAUUSD.pro ticks: 2020.03.01 00:00:00.000 - 2020.03.31 23:59:59.999, Amount = 5 384 149. [Time = 00:00:00.696 (86.8% - CopyTicks), Performance = 7.7 Ticks (millions)/sec.]
XAUUSD.pro request ticks progress 100%: Amount = 488 780 092, Length = 5 Years 6 Months. [Time  = 00:01:06.230, Estimated = 00:00:00.000]
XAUUSD.pro ticks request: 2020.03.01 00:00:00.000 - 2025.09.01 00:00:00.000, Length = 5 Years 6 Months - Done.
ArraySize(MqlTick[]) = 27968 MB
MQLInfoInteger(MQL_MEMORY_USED) = 2798


Filtering...
MQLInfoInteger(MQL_MEMORY_USED) = 1400

CUSTOM_XAUUSD.pro save ticks request: 2020.03.01 00:00:00.000 - 2025.08.31 23:59:59.999, Length = 5 Years 6 Months
...
CUSTOM_XAUUSD.pro save ticks: 2025.08.01 00:00:00.000 - 2025.08.31 23:59:59.999, Amount = 5 410 307. [Time = 00:00:04.665 (97.5% - CustomTicks), Performance = 1.2 Ticks (millions)/sec.]
CUSTOM_XAUUSD.pro request save ticks progress 100%: Amount = 244 390 046, Length = 5 Years 6 Months. [Time  = 00:03:29.971, Estimated = 00:00:00.000]
CUSTOM_XAUUSD.pro save ticks request: 2020.03.01 00:00:00.000 - 2025.08.31 23:59:59.999, Length = 5 Years 6 Months - Done.

Были запрошены тики за 5.5 лет. Это почти 500 миллионов тиков. Если бы был запрос через штатный CopyTicksRange, то потребовалось бы больше 28 Гб RAM. В данной реализации - в 10 раз меньше. Это позволило даже на очень старом компе полностью получить и хранить в памяти все 500 миллионов тиков.


Поскольку все тики хранятся в памяти, то с ними можно работать. В частности, фильтровать - см. исходник.


Столь дешевое наполнение тиками кастомных символов позволяет на этих символах получать в Тестере идентичную тиковой истории последовательность тиков. Что полностью исключает влияние рассинхронизированных баров реальных символов на генерацию тиков Тестером. Грубо говоря, Тестер выдает только те тики, что были записаны.


Напоминаю, что есть дешевый способ посмотреть данные по имеющимся тикам.

Библиотеки: MultiTester - Получите информацию об имеющихся исторических тиках по символам.
Библиотеки: MultiTester - Получите информацию об имеющихся исторических тиках по символам.
  • 2025.09.04
  • www.mql5.com
Статьи и техническая библиотека по автоматическому трейдингу: Библиотеки: MultiTester
 
fxsaber #:

После починки кодобазы будет доступен CopyTicksRange, который потребляет на порядок меньше памяти (чем штатный) и работает быстрее.

Опубликован.

 
fxsaber # :

Опубликован.

Просто потрясающе!
 

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

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

fxsaber, 2025.10.04 06:18

ЗЫ Это еще одна причина создавать кастомные символы - закидывать в историю только последний тик из последовательностей с одинаковым временем. В таком случае в моновалютном режиме будет всегда соблюдаться актуализация.

// Актуализация истории тиков.
void Filter( LOTS_TICKS &LotsTicks, const int Reserve = 0 )
{
  MqlTick PrevTick = {};
  MqlTick Tick;

  LotsTicks.Init(); // Сбросили указатель тиков на начало.
    
  while (LotsTicks.NextTick(Tick)) // Запрашиваем последовательно тики.
  {
    if (PrevTick.time_msc && (Tick.time_msc > PrevTick.time_msc))
      LotsTicks += PrevTick; // Нужные тики записываем.
    
    PrevTick = Tick;
  }
  
  if (PrevTick.time_msc)
    LotsTicks += PrevTick;   // Нужные тики записываем.
          
  LotsTicks.Resize(Reserve); // Корректируем размер под записанные нужные тики. -1 - физическое перераспределение памяти.
  
  return;
}

В полноценном примере выше замена этой функции будет создавать кастомные символы с условием актуализации.

Но надо всегда осознавать один нюанс.

 

The header file "TicksShort.mqh" provides an alternative implementation of 'TicksShort' tick compression library by fxsaber usig 'CBitBuffer' class.

https://www.mql5.com/en/code/61728

TicksShort_SaveLoad (EURUSD,M1) Ratio = 10.000
TicksShort_SaveLoad (EURUSD,M1) Correct = true
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.
 
amrali #:

The header file "TicksShort.mqh" provides an alternative implementation of 'TicksShort' tick compression library by fxsaber usig 'CBitBuffer' class.

https://www.mql5.com/en/code/61728

Ваш вариант печатает фантастический результат компрессии.
Compressed 1910938740 bytes into 105831727 bytes ==> 5.54%
Compress performance: 3637 MB/s
Compress performance: 63.6 Ticks (millions)/sec.
Compress performance criterion: 1147.8
Decompress performance: 1986 MB/s
Decompress performance: 34.7 Ticks (millions)/sec.
Decompress performance criterion: 626.7
Correct = true
Ratio = 18.056
Correct = true

Как Вы этого достигли?


После применения ZIP итоговое сжатие превышает 28x.

 
fxsaber #:

После применения ZIP итоговое сжатие превышает 28x.

Опередили даже tkc-формат.

Шикарный результат!

 
fxsaber # :

They even surpassed the tkc format.

A fantastic result!

This Delta + VLQ encoding is very efficient. It is also flexible to allow compressing other fields (volume, flags, etc..) by just adding few extra lines of code. 

      long prev_flags = 0;
      for (int i = 0; i < nticks; i++)
        {
         const MqlTick tick = ticks[i];
         long f = tick.flags;

         VLQWrite(buf, pos, ZigZagEncode(f - prev_flags));  // compress flags field

         prev_flags = f; // Update previous
        }
 
amrali #:

This Delta + VLQ encoding is very efficient. It is also flexible to allow compressing other fields (volume, flags, etc..) by just adding few extra lines of code. 

Спасибо за пример, обязательно посмотрю исходник.
 
fxsaber #:

Столь дешевое наполнение тиками кастомных символов позволяет на этих символах получать в Тестере идентичную тиковой истории последовательность тиков. Что полностью исключает влияние рассинхронизированных баров реальных символов на генерацию тиков Тестером. Грубо говоря, Тестер выдает только те тики, что были записаны.

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

#property script_show_inputs

input string inName = "";
input datetime inFrom = D'2024.09.01';
input datetime inTo = D'2026.09.01';
input bool inAntiDST = false;

#include <fxsaber\TicksShort\LotsTicks.mqh> // https://www.mql5.com/ru/code/61126

void OnStart()
{
  LOTS_TICKS LotsTicks;
  
  if ((LotsTicks.CopyTicksRange(_Symbol, COPY_TICKS_ALL, inFrom * 1000, inTo * 1000) > 0) &&   
      (!inAntiDST || LotsTicks.AntiDST())) // Не меняется время ролловера для брокеров европейского времени.
  {
    const string Name = (inName == "") ? "CUSTOM_" + _Symbol + "_AntiDST_" + (string)inAntiDST : inName;
    
    if (CustomSymbolCreate(Name, NULL, _Symbol) &&
        (LotsTicks.CustomTicksReplace(Name) > 0) &&
        SymbolSelect(Name, true))
      ChartOpen(Name, _Period);
  }
}


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

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

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

SpreadSymbol
SpreadSymbol
  • 2022.09.15
  • www.mql5.com
Индикатор спреда сразу нескольких брокеров.