DeepLOB: глубокое обучение на книгах лимитных ордеров
Книга лимитных ордеров — центральная структура данных современных электронных рынков. Каждая заявка на покупку, каждая заявка на продажу, каждая отмена — все это живет в LOB. Десятилетиями квантитативные исследователи вручную конструировали признаки из этих данных: коэффициенты дисбаланса ордеров, взвешенные средние цены, сигналы позиции в очереди. DeepLOB пошел другим путем — он учит эти признаки напрямую из сырых снимков книги ордеров с помощью гибридной архитектуры CNN-LSTM.
Опубликованная Чжаном, Зореном и Робертсом в Oxford-Man Institute в 2019 году, DeepLOB показала, что единая глубокая сеть, обученная сквозным образом на сырых данных книги, конкурентоспособна или превосходит сильные классические базовые модели в прогнозировании движения средней цены. Однако нужно быть точными в отношении доказательной базы. Эталонный набор данных FI-2010 — тот, который цитирует большинство статей, но сами авторы называют его недостаточным — "слишком коротким, прореженным и взятым с менее ликвидного рынка" — и представляют вторую, гораздо более масштабную оценку на данных Лондонской фондовой биржи (LSE) как свой более сильный результат. Это исследование на LSE охватывает примерно один год для пяти обучающих и пяти тестовых акций, порядка 100M+ образцов, и демонстрирует перенос обучения: модель, обученная на одном наборе акций, по-прежнему делает прогнозы на невиданных ранее акциях. Именно этот результат переноса, а не таблица лидеров FI-2010, является настоящим заголовком статьи. Этот пост разбирает архитектуру, математику, реальные цифры и рабочую реализацию на PyTorch.
Книга лимитных ордеров как структура данных

Книга лимитных ордеров поддерживает два отсортированных списка — заявки на покупку (bids) и заявки на продажу (asks) — каждый организован по ценовым уровням. На каждом уровне книга фиксирует цену и совокупный объем покоящихся ордеров.
Для книги ордеров с уровнями отдельный снимок в момент времени — это вектор из значений:
где и — цена и объем продажи на уровне , а , — соответствующие значения на стороне покупки. Уровень 1 содержит лучшую заявку на покупку и лучшую заявку на продажу (BBO); их разница — это спред между покупкой и продажей.
В эталонном наборе данных FI-2010 , что дает 40 признаков на снимок. FI-2010 построен примерно из 4 миллионов сырых сообщений лимитных ордеров по пяти финским акциям на NASDAQ Nordic (Kesko, Outokumpu, Sampo, Rautaruukki, Wartsila) за десять последовательных торговых дней, 1-14 июня 2010 года. Что важно, DeepLOB не обучается на 4M снимков: эталон прореживает эти сообщения (каждое 10-е событие) в нормализованное представление из 394 337 образцов. Именно эту прореженную, нормализованную форму модель и видит на самом деле — одна из причин, по которой авторы предостерегают от того, чтобы считать FI-2010 окончательным словом.
Средняя цена и ее движения
Средняя цена в момент времени — это среднее лучшей заявки на покупку и продажу:
DeepLOB прогнозирует направление движения средней цены на будущем горизонте в событий. Метка — это сглаженная доходность, но имейте в виду, что в литературе есть два соглашения о сглаживании, и они не взаимозаменяемы:
- Будущее среднее против текущей цены (Tsantekidis et al.): сравнивает среднюю среднюю цену за следующие событий с сырой текущей средней ценой.
- Будущее среднее против предыдущего среднего (Ntakaris et al., каноническая метка FI-2010, та же, что DeepLOB использовала для своих данных LSE): и опорное значение, и целевое сглажены.
Сглаживание опорного значения (а не только будущего) существенно снижает шум метки от колебаний в один тик, поэтому форма с предыдущим/следующим средним предпочтительнее. Какую бы вы ни использовали, непрерывная доходность дискретизируется на три класса — вверх, вниз, без изменений — с помощью фиксированных порогов :
Набор данных FI-2010 предоставляет метки для пяти горизонтов прогнозирования: событий.
Традиционные признаки LOB
До глубокого обучения исследователи полагались на признаки, сконструированные вручную. Понимание их существенно важно, потому что DeepLOB намеренно структурирована так, чтобы напоминать многие из них — ее архитектура мотивирована этими величинами даже там, где она не воспроизводит их в точности.
Дисбаланс книги ордеров (OBI)
Наиболее широко используемый сигнал микроструктуры. На вершине книги:
Больший объем покупки относительно объема продажи указывает на давление вверх. Многоуровневый дисбаланс агрегирует по уровням:
Средняя цена, взвешенная по объему
Стандартная средняя цена взвешивает обе стороны одинаково. Средняя цена, взвешенная по объему (также называемая weighted mid, или VAMP), наклоняется в сторону более тяжелой стороны книги. Записывая дисбаланс вершины книги как , это взвешенное по дисбалансу среднее двух цен:
Обратите внимание на перекрестное взвешивание: цена продажи взвешивается объемом покупки и наоборот. Когда объем покупки доминирует (), взвешенная средняя сдвигается в сторону продажи — отражая ожидание того, что несбалансированная книга разрешится движением в сторону более тяжелой стороны.
Предостережение по поводу наименования. Эта статическая, взвешенная по объему средняя — это не микроцена Стойкова. Микроцена Стойкова (2018) — это оценщик с мартингальной поправкой , полученный из рекурсивной коррекции того, как развиваются спред и дисбаланс — вся его суть в том, что наивная взвешенная средняя смещена и не является мартингалом. Это два различных объекта; мы используем здесь взвешенную среднюю ради ее простоты, а не как замену микроцене.
Дисбаланс глубины
Измеряет форму книги за пределами BBO:
Спред и относительный спред
Эти признаки мощны, но ограничены. Они требуют предметной экспертизы для разработки, не улавливают сложные нелинейные взаимодействия и игнорируют временную динамику между последовательными снимками. DeepLOB устраняет все три ограничения.
Архитектура DeepLOB

