CustomRatesReplace: чрезмерный рост размера .hcc при последовательной записи M1-баров

При работе с историей пользовательских символов MT5 столкнулся с проблемой сильного разрастания файлов .hcc.

В реальных условиях отдельные годовые файлы истории достигали нескольких гигабайт.

При непрерывной работе моего сервиса-криптомоста на 14 символах свободное место на диске начало уменьшаться примерно по 1 Гб в сутки.

Удалось воспроизвести этот эффект в небольшом изолированном тесте с использованием CustomRatesReplace().


Среда тестирования: MetaTrader 5, build 6230. Необходимо разрешить импорт DLL для получения размеров hcc файлов.

При трёхминутном тесте скрипт генерирует 180 искусственных M1-баров с последовательным временем открытия, фиксированными OHLC, объёмами и спредом.

Сравниваются два способа записи одних и тех же баров в пользовательские символы:


BULK — пакетная запись

Для каждой контрольной точки (30, 60, 90,120, 150 и 180 баров) создаётся новый пользовательский символ с пустой историей.

Все N баров записываются одним вызовом: CustomRatesReplace(symbol, first, last, bars)

Таким образом, каждый BULK-файл формируется независимо, ровно одним вызовом CustomRatesReplace.


SEQ — последовательная запись

Создаётся один пользовательский символ, в который те же бары записываются по одному, с интервалом в одну секунду.

Для каждого бара вызывается: CustomRatesReplace(symbol, bar.time, bar.time, one_bar)


После каждых 30 вызовов измеряется физический размер годового файла 2025.hcc.

На каждой контрольной точке оба варианта содержат одинаковое количество одинаковых M1-баров.

Размер .hcc измеряется непосредственно средствами Windows API (GetFileAttributesExW), а не оценивается по количеству баров.


Сравнение скорости роста размера файлов:

Количество M1 BULK, байт SEQ, байт
30 17 133 48 714
60 18 933 136 284
90 20 733 277 854
120 22 533 473 424
150 24 333 722 994
180 26 133 1 026 564



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

После записи 180 баров:

BULK: 26 133 байта, один вызов CustomRatesReplace

SEQ: 1 026 564 байта, 180 вызовов CustomRatesReplace

Разница: 39 раз


