Глава 277: GNN LOB -- Графовые нейронные сети для торговли по книге заявок
1. Введение
Книга лимитных заявок (LOB) — центральная структура данных современных электронных бирж. Она содержит все активные ордера на покупку (bid) и продажу (ask) на различных ценовых уровнях. Традиционные подходы к моделированию LOB — такие как подача сырых векторов цена-объём в LSTM или CNN — рассматривают ценовые уровни как независимые признаки на плоской сетке. Это игнорирует богатую реляционную структуру, естественно существующую между уровнями: соседние уровни взаимодействуют через поток заявок, каскадные отмены и миграцию ликвидности.
Графовые нейронные сети (GNN) предлагают принципиальный способ моделирования этих реляционных динамик. Представляя каждый ценовой уровень как узел графа и соединяя уровни рёбрами, кодирующими близость, корреляцию или причинное влияние, мы можем использовать механизмы передачи сообщений для обучения представлений, которые захватывают межуровневые зависимости гораздо эффективнее, чем сеточные модели.
Почему графы для LOB?
- Переменная топология: количество активных ценовых уровней меняется от тика к тику. Графы естественно работают с входами переменного размера, тогда как фиксированные векторы требуют дополнения или усечения.
- Локальность и дальнодействие: GCN с k слоями захватывает k-шаговые окрестности. Двухслойная сеть позволяет информации перетекать от уровня bid к уровню ask, моделируя взаимодействия через спред.
- Учёт перестановок: хотя ценовые уровни имеют естественный порядок, граф позволяет дополнительно кодировать непоследовательные связи (например, эффекты круглых чисел).
- Внимание к уровням: GAT обучается определять, какие соседние уровни наиболее информативны для предсказания движения цены, обеспечивая интерпретируемые карты внимания.
План главы
| Раздел | Тема |
|---|---|
| 2 | Математические основы — построение графа, GCN, GAT |
| 3 | Приложения — предсказание средней цены, межуровневые зависимости, моделирование рыночного влияния |
| 4 | Реализация на Rust |
| 5 | Интеграция с данными Bybit |
| 6 | Ключевые выводы |
2. Математические основы
2.1 Построение графа из LOB
Для снимка LOB с B уровнями bid и A уровнями ask строим граф G = (V, E, X), где:
-
Узлы V = {v_1, …, v_{B+A}}. Каждый узел — один ценовой уровень.
-
Признаки узлов X in R^{N x F}. Для каждого уровня i вектор признаков:
x_i = [p_i, q_i, side_i, delta_p_i, delta_q_i, depth_ratio_i]
где p_i — цена, q_i — объём, side_i in {0, 1} обозначает bid/ask, delta_p и delta_q — изменения с последнего снимка, depth_ratio — доля кумулятивной глубины.
-
Рёбра E. Рассматриваем несколько стратегий:
Стратегия 1 — k ближайших ценовых уровней:
Соединяем каждый узел с k ближайшими соседями по цене:
E_knn = {(i, j) : |p_i - p_j| <= delta_k(i)}
Стратегия 2 — Полный двудольный граф (Bid-Ask):
Соединяем каждый bid-узел с каждым ask-узлом:
E_bipartite = {(i, j) : side_i != side_j}
Стратегия 3 — Последовательные + пропускные соединения:
Соединяем каждый узел с непосредственными соседями на той же стороне, плюс пропускные соединения каждые s уровней:
E_seq = {(i, i+1)} union {(i, i+s)}
-
Веса рёбер (опционально): w_{ij} = exp(-alpha |p_i - p_j|) для параметра затухания alpha > 0.
2.2 Слой GCN (Graph Convolutional Network)
Слой GCN из работы Kipf и Welling (2017) выполняет агрегацию по окрестности:
H^{(l+1)} = sigma(D_hat^{-1/2} A_hat D_hat^{-1/2} H^{(l)} W^{(l)})
где:
- A_hat = A + I_N (матрица смежности с петлями)
- D_hat_{ii} = sum_j A_hat_{ij} (матрица степеней)
- W^{(l)} in R^{F_l x F_{l+1}} — обучаемая матрица весов
- sigma — нелинейная активация (ReLU)
Упрощённое обновление для одного узла:
h_i^{(l+1)} = sigma(W^{(l)} * (1/(d_i+1)) * (h_i^{(l)} + sum_{j in N(i)} (1/sqrt((d_i+1)(d_j+1))) * h_j^{(l)}))
2.3 Слой GAT (Graph Attention Network)
GAT (Velickovic et al., 2018) заменяет фиксированную нормализацию обучаемыми коэффициентами внимания:
Шаг 1 — Коэффициенты внимания:
e_{ij} = LeakyReLU(a^T [W h_i || W h_j])
где || обозначает конкатенацию, a in R^{2F’} — обучаемый вектор внимания.
Шаг 2 — Нормализация softmax:
alpha_{ij} = softmax_j(e_{ij}) = exp(e_{ij}) / sum_{k in N(i)} exp(e_{ik})
Шаг 3 — Взвешенная агрегация:
h_i’ = sigma(sum_{j in N(i)} alpha_{ij} W h_j)
Многоголовое внимание с K головами:
h_i’ = ||{k=1}^{K} sigma(sum{j in N(i)} alpha_{ij}^k W^k h_j)
Для данных LOB головы внимания могут специализироваться: одна фокусируется на соседях той же стороны (давление глубины), другая — на уровнях через спред (динамика спреда).
2.4 Считывание на уровне графа (Readout)
После L слоёв передачи сообщений получаем эмбеддинги узлов {h_i^{(L)}}. Для предсказания на уровне графа нужна функция readout:
Среднее пулинг: h_G = (1/|V|) sum_{i in V} h_i^{(L)}
Максимум пулинг: h_G = max_{i in V} h_i^{(L)} (поэлементно)
Пулинг с вниманием: h_G = sum_{i in V} softmax(MLP(h_i^{(L)})) * h_i^{(L)}
Эмбеддинг графа h_G подаётся в голову предсказания (MLP) для классификации или регрессии.
2.5 Предсказание направления средней цены
Целевая переменная — будущее движение средней цены:
y = sign(m_{t+tau} - m_t)
где m_t = (p_best_bid + p_best_ask) / 2.
Полная модель:
y_hat = MLP(ReadOut(GAT_L(…GAT_1(X, A)…)))
Функция потерь (кросс-энтропия для 3 классов: рост/падение/стагнация):
L = -sum_{c in {up, down, stat}} y_c log(y_hat_c)
3. Приложения
3.1 Предсказание состояния LOB
Основное приложение — предсказание следующего состояния LOB или направления средней цены. GNN захватывает:
- Дисбаланс глубины: асимметрия между объёмами bid и ask на нескольких уровнях, агрегированная через передачу сообщений.
- Кластеры ликвидности: группы уровней с аномально высоким объёмом, действующие как поддержка/сопротивление.
- Эффекты позиции в очереди: как форма книги заявок на разных глубинах сигнализирует о будущих движениях цены.
Эмпирические результаты из литературы показывают, что модели на основе GNN превосходят DeepLOB и другие базовые линии CNN/LSTM на 2-5% по F1-метрике.
3.2 Моделирование межуровневых зависимостей
Традиционные модели обрабатывают каждый уровень независимо или через свёртку по последовательным уровням. GNN может моделировать:
- Связь bid-ask: как изменения на лучшем ask влияют на более глубокие уровни bid.
- Каскадные отмены: когда крупный ордер размещается на уровне k, он может вызвать отмены на уровнях k+1, k+2 и т.д.
- Обнаружение скрытой ликвидности: айсберг-ордера создают аномальные паттерны в локальной окрестности графа.
3.3 Моделирование рыночного влияния
Для алгоритмов исполнения критически важно понимать, как сделка на одном ценовом уровне влияет на всю книгу. GNN естественно моделирует это:
- Кодируем текущий LOB как граф.
- Симулируем удаление объёма на целевом уровне (сделка).
- Используем GNN для предсказания нового равновесного состояния LOB.
3.4 Мультиактивные LOB-графы
Фреймворк расширяется на несколько активов через мультиграф:
- Каждый актив имеет свой подграф LOB.
- Межактивные рёбра соединяют коррелированные ценовые уровни.
- GNN захватывает как внутрикнижные, так и межкнижные динамики.
4. Реализация на Rust
Наша реализация в rust/src/lib.rs включает:
| Компонент | Описание |
|---|---|
LOBGraph | Строит граф из уровней bid/ask с настраиваемой смежностью |
GCNLayer | Стандартная передача сообщений GCN с обучаемыми весами |
GATLayer | Агрегация на основе внимания с многоголовой поддержкой |
GraphReadout | Среднее и максимальное пулинги для эмбеддингов графа |
MidPricePredictor | Полный пайплайн: построение графа + GNN + голова предсказания |
BybitClient | Получает данные стакана в реальном времени через API Bybit |
Сборка и запуск
cd 277_gnn_lob/rustcargo buildcargo testcargo run --example trading_example5. Интеграция с Bybit
Реализация подключается к публичному REST API Bybit:
Эндпоинт: GET https://api.bybit.com/v5/market/orderbook
Параметры:
category=spotsymbol=BTCUSDTlimit=50
Структура ответа:
{ "result": { "b": [["цена", "объём"], ...], "a": [["цена", "объём"], ...], "ts": 1234567890, "u": 12345 }}Пайплайн данных
- Получение снимка стакана (50 уровней с каждой стороны).
- Построение графа с рёбрами k ближайших соседей (k=5 по умолчанию).
- Вычисление признаков узлов: цена, объём, сторона, нормализованная позиция.
- Запуск прямого прохода GNN (2 слоя GCN + считывание + MLP).
- Вывод предсказанного направления средней цены и уверенности.
6. Ключевые выводы
-
LOB имеет естественную графовую структуру. Ценовые уровни взаимодействуют через поток заявок, и GNN захватывает эти взаимодействия через передачу сообщений.
-
Компромисс GCN vs. GAT. GCN быстрее и проще; GAT обеспечивает интерпретируемость через внимание. Для данных LOB GAT обычно превосходит GCN.
-
Построение графа имеет значение. Выбор стратегии рёбер существенно влияет на качество. k-NN с k=5 — хороший выбор по умолчанию.
-
Масштабируемость. LOB-графы малы (десятки-сотни узлов), поэтому инференс GNN быстр — укладывается в бюджет задержки для HFT.
-
Мультиактивное расширение. Фреймворк естественно расширяется на мультиактивные графы для извлечения кросс-рыночных сигналов.
-
Rust для продакшена. Наша реализация демонстрирует, что инференс GNN можно выполнять на чистом Rust без зависимостей от Python.
Ссылки
- Kipf, T. N., & Welling, M. (2017). Semi-Supervised Classification with Graph Convolutional Networks. ICLR.
- Velickovic, P., et al. (2018). Graph Attention Networks. ICLR.
- Zhang, Z., Zohren, S., & Roberts, S. (2019). DeepLOB. IEEE Trans. Signal Processing.
- Xu, K., et al. (2021). Graph Neural Networks for Limit Order Book Modeling. NeurIPS Workshop.
- Cont, R. (2011). Statistical Modeling of High-Frequency Financial Data. IEEE Signal Processing Magazine.