Архитектура состоит из трех блоков, каждый со своей отдельной ролью:
- Сверточный блок — извлекает пространственные признаки из снимка книги ордеров
- Inception-модуль — улавливает временные паттерны разных масштабов
- LSTM-блок — моделирует последовательные зависимости во времени
Вход сети — это тензор формы , где — окно ретроспективы (100 временных шагов в статье), а для 10 уровней цены и объема с обеих сторон.
Блок 1: сверточное извлечение признаков
Первые сверточные слои работают вдоль измерения признаков, чтобы выучить взаимодействия между ценой и объемом на каждом уровне.
Слой 1: свертка с размером фильтра и шагом , применяемая к каждой паре цена-объем. Это суммирует каждую пару в один признак — аналогично вычислению "взаимодействия цена-объем" на каждом уровне. Ширина сжимается с 40 до 20.
Слой 2: свертка с шагом , которая работает между сопоставленными парами покупка-продажа на одном уровне. Это улавливает информацию о спреде и дисбалансе на каждом уровне. Ширина сжимается с 20 до 10.
Слой 3: свертка , которая интегрирует по всем 10 уровням, сворачивая измерение глубины до ширины 1. Это производит единый агрегированный признак на временной шаг, который кодирует полный профиль глубины.
За каждым шагом / следуют две свертки вдоль оси времени, каждая с активацией LeakyReLU и пакетной нормализацией. Обратите внимание, что эти свертки с padding=(1, 0) не сохраняют измерение времени: каждая укорачивает его на один шаг (). На протяжении шести таких слоев в блоках 1-3 ось времени сжимается со 100 до 94 перед inception-модулем — что комментарии о формах в коде ниже делают явным.
Дизайн намеренно избегает больших пространственных фильтров. Фильтры уважают естественную парную структуру данных LOB — цена с объемом, покупка с продажей. Это индуктивное смещение критично: фильтр смешивал бы соседние уровни и стороны способом, не имеющим финансового смысла.
Блок 2: Inception-модуль
После того как сверточный блок сокращает 40 признаков до компактного пространственного представления (ширина 1), inception-модуль работает вдоль измерения времени, чтобы одновременно улавливать паттерны на множестве временных масштабов.
Inception-модуль DeepLOB имеет четыре параллельных пути, каждый производит 32 канала, все они конкатенируются:
- узкое место временная свертка: краткосрочные временные паттерны (3 временных шага)
- узкое место временная свертка: среднесрочные временные паттерны (5 временных шагов)
- max-pool свертка: пулинг-путь, сохраняющий сглаженный, прореженный взгляд
- (сокращения действуют как точечные узкие места перед временными свертками)
Каждый временной путь использует симметричный паддинг, так что измерение времени поддерживается внутри inception-блока (в отличие от сверточных блоков выше). Выходы конкатенируются вдоль измерения каналов, давая сети доступ к временным признакам разных масштабов одновременно.
Это вдохновлено inception-архитектурой GoogLeNet, но адаптировано для одномерных временных данных, а не двумерных изображений. Ключевая идея в том, что динамика LOB действует на множестве временных масштабов: потиковый шум, краткосрочный моментум и возврат к среднему на более длинном горизонте сосуществуют.
Реализация на PyTorch ниже представляет упрощенный вариант с тремя путями (две временные свертки плюс путь ), чтобы код оставался читаемым; она опускает max-pool путь. Мы явно указываем на это, потому что это отклонение от статьи, а не оригинальный модуль.
Блок 3: моделирование последовательностей LSTM
Выход inception-модуля подается в LSTM-слой, который обрабатывает всю последовательность длины . LSTM улавливает дальнодействующие временные зависимости, которые свертки сами по себе упустили бы — смены режимов, эффекты времени суток и эволюционирующие рыночные условия.
Финальное скрытое состояние LSTM проходит через полносвязный слой с softmax-активацией, чтобы произвести распределение вероятностей по трем классам (вверх, вниз, без изменений).
Функция потерь
Модель обучается с категориальной перекрестной энтропией:
где — это истинная метка в one-hot кодировании, а — предсказанная вероятность для класса .
Реализация на PyTorch
Оригинальная DeepLOB была построена на Keras с бэкендом TensorFlow; репозиторий авторов (zcakhaa) позже добавил порт на PyTorch. Код ниже — это наша собственная иллюстративная реализация на PyTorch, а не официальная. Она отклоняется от статьи двумя способами, которые мы помечаем по ходу: она опускает max-pool путь inception (три пути вместо четырех) и масштабирует количество каналов вверх. В статье используется 16 фильтров на протяжении сверточных блоков и 32 фильтра на путь inception (вход LSTM ), что дает компактную модель примерно из 60k параметров. Фрагмент ниже использует 32 сверточных / 64 inception фильтра (вход LSTM 192) — внутренне согласованный и запускаемый, но более тяжелый, чем оригинал. Чтобы соответствовать статье, установите количество сверточных каналов в 16, inception-каналов в 32 и input_size=96.
import torch
import torch.nn as nn
class DeepLOB(nn.Module):
"""
DeepLOB-style CNN-Inception-LSTM for limit order books.
Reimplementation inspired by Zhang, Zohren, Roberts (2019),
IEEE Transactions on Signal Processing, arXiv:1808.03668.
NOTE: this is an illustrative reimplementation, NOT the official model.
Differences from the paper:
- inception has 3 paths here vs 4 in the paper (max-pool path omitted);
- channel counts are scaled up (paper: 16 conv / 32 inception, input 96).
Input shape: (batch_size, 1, T, 40)
T = lookback window (e.g. 100)
40 = 10 levels x 4 features (ask_price, ask_vol, bid_price, bid_vol)
"""
def __init__(self, num_classes: int = 3, T: int = 100):
super().__init__()
self.num_classes = num_classes
self.conv1 = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=(1, 2), stride=(1, 2)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)), # time -1
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)), # time -1
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
)
self.conv2 = nn.Sequential(
nn.Conv2d(32, 32, kernel_size=(1, 2), stride=(1, 2)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)), # time -1
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)), # time -1
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
)
self.conv3 = nn.Sequential(
nn.Conv2d(32, 32, kernel_size=(1, 10)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)), # time -1
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
nn.Conv2d(32, 32, kernel_size=(4, 1), padding=(1, 0)), # time -1
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(32),
)
self.inp1 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(64),
)
self.inp2 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(64),
nn.Conv2d(64, 64, kernel_size=(3, 1), padding=(1, 0)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(64),
)
self.inp3 = nn.Sequential(
nn.Conv2d(32, 64, kernel_size=(1, 1), padding=(0, 0)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(64),
nn.Conv2d(64, 64, kernel_size=(5, 1), padding=(2, 0)),
nn.LeakyReLU(negative_slope=0.01),
nn.BatchNorm2d(64),
)
self.lstm = nn.LSTM(
input_size=192, # 64 * 3 paths from the simplified inception
hidden_size=64,
num_layers=1,
batch_first=True,
)
self.fc = nn.Linear(64, num_classes)
def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Args:
x: Tensor of shape (batch, 1, T, 40)
Returns:
Tensor of shape (batch, num_classes)
"""
h = self.conv1(x) # (batch, 32, T-2, 20)
h = self.conv2(h) # (batch, 32, T-4, 10)
h = self.conv3(h) # (batch, 32, T-6, 1) e.g. T=100 -> 94
h_inp1 = self.inp1(h) # (batch, 64, T-6, 1)
h_inp2 = self.inp2(h) # (batch, 64, T-6, 1)
h_inp3 = self.inp3(h) # (batch, 64, T-6, 1)
h = torch.cat([h_inp1, h_inp2, h_inp3], dim=1) # (batch, 192, T-6, 1)
h = h.squeeze(-1) # (batch, 192, T-6)
h = h.permute(0, 2, 1) # (batch, T-6, 192)
h, _ = self.lstm(h)
h = h[:, -1, :] # take last hidden state
out = self.fc(h)
return out
Предобработка данных
Набор данных FI-2010 поставляется нормализованным по z-оценке. Для живых данных книги ордеров вам нужно нормализовать аналогично:
import numpy as np
from torch.utils.data import Dataset
class LOBDataset(Dataset):
"""Dataset for limit order book snapshots."""
def __init__(
self,
data: np.ndarray,
labels: np.ndarray,
T: int = 100,
):
"""
Args:
data: shape (num_snapshots, 40), raw LOB features
labels: shape (num_snapshots,), class labels {0, 1, 2}
T: lookback window length
"""
self.data = data
self.labels = labels
self.T = T
self.mean = data[:len(data) // 2].mean(axis=0)
self.std = data[:len(data) // 2].std(axis=0)
self.std[self.std == 0] = 1.0
self.data = (self.data - self.mean) / self.std
def __len__(self) -> int:
return len(self.data) - self.T
def __getitem__(self, idx: int):
x = self.data[idx : idx + self.T].reshape(1, self.T, 40)
y = self.labels[idx + self.T - 1]
return torch.tensor(x, dtype=torch.float32), torch.tensor(
y, dtype=torch.long
)
Цикл обучения
def train_deeplob(
model: DeepLOB,
train_loader,
val_loader,
epochs: int = 50,
lr: float = 0.01,
device: str = "cuda",
):
model = model.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr, eps=1)
best_val_f1 = 0.0
for epoch in range(epochs):
model.train()
train_loss = 0.0
for x_batch, y_batch in train_loader:
x_batch = x_batch.to(device)
y_batch = y_batch.to(device)
optimizer.zero_grad()
logits = model(x_batch)
loss = criterion(logits, y_batch)
loss.backward()
optimizer.step()
train_loss += loss.item()
model.eval()
all_preds, all_labels = [], []
with torch.no_grad():
for x_val, y_val in val_loader:
x_val = x_val.to(device)
preds = model(x_val).argmax(dim=1).cpu()
all_preds.extend(preds.numpy())
all_labels.extend(y_val.numpy())
from sklearn.metrics import f1_score
val_f1 = f1_score(all_labels, all_preds, average="weighted")
print(
f"Epoch {epoch+1}/{epochs} | "
f"Train Loss: {train_loss/len(train_loader):.4f} | "
f"Val F1: {val_f1:.4f}"
)
if val_f1 > best_val_f1:
best_val_f1 = val_f1
torch.save(model.state_dict(), "deeplob_best.pt")
Ключевые гиперпараметры обучения из оригинальной статьи:
- Оптимизатор: Adam с (необычно большой — помогает стабилизировать обновления на зашумленных финансовых данных)
- Скорость обучения: 0.01
- Размер пакета: 32
- Окно ретроспективы: временных шагов
Мы отслеживаем взвешенный F1, а не точность на валидации, потому что три класса несбалансированы — и, как показывает следующий раздел, F1 — это метрика, на которой оригинальная статья делает акцент именно по этой причине.
Что DeepLOB построена улавливать

Один привлекательный аспект DeepLOB — насколько тесно ее блоки мотивированы признаками, сконструированными вручную, выше. Здесь мы хотим быть осторожными: статья представляет это как интуиции дизайна, а не как доказанные свойства обученной сети. В ней не публикуются визуализации фильтров, корреляции активаций с дисбалансом или анализ того, на что обращает внимание LSTM. Поэтому читайте следующее как архитектурный замысел, а не как измеренные находки.
Первый сверточный блок. Фильтры объединяют цену с объемом на каждом уровне. Структурно это та же операция, что формирует взвешенную по объему цену — статья мотивирует первый слой, отмечая, что его карты признаков формируют величину, подобную микроцене. Сеть построена так, чтобы восстановить что-то из этого семейства; мы не утверждаем, что она доказуемо заново открывает какой-либо конкретный оценщик.
Второй сверточный блок. Работая между парами покупка-продажа, эти фильтры расположены так, чтобы учить признаки, подобные дисбалансу, на множестве уровней — опять же, по построению, а не по продемонстрированной корреляции.
Inception-модуль. Временные свертки разных масштабов призваны улавливать моментум на разных частотах: путь реагирует на точечную структуру, путь — на краткосрочные тренды, путь — на немного более длинные, а (в полном модуле) max-pool путь — на сглаженный взгляд.
LSTM-слой. Рекуррентный компонент добавляет память о дальнодействующих зависимостях, которые свертки не могут представить — смены режимов и эффекты времени суток. Мы избегаем более сильных утверждений (таких как то, что LSTM реализует "адаптивное внимание", которое перевзвешивает недавние данные в волатильных режимах); статья этого не показывает.
Производительность на FI-2010
Оригинальная статья оценивает два протокола. Setup 1 использует более раннее разбиение нормализации набора данных; Setup 2 — это deep-learning постановка, с которой сравнивается большая часть последующих работ. Поскольку FI-2010 несбалансирован по классам, статья делает акцент на F1, а не на точности, и приводит цифры на основе precision/recall для ненейронных базовых моделей (SVM, MLP). Вот реальные цифры Setup 2 (F1, %):
| Горизонт (k) | SVM | MLP | CNN-I | LSTM | DeepLOB |
|---|---|---|---|---|---|
| 10 | 35.88 | 48.27 | 55.21 | 66.33 | 83.40 |
| 20 | — | — | — | — | 72.82 |
| 50 | — | — | — | — | 80.35 |
При DeepLOB также сообщает 84.47% точности наряду с ее F1 83.40. Setup 2 сообщает только — здесь нет строки . (Setup 1 сообщает , с F1 DeepLOB 77.66 / 74.96 / 76.58 соответственно.) Прочерки выше отмечают ячейки базовых моделей, которые статья не табулирует на этих горизонтах в данном протоколе.
Выделяется несколько наблюдений:
- DeepLOB обыгрывает базовые модели с большим отрывом на коротком горизонте. При ее F1 (83.40) намного выше LSTM (66.33), CNN-I (55.21), MLP (48.27) и SVM (35.88). Качественный порядок — глубокие рекуррентно-сверточные модели над простыми CNN, MLP и SVM — это устойчивый вывод.
- Тренд по горизонту немонотонен, не "длиннее значит легче". В Setup 2 F1 DeepLOB идет , когда идет — U-образный паттерн, где самый трудный, а не чистый рост вверх. Является ли горизонт "более легким", сильно зависит от постановки, порога и схемы сглаживания меток; мы не должны вычитывать универсальный закон в этих цифрах.
- DeepLOB не доминирует над каждым классическим методом в каждой ячейке. Против сильных базовых моделей, таких как C(TABL), отрывы сужаются на некоторых горизонтах, так что "превосходит все классические подходы везде" преувеличивает дело. Защитимое утверждение в том, что она конкурентоспособна-до-лучшей и явно лучшая на коротком горизонте.
И снова: собственный взгляд статьи в том, что FI-2010 слишком мал и слишком прорежен, чтобы решить вопрос. Ее более сильное доказательство — это исследование на LSE, где DeepLOB обучается на одном наборе акций и по-прежнему делает прогнозы на отложенных акциях — результат переноса обучения, который FI-2010 показать не может.
LOBFrame и кризис воспроизводимости

Эталонный фреймворк LOBFrame (Briola, Bartolucci, Aste, 2024) дает отрезвляющее дополнение к этим результатам. Хотя архитектура DeepLOB обоснована, фреймворк подчеркивает несколько важных оговорок:
Зависимость от микроструктуры. Производительность модели значительно варьируется по акциям с разными микроструктурными характеристиками. Ликвидные акции с большим тиком легче прогнозировать, чем неликвидные инструменты с малым тиком. Модель, которая выглядит сильной на одной акции, может существенно деградировать на другой.
Прогноз против прибыли. Высокая точность классификации не транслируется автоматически в торговую прибыль. LOBFrame подчеркивает метрики, привязанные к тому, достаточно ли велико прогнозируемое движение, чтобы перекрыть спред между покупкой и продажей. Модель должна быть права достаточно часто и на достаточно крупных движениях, чтобы преодолеть спред — а для акций с узким спредом эта планка высока.
Чувствительность к меткам. Выбор порога и горизонта драматически влияет как на сообщаемую точность, так и на практическую ценность прогнозов. Слишком узкие метки производят зашумленные цели; слишком широкие метки производят тривиально "точные", но бесполезные прогнозы.
За пределами DeepLOB: текущий ландшафт

С момента публикации DeepLOB появилось несколько расширений:
Трансформеры для книг лимитных ордеров (Wallbridge, 2020). Часто вольно называемая "TransLOB" в более поздней литературе, сама модель — это причинно-следственный/дилатированный сверточный экстрактор признаков, за которым следует маскированное многоголовое self-attention — а не просто DeepLOB с заменой LSTM на трансформер; она не переиспользует стек inception+conv. Она сообщила о новом состоянии искусства на FI-2010 для своего времени.
Варианты в крипто-домене. Несколько групп применяют архитектуры в стиле DeepLOB к рынкам криптовалют, где динамика книги ордеров существенно отличается от акций — более широкие спреды, торговля 24/7 и иной состав участников, что все вместе требует переобучения.
Варианты с дополненным вниманием. Линия работ вставляет многоголовое внимание между блоками inception и LSTM, позволяя сети сосредоточиться на уровнях или временных шагах, наиболее информативных для текущего прогноза.
LOB-Bench (Nagy, Frey, Li, Sarkar, Vyetrenko, Zohren, Calinescu, Foerster, 2025). Этот эталон переключает внимание с прогнозирования на генерацию, оценивая, насколько реалистичны генеративные модели данных книги ордеров — релевантно для бэктестинга и обучения агентов, а не для направленного прогнозирования.
Практические соображения для продакшена
Если вы рассматриваете развертывание модели в стиле DeepLOB в живой торговой системе, возникает несколько инженерных вопросов:
Задержка
Модель должна производить прогнозы в рамках бюджета задержки вашей торговой системы. Для HFT-систем, работающих с субмиллисекундными задержками, даже оптимизированный вывод PyTorch может быть слишком медленным. Варианты включают:
- Экспорт в ONNX с оптимизацией TensorRT
- Квантизацию до INT8
- Развертывание на FPGA для наиболее чувствительных к задержке приложений
Конвейер данных
Модель ожидает нормализованные, выровненные снимки книги ордеров на фиксированной частоте. На практике обновления LOB приходят асинхронно. Вам нужны:
- Движок реконструкции снимков, который поддерживает текущее состояние книги
- Сэмплер с фиксированной частотой, который производит входной тензор
- Онлайн-нормализация с использованием скользящей статистики
Стабильность признаков
Параметры нормализации по z-оценке, вычисленные на обучающих данных, дрейфуют со временем. Цены меняются, режимы волатильности сдвигаются, структура рынка эволюционирует. Продакшен-системе нужны:
- Скользящие окна нормализации (например, пересчитывать статистику ежедневно)
- Обнаружение режимов для запуска переобучения модели
- Мониторинг сдвига распределения входа
Переобучение под микроструктуру
Паттерны LOB специфичны для площадки и инструмента. Модель, обученная на акциях NASDAQ, не будет работать на Binance BTC/USDT без переобучения. Даже в рамках одной площадки модели могут переобучаться под:
- Режим размера тика (акции с большим тиком против малого тика)
- Паттерны времени суток (открывающий аукцион, обеденное затишье, закрывающий кросс)
- Поведение маркет-мейкера, которое меняется со временем
Заключение
DeepLOB представляет собой чистое, хорошо мотивированное применение глубокого обучения к микроструктуре рынка. Ее трехблочная архитектура — CNN для пространственных признаков, inception для временных паттернов разных масштабов, LSTM для последовательных зависимостей — естественно отображается на структуру данных книги лимитных ордеров.
Ключевая идея не просто в том, что глубокая модель может сравняться с признаками, сконструированными вручную, или обыграть их, а в том, что индуктивные смещения архитектуры — фильтры , параллелизм inception, рекуррентная память — кодируют подлинное предметное знание о том, как работают книги ордеров. Это не дженерик-сеть, наброшенная на финансовые данные; это архитектура, спроектированная вокруг специфической геометрии книги лимитных ордеров. И ее наиболее убедительное доказательство — это не таблица лидеров FI-2010, которой сами авторы не доверяют, а результат переноса обучения на годе данных LSE.
Для практиков DeepLOB — сильная базовая модель и полезный строительный блок. Для исследователей она демонстрирует, что продуманный дизайн архитектуры — а не просто масштаб модели — движет производительностью на структурированных финансовых данных. Только не забывайте цитировать реальные цифры, следить за схемой меток и относиться к точности классификации как к тому, что очень далеко от торговой прибыли.
Ссылки
-
Zhang, Z., Zohren, S., & Roberts, S. (2019). DeepLOB: Deep Convolutional Neural Networks for Limit Order Books. IEEE Transactions on Signal Processing, 67(11), 3001-3012. arXiv:1808.03668
-
Ntakaris, A., Magris, M., Kanniainen, J., Gabbouj, M., & Iosifidis, A. (2018). Benchmark Dataset for Mid-Price Forecasting of Limit Order Book Data with Machine Learning Methods. Journal of Forecasting, 37(8), 852-866. arXiv:1705.03233
-
Briola, A., Bartolucci, S., & Aste, T. (2024). Deep Limit Order Book Forecasting (LOBFrame). arXiv:2403.09267
-
Wallbridge, J. (2020). Transformers for Limit Order Books. arXiv:2003.00130
-
Cont, R., Kukanov, A., & Stoikov, S. (2014). The Price Impact of Order Book Events. Journal of Financial Econometrics, 12(1), 47-88.
-
Stoikov, S. (2018). The Micro-Price: A High-Frequency Estimator of Future Prices. Quantitative Finance, 18(12), 1959-1966.
-
Nagy, P., Frey, S., Li, K., Sarkar, B., Vyetrenko, S., Zohren, S., Calinescu, A., & Foerster, J. (2025). LOB-Bench: Benchmarking Generative AI for Finance — an Application to Limit Order Book Data. ICML 2025. arXiv:2502.09172
-
DeepLOB code (original in Keras/TensorFlow; the repository also provides a PyTorch port): github.com/zcakhaa/DeepLOB-Deep-Convolutional-Neural-Networks-for-Limit-Order-Books
Авторы
Инженер торговых систем
Разработка торговых ботов с 2017 года: межбиржевой арбитраж (подключал до 30 бирж), парный арбитраж на коинтеграции между спотом и фьючерсами, скальпинг, фронтраннинг, торговля по новостям, сентиментный анализ, трендовые алгоритмы, а также алгоритмы управления и балансировки портфелей. Делает выставление ордеров до 1 мс, warehouse для big data, бэктестинг-движки, AI-агентов и интерфейсы для ботов (в т.ч. open-source profitmaker.cc). Стек: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, архитектура.