Дисклеймер: Информация в этой статье предоставлена исключительно в образовательных и ознакомительных целях и не является финансовым, инвестиционным или торговым советом. Торговля криптовалютами сопряжена с высоким риском убытков.
Дисклеймер: информация в этой статье предназначена исключительно для образовательных и информационных целей и не является финансовой, инвестиционной или торговой рекомендацией. Торговля криптовалютами сопряжена со значительным риском потерь.
Привет! Сегодня мы начинаем трёхчастное глубокое погружение в QuestDB — open-source базу данных временны́х рядов, которая всё увереннее становится фундаментом современной торговой инфраструктуры. Это не очередной рейтинг «топ-10 баз данных». Мы пойдём вглубь, потому что именно этого требует алгоритмическая торговля.
Если вы когда-либо упирались в ограничения кардинальности InfluxDB, боролись с накладными расходами TimescaleDB на тиковых данных или задавались вопросом, почему ваш PostgreSQL не справляется с миллионом вставок в секунду — эта серия для вас.
Почему базы данных временны́х рядов важны для трейдинга
Любая алгоритмическая торговая система — от простого грид-бота до полноценного HFT-движка — имеет одну фундаментальную зависимость: данные. Конкретно — упорядоченные по времени данные, поступающие с огромной скоростью и требующие возможности запроса в реальном времени.
Традиционные реляционные базы данных для этого не проектировались. Они превосходны в ACID-транзакциях и сложных JOIN'ах по нормализованным схемам, но захлёбываются на append-ориентированных, секционированных по времени нагрузках, которые определяют финансовые рынки. Вы оказываетесь в борьбе с базой данных вместо того, чтобы заставить её работать на себя.
Базы данных временны́х рядов переворачивают эту парадигму. Они исходят из того, что ваши данные имеют временну́ю метку, поступают примерно в хронологическом порядке и ваши запросы почти всегда затрагивают временны́е диапазоны. QuestDB идёт дальше, будучи спроектированной именно с учётом потребностей рынков капитала — инженерная команда пришла из банков первого эшелона (BoA, UBS, HSBC), и это заметно в каждом архитектурном решении.
QuestDB в двух словах
QuestDB — это open-source (Apache 2.0) база данных временны́х рядов, написанная на zero-GC Java, C++ и Rust. «Zero-GC» — ключевой момент: ядро движка полностью обходит сборщик мусора Java, управляя памятью вручную, чтобы исключить непредсказуемые всплески задержек, характерные для большинства JVM-систем.
Ключевые характеристики производительности:
Пропускная способность записи — миллионы строк в секунду на одном сервере
Задержка запросов менее миллисекунды за счёт векторизованного исполнения с SIMD-инструкциями
Нативные временны́е метки с точностью до наносекунды — необходимо для тиковых данных
Трёхуровневая архитектура хранения, оптимизированная как для горячих, так и для холодных данных
SQL-интерфейс с мощными расширениями для временны́х рядов
Но одни лишь цифры раскрывают лишь часть картины. По-настоящему интересным QuestDB для торговых систем делает то, как он хранит и запрашивает данные.
Трёхуровневый движок хранения
Именно здесь архитектура QuestDB приобретает элегантность. Данные проходят через три различных уровня, каждый из которых оптимизирован под свой паттерн доступа:
Уровень 1: WAL (Write-Ahead Log)
Входящие данные первым делом попадают в журнал предзаписи. Это ваш ультранизколатентный слой добавления. Каждая запись становится долговременной до начала любой обработки — выживает при сбоях и отключениях питания без потери данных. WAL работает только на последовательную запись, что идеально сочетается с современными SSD и NVMe-накопителями.
Для торговых систем это означает, что ваш конвейер приёма рыночных данных может лить данные в QuestDB, не беспокоясь об усилении записи или конкуренции за блокировки. Получаете ли вы обновления через WebSocket с 50 криптовалютных бирж или обрабатываете поток FIX-сообщений — WAL поглощает всё.
WAL также асинхронно отправляется в объектное хранилище, позволяя новым репликам быстро начать работу и читать ту же историю — критическое свойство для аварийного восстановления в промышленных торговых средах.
Уровень 2: Колоночное хранилище
Асинхронно данные упорядочиваются по времени, дедуплицируются и записываются в нативный колоночный формат QuestDB. Этот формат секционирован по времени (по часам, дням, неделям или месяцам в зависимости от объёма данных) и мгновенно доступен для запросов.
Именно колоночная схема обеспечивает производительность запросов QuestDB. Когда вы запрашиваете среднюю цену BTC-USD за последний час, движок читает только столбец price из соответствующих временны́х секций — а не целые строки. В сочетании с SIMD-векторизованным исполнением на нескольких ядрах это даёт субмиллисекундное время запросов, которое делает реальными дашборды реального времени и живые расчёты стратегий.
Каждая таблица хранится как отдельные файлы по столбцам: типы фиксированного размера занимают один файл на столбец, типы переменного размера (например, VARCHAR) — два. Такая схема специально создана для последовательных сканирований, доминирующих в аналитике временны́х рядов.
Уровень 3: Объектное хранилище (Parquet)
Здесь управление стоимостью встречается с интероперабельностью. Старые секции автоматически конвертируются в формат Apache Parquet и отправляются в объектное хранилище (S3, Azure Blob, GCS). Но — и это ключевая инновация — вы всё равно можете прозрачно запрашивать их через SQL-интерфейс QuestDB. Планировщик запросов охватывает все три уровня бесшовно.
Для алготрейдеров это означает возможность держать годы исторических тиковых данных доступными для бэктестирования без оплаты терабайт SSD-хранилища. Ваш Python-фреймворк для бэктестирования может читать те же Parquet-файлы напрямую через Polars, Pandas или Spark — никакого экспорта из базы данных не нужно. Ваш ML-конвейер обучения может получать доступ к тем же данным через Arrow/ADBC для обработки в памяти. Никакой привязки к вендору.
Это радикально иное предложение по сравнению с проприетарными форматами баз данных, которые запирают ваши данные за единственным интерфейсом запросов.
Проектирование схем для торговых данных
Философия проектирования схем QuestDB строится вокруг нескольких критически важных концепций, идеально совпадающих с торговыми данными:
Обозначенная временна́я метка
Каждая таблица временны́х рядов нуждается в обозначенном столбце временны́х меток. Это не просто метаданные — именно он определяет физический порядок хранения и позволяет обрезать секции. Без него вы теряете большую часть преимуществ QuestDB по производительности:
CREATE TABLE trades (
timestampTIMESTAMP,
symbol SYMBOL,
side SYMBOL,
price DOUBLE,
quantity DOUBLE
) TIMESTAMP(timestamp) PARTITIONBYDAY;
Тип SYMBOL
Тип SYMBOL — это ответ QuestDB на проблему строк с высокой кардинальностью. Торговые пары вроде «BTC-USD» или «ETH-USDT» хранятся как словарные записи с целочисленным индексом. Фильтрация и группировка по столбцам SYMBOL кардинально быстрее, чем по VARCHAR — QuestDB приводит сравнение строк к сравнению целых чисел на этапе компиляции.
Если вы принимаете данные со 100+ бирж с тысячами торговых пар, одна эта оптимизация может стать разницей между запросом, занимающим 5 мс и 500 мс.
Стратегия секционирования
Размер секции должен соответствовать объёму данных. Высокочастотные тиковые данные (миллионы строк в день на символ) следует хранить с PARTITION BY HOUR. Данные с меньшим объёмом (ежедневные цены) прекрасно работают с PARTITION BY MONTH. Цель — держать отдельные секции управляемыми, обеспечивая при этом эффективную обрезку:
В реальных торговых системах дублирование данных неизбежно. Ретрансмиссия по сети, дублирующие соединения с биржей для надёжности, воспроизведение исторических данных при восстановлении — всё это порождает дубликаты. QuestDB обрабатывает это нативно: при включённой дедупликации совпадающие строки заменяются новыми версиями, а вставляются только по-настоящему новые строки.
Влияние на производительность зависит от паттерна данных. Если временны́е метки в большинстве строк уникальны, накладные расходы минимальны. Наиболее требовательный случай — когда многие строки разделяют одну временну́ю метку и требуется дедупликация по дополнительным столбцам — что характерно для снимков стакана заявок, где несколько ценовых уровней обновляются одновременно.
Вопросы промышленного развёртывания
Промышленные клиенты QuestDB включают B3 (крупнейшую фондовую биржу Латинской Америки), One Trading (регулируемую криптобиржу, принимающую до 4 миллионов строк в секунду), Laser Digital (группа Nomura), а также многочисленные банки первого эшелона и хедж-фонды.
Несколько практических замечаний по развёртыванию:
QuestDB поддерживает протокол PostgreSQL wire, поэтому большинство клиентских библиотек для PG работают «из коробки»
Для высокопроизводительной записи рекомендуемый путь — InfluxDB Line Protocol (ILP) по HTTP или TCP
Protocol Version 2 (начиная с QuestDB 9.0+) добавляет бинарное кодирование для массивов и вещественных чисел, существенно снижая нагрузку на полосу пропускания и серверную обработку
Автоматическое создание схем и одновременные изменения схем позволяют обрабатывать несколько потоков данных с модификациями на лету
Enterprise-редакция добавляет RBAC (включая разрешения на уровне столбцов), шифрование TLS, автоматическую репликацию и переключение при сбое, многоуровневое хранение в облачных объектных хранилищах и выделенную поддержку с SLA. Для регулируемых сред это базовые требования.
Что будет в частях 2 и 3
В Части 2 мы глубоко погрузимся в SQL-расширения для временны́х рядов QuestDB — SAMPLE BY, ASOF JOIN, HORIZON JOIN, WINDOW JOIN и LATEST ON — с примерами из реальной торговли. Это не инкрементальные улучшения стандартного SQL; это принципиально другие инструменты, устраняющие целые категории сложных запросов.
В Части 3 мы рассмотрим практические применения в трейдинге: материализованные представления для OHLC в реальном времени, 2D-массивы для аналитики стакана заявок и полную архитектуру алготрейдинговой платформы на основе QuestDB.
Следите за обновлениями.
Цитирование
@software{soloviov2025questdb_algotrading_p1,
author = {Soloviov, Eugen},
title = {QuestDB for Algorithmic Trading: Architecture That Speaks the Language of Markets},
year = {2025},
url = {https://marketmaker.cc/en/blog/post/questdb-algotrading-architecture},
version = {0.1.0},
description = {Deep dive into QuestDB's three-tier storage architecture and schema design for algorithmic trading systems.}
}