Лог:
2026.10.10 13:49:01.591 Terminal build: 6230
2026.10.10 13:49:01.591 Test duration: 3 min; M1 bars: 180; size step: 30 M1
2026.10.10 13:49:01.599 SEQ symbol: TestHCCSeq_261010_134901_5109
2026.10.10 13:49:01.599 SEQ HCC: C:\Program Files\MetaTrader 5\bases\Custom\history\TestHCCSeq_261010_134901_5109\2025.hcc
2026.10.10 13:49:30.763 BULK symbol for 30 M1: HCCBulk_30_261010_134901_5109
2026.10.10 13:49:30.763 BULK HCC: C:\Program Files\MetaTrader 5\bases\Custom\history\HCCBulk_30_261010_134901_5109\2025.hcc
2026.10.10 13:49:31.005 BULK after 1 call (30 M1): HCC = 17133 bytes
2026.10.10 13:49:31.005 SEQ after 30 calls (30 M1): HCC = 48714 bytes
2026.10.10 13:49:31.016 HCCBulk_30_261010_134901_5109: 30 M1, all fields match input
2026.10.10 13:49:31.026 TestHCCSeq_261010_134901_5109: 30 M1, all fields match input
2026.10.10 13:49:31.026 POINT: M1=30, BULK=17133 bytes (1 call), SEQ=48714 bytes (30 calls), SEQ/BULK=2.843x
2026.10.10 13:50:01.243 BULK symbol for 60 M1: HCCBulk_60_261010_134901_5109
2026.10.10 13:50:01.243 BULK HCC: C:\Program Files\MetaTrader 5\bases\Custom\history\HCCBulk_60_261010_134901_5109\2025.hcc
2026.10.10 13:50:01.499 BULK after 1 call (60 M1): HCC = 18933 bytes
2026.10.10 13:50:01.499 SEQ after 60 calls (60 M1): HCC = 136284 bytes
2026.10.10 13:50:01.508 HCCBulk_60_261010_134901_5109: 60 M1, all fields match input
2026.10.10 13:50:01.508 TestHCCSeq_261010_134901_5109: 60 M1, all fields match input
2026.10.10 13:50:01.508 POINT: M1=60, BULK=18933 bytes (1 call), SEQ=136284 bytes (60 calls), SEQ/BULK=7.198x
2026.10.10 13:50:31.724 BULK symbol for 90 M1: HCCBulk_90_261010_134901_5109
2026.10.10 13:50:31.724 BULK HCC: C:\Program Files\MetaTrader 5\bases\Custom\history\HCCBulk_90_261010_134901_5109\2025.hcc
2026.10.10 13:50:31.985 BULK after 1 call (90 M1): HCC = 20733 bytes
2026.10.10 13:50:31.986 SEQ after 90 calls (90 M1): HCC = 277854 bytes
2026.10.10 13:50:31.996 HCCBulk_90_261010_134901_5109: 90 M1, all fields match input
2026.10.10 13:50:31.996 TestHCCSeq_261010_134901_5109: 90 M1, all fields match input
2026.10.10 13:50:31.996 POINT: M1=90, BULK=20733 bytes (1 call), SEQ=277854 bytes (90 calls), SEQ/BULK=13.402x
2026.10.10 13:51:02.144 BULK symbol for 120 M1: HCCBulk_120_261010_134901_5109
2026.10.10 13:51:02.144 BULK HCC: C:\Program Files\MetaTrader 5\bases\Custom\history\HCCBulk_120_261010_134901_5109\2025.hcc
2026.10.10 13:51:02.404 BULK after 1 call (120 M1): HCC = 22533 bytes
2026.10.10 13:51:02.404 SEQ after 120 calls (120 M1): HCC = 473424 bytes
2026.10.10 13:51:02.415 HCCBulk_120_261010_134901_5109: 120 M1, all fields match input
2026.10.10 13:51:02.415 TestHCCSeq_261010_134901_5109: 120 M1, all fields match input
2026.10.10 13:51:02.415 POINT: M1=120, BULK=22533 bytes (1 call), SEQ=473424 bytes (120 calls), SEQ/BULK=21.010x
2026.10.10 13:51:32.581 BULK symbol for 150 M1: HCCBulk_150_261010_134901_5109
2026.10.10 13:51:32.582 BULK HCC: C:\Program Files\MetaTrader 5\bases\Custom\history\HCCBulk_150_261010_134901_5109\2025.hcc
2026.10.10 13:51:32.842 BULK after 1 call (150 M1): HCC = 24333 bytes
2026.10.10 13:51:32.842 SEQ after 150 calls (150 M1): HCC = 722994 bytes
2026.10.10 13:51:32.852 HCCBulk_150_261010_134901_5109: 150 M1, all fields match input
2026.10.10 13:51:32.852 TestHCCSeq_261010_134901_5109: 150 M1, all fields match input
2026.10.10 13:51:32.852 POINT: M1=150, BULK=24333 bytes (1 call), SEQ=722994 bytes (150 calls), SEQ/BULK=29.712x
2026.10.10 13:52:03.026 BULK symbol for 180 M1: HCCBulk_180_261010_134901_5109
2026.10.10 13:52:03.026 BULK HCC: C:\Program Files\MetaTrader 5\bases\Custom\history\HCCBulk_180_261010_134901_5109\2025.hcc
2026.10.10 13:52:03.283 BULK after 1 call (180 M1): HCC = 26133 bytes
2026.10.10 13:52:03.283 SEQ after 180 calls (180 M1): HCC = 1026564 bytes
2026.10.10 13:52:03.298 HCCBulk_180_261010_134901_5109: 180 M1, all fields match input
2026.10.10 13:52:03.298 TestHCCSeq_261010_134901_5109: 180 M1, all fields match input
2026.10.10 13:52:03.298 POINT: M1=180, BULK=26133 bytes (1 call), SEQ=1026564 bytes (180 calls), SEQ/BULK=39.282x
2026.10.10 13:52:03.298 RESULT: BULK=26133 bytes (1 call, 180 M1), SEQ=1026564 bytes (180 one-bar calls), SEQ/BULK=39.282x, M1=EQUAL
2026.10.10 13:52:03.298 Тестовые символы сохранены для проверки; исходные котировки не изменялись.


Почему пришлось использовать CustomRatesReplace:

Изначально применялся CustomRatesUpdate(), однако при его совместной работе с CustomTicksAdd() обнаружилась потеря части M1-истории текущего дня.

Отдельный тест подтвердил проблему: CustomRatesUpdate() приводил к потере баров, а CustomRatesReplace() сохранял историю полностью, см. тему: https://www.mql5.com/ru/forum/517927

Поэтому пришлось перейти на CustomRatesReplace(), но возникла другая проблема — чрезмерное разрастание файлов .hcc при последовательной записи M1.

CustomRatesUpdate + CustomTicksAdd: пропадает M1-история пользовательского символа
CustomRatesUpdate + CustomTicksAdd: пропадает M1-история пользовательского символа
  • 2026.10.08
  • www.mql5.com
Здравствуйте. Выявлен баг на пользовательских символах...
Если кастом обновлять каждый тик через CustomRatesUpdate, будет такой же рост размера файла. Это старая проблема. Для себя нашел решение через регулярное удаление и перезаливку всей истории кастома одним куском в генераторе. Занимает миллисекунды, файл возвращается к нормальным размерам.
Подтверждено и передано в MetaQuotes.
Владимир #:
Если кастом обновлять каждый тик через CustomRatesUpdate, будет такой же рост размера файла. Это старая проблема. Для себя нашел решение через регулярное удаление и перезаливку всей истории кастома одним куском в генераторе. Занимает миллисекунды, файл возвращается к нормальным размерам.
Да, я в результате тестов пришел к решению - с какой-то периодичностью удалить всю историю за последний год и залить одним куском, правда там не миллисекунды, а пару секунд получалось.
А о каком генераторе речь?
Sunriser #:
А о каком генераторе речь?
Я, с помощью Клода, сделал себе сервис-генератор ренко и рендж баров в виде кастомных символов. Минутное дело.