Перейти к содержимому

Глава 296: DQN для управления портфелем

Введение

Глубокие Q-сети (DQN) фундаментально трансформировали обучение с подкреплением с момента их знакового успеха в обучении игре в Atari непосредственно по пиксельным изображениям. Ключевая идея — нейронная сеть может аппроксимировать функцию ценности действий Q(s, a) для выбора оптимальных действий — естественно распространяется на управление портфелем, где агент должен решать, как распределять капитал между несколькими активами на каждом временном шаге.

Традиционные методы оптимизации портфеля, такие как оптимизация средне-дисперсионная (MVO), опираются на оценки распределений доходности, которые, как известно, нестабильны. Стратегии паритета риска и минимальной дисперсии обходят оценку доходности, но игнорируют потенциальные альфа-сигналы. Портфельная торговля на основе DQN предлагает принципиально иной подход: агент обучает оптимальную политику распределения непосредственно по рыночным данным путём проб и ошибок взаимодействия с моделируемой торговой средой, не требуя явных прогнозов доходности.

При управлении портфелем агент DQN наблюдает состояние, включающее недавние движения цен, текущие веса портфеля и потенциально вспомогательные признаки. Он выбирает дискретное действие ребалансировки — например, «увеличить вес BTC на 10% и уменьшить вес ETH на 10%» — и получает вознаграждение на основе доходности портфеля за вычетом транзакционных издержек. За тысячи эпизодов агент обнаруживает стратегии распределения, адаптирующиеся к изменяющимся рыночным режимам.

В этой главе реализована полная система портфельной торговли на основе DQN на языке Rust, включающая три основных улучшения, особенно важных для финансовых приложений: Double DQN для уменьшения смещения переоценки, архитектуру Dueling-сети для разделения ценности состояния от преимуществ действий и приоритизированный воспроизведение опыта (PER) для эффективного обучения на редких, но важных рыночных событиях. Мы получаем реальные мультиактивные данные с Bybit (BTC, ETH, SOL) и обучаем агента, который учится динамически ребалансировать между этими активами.

Математические основы

Пространство состояний

Состояние на временном шаге t кодирует информацию, необходимую агенту для принятия решений о распределении. Вектор состояния определяется как конкатенация:

Ценовые признаки для каждого актива i в юниверсе из N активов:

$$s_t^{price} = \left[ r_{t-k,i}, r_{t-k+1,i}, \ldots, r_{t-1,i} \right]_{i=1}^{N}$$

где $r_{t,i} = \frac{p_{t,i} - p_{t-1,i}}{p_{t-1,i}}$ — логарифмическая доходность актива i в момент t, а k — окно ретроспективного анализа.

Текущие веса портфеля:

$$s_t^{weights} = \left[ w_{t,1}, w_{t,2}, \ldots, w_{t,N} \right]$$

где $w_{t,i} \geq 0$ и $\sum_{i=1}^{N} w_{t,i} = 1$.

Признаки волатильности (скользящее стандартное отклонение доходности):

$$\sigma_{t,i} = \sqrt{ \frac{1}{k-1} \sum_{j=0}^{k-1} (r_{t-j,i} - \bar{r}_{t,i})^2 }$$

Полный вектор состояния:

$$s_t = \left[ s_t^{price}, s_t^{weights}, \sigma_{t,1}, \ldots, \sigma_{t,N} \right] \in \mathbb{R}^{d}$$

где $d = N \cdot k + N + N = N(k + 2)$.

Пространство действий

Для вычислительной управляемости мы дискретизируем непрерывное пространство весов портфеля. Определяем набор дискретных действий ребалансировки. При N активах каждое действие задаёт сдвиг веса для каждого актива с шагом $\delta$:

$$a \in \mathcal{A} = { (\Delta w_1, \Delta w_2, \ldots, \Delta w_N) \mid \Delta w_i \in {-\delta, 0, +\delta}, \sum_i \Delta w_i = 0 }$$

Ограничение $\sum_i \Delta w_i = 0$ обеспечивает сохранение нормализации весов. После применения действия a новые веса:

$$w_{t+1,i} = \text{clip}(w_{t,i} + \Delta w_i, 0, 1)$$

с последующей ренормализацией, чтобы $\sum_i w_{t+1,i} = 1$.

Для 3 активов с шагом $\delta = 0.1$ это даёт управляемое пространство действий из примерно 19 различных действий (включая действие «удержания», где все сдвиги равны нулю).

Функция вознаграждения

Вознаграждение отражает доходность портфеля с учётом транзакционных издержек:

$$r_t = \sum_{i=1}^{N} w_{t,i} \cdot R_{t,i} - c \sum_{i=1}^{N} |w_{t,i} - w_{t-1,i}|$$

где $R_{t,i}$ — доходность актива i в момент t, а c — коэффициент транзакционных издержек.

Уравнение Беллмана и Q-обучение

Оптимальная функция ценности действий удовлетворяет уравнению оптимальности Беллмана:

$$Q^(s, a) = \mathbb{E}\left[ r + \gamma \max_{a’} Q^(s’, a’) \mid s, a \right]$$

где $\gamma \in [0, 1)$ — коэффициент дисконтирования. DQN аппроксимирует $Q^*$ нейронной сетью с параметрами $\theta$:

$$Q(s, a; \theta) \approx Q^*(s, a)$$

Функция потерь для обучения:

$$\mathcal{L}(\theta) = \mathbb{E}{(s,a,r,s’) \sim \mathcal{D}} \left[ \left( r + \gamma \max{a’} Q(s’, a’; \theta^{-}) - Q(s, a; \theta) \right)^2 \right]$$

где $\theta^{-}$ — параметры периодически обновляемой целевой сети, а $\mathcal{D}$ — буфер воспроизведения опыта.

Улучшения DQN для финансов

Double DQN

Стандартный DQN имеет тенденцию переоценивать Q-значения, поскольку одна и та же сеть выбирает и оценивает действия. В финансах переоценка приводит к чрезмерно уверенному распределению в волатильные активы. Double DQN разделяет выбор и оценку:

$$y_t^{DDQN} = r_t + \gamma Q(s_{t+1}, \arg\max_{a’} Q(s_{t+1}, a’; \theta); \theta^{-})$$

Онлайн-сеть $\theta$ выбирает лучшее действие, но целевая сеть $\theta^{-}$ его оценивает. Это даёт более консервативные и стабильные портфельные распределения.

Архитектура Dueling-сети

Архитектура dueling разделяет Q-функцию на функцию ценности состояния $V(s)$ и функцию преимущества $A(s, a)$:

$$Q(s, a; \theta, \alpha, \beta) = V(s; \theta, \beta) + \left( A(s, a; \theta, \alpha) - \frac{1}{|\mathcal{A}|} \sum_{a’} A(s, a’; \theta, \alpha) \right)$$

Для управления портфелем это особенно ценно. Поток ценности обучается определять, какие рыночные состояния в целом благоприятны (трендовые рынки, режимы низкой волатильности), тогда как поток преимущества обучается определять, какие конкретные действия ребалансировки лучше среднего в каждом состоянии. Это разложение ускоряет обучение, поскольку функция ценности может обновляться из каждого опыта, независимо от выбранного действия.

Приоритизированное воспроизведение опыта

Финансовые рынки характеризуются редкими, но критическими событиями — внезапные обвалы, развороты трендов, смены режимов. Стандартная равномерная выборка из буфера воспроизведения недооценивает эти переходы. Приоритизированное воспроизведение опыта (PER) выбирает переходы пропорционально их ошибке временной разности (TD):

$$P(i) = \frac{p_i^{\alpha}}{\sum_k p_k^{\alpha}}$$

где $p_i = |\delta_i| + \epsilon$ — приоритет перехода i, $\delta_i$ — ошибка TD, а $\alpha$ контролирует степень приоритизации. Веса importance sampling корректируют смещение:

$$w_i = \left( \frac{1}{N \cdot P(i)} \right)^{\beta}$$

где $\beta$ постепенно увеличивается от начального значения к 1 в процессе обучения.

Для торговли PER обеспечивает, что агент повторно посещает и обучается на экстремальных рыночных движениях и других высокоэффективных событиях, непропорционально важных для управления рисками.

Реализация на Rust

Наша реализация на Rust предоставляет несколько преимуществ для производственных торговых систем. Абстракции с нулевой стоимостью Rust обеспечивают производительность, близкую к C, для вычислительно интенсивных прямых и обратных проходов нейронной сети. Система владения предотвращает гонки данных при потенциальном многопоточном обучении. А строгая система типов обнаруживает несоответствия размерностей во время компиляции.

Обзор архитектуры

Реализация состоит из следующих основных компонентов:

  1. MultiAssetState — Кодирует истории цен, текущие веса портфеля и признаки волатильности в плоский вектор состояния, подходящий для входа нейронной сети.

  2. ActionSpace — Перечисляет все допустимые дискретные действия ребалансировки, сохраняющие ограничение нормализации весов.

  3. DuelingNetwork — Сеть прямого распространения с общими слоями признаков, разделяющимися на потоки ценности и преимущества, реализующая архитектуру dueling.

  4. ReplayBuffer — Хранит кортежи опыта $(s, a, r, s’, done)$ с приоритетами на основе TD-ошибки для приоритизированной выборки.

  5. DQNAgent — Координирует обучение с epsilon-жадным исследованием, обновлениями целевой сети Double DQN и периодической синхронизацией целевой сети.

  6. BybitClient — Получает исторические данные OHLCV для нескольких активов через REST API Bybit.

Ключевые проектные решения

  • Нормализация состояния: Доходности и волатильности нормализуются по z-оценке с использованием скользящей статистики для улучшения стабильности обучения.
  • Маскирование действий: Действия, которые привели бы к отрицательным весам, маскируются перед argmax, предотвращая недопустимые портфели.
  • Мягкие обновления целевой сети: Вместо периодического жёсткого копирования используется усреднение Поляка: $\theta^{-} \leftarrow \tau \theta + (1 - \tau) \theta^{-}$ с $\tau = 0.005$.
  • Формирование вознаграждения: Используются доходности с поправкой на риск (типа Шарпа), а не сырые доходности для поощрения осознанного отношения к риску.

Данные Bybit по нескольким активам

Мы используем API Bybit для получения исторических данных свечей по трём основным криптовалютным активам:

  • BTC/USDT — Биткойн, доминирующая криптовалюта с высокой ликвидностью
  • ETH/USDT — Ethereum, второй по величине актив, часто коррелированный, но с отличающейся динамикой
  • SOL/USDT — Solana, актив с более высокой бетой, предлагающий возможности диверсификации

Конечная точка REST API Bybit /v5/market/kline предоставляет данные OHLCV с различными интервалами. Мы получаем часовые свечи для достаточной гранулярности при управляемой длине эпизодов.

Конвейер данных

  1. Получение: Извлечение 1000 часовых свечей для каждого актива параллельно
  2. Выравнивание: Обеспечение совпадения временных меток по всем активам
  3. Вычисление доходностей: Расчёт логарифмических доходностей по ценам закрытия
  4. Скользящая статистика: Вычисление скользящей волатильности и параметров z-нормализации
  5. Построение эпизодов: Разделение выровненных данных на обучающие и оценочные эпизоды

Обучение агента DQN

Цикл обучения следует стандартной процедуре DQN с описанными выше улучшениями:

for episode in 1..num_episodes:
state = env.reset()
for step in 1..max_steps:
action = agent.act(state, epsilon) // epsilon-жадная стратегия
next_state, reward, done = env.step(action)
agent.store(state, action, reward, next_state, done)
if agent.buffer_size() >= min_replay:
agent.train_step(batch_size) // выборка из PER
agent.soft_update_target() // усреднение Поляка
state = next_state
if done: break
epsilon = max(epsilon_min, epsilon * epsilon_decay)

Гиперпараметры

ПараметрЗначениеОбоснование
Скорость обучения0.001Стандарт для DQN с Adam
Коэффициент дисконтирования (gamma)0.99Долгосрочная оптимизация портфеля
Epsilon начальный1.0Полное исследование на старте
Epsilon конечный0.01Поддержание лёгкого исследования
Затухание epsilon0.995Постепенное снижение за ~1000 эпизодов
Размер пакета64Баланс между стабильностью и скоростью
Размер буфера воспроизведения100 000Хранение разнообразных рыночных условий
Обновление целевой сети (tau)0.005Медленно движущаяся цель для стабильности
Скрытые слои[128, 64]Достаточная ёмкость для задачи с 3 активами
Шаг веса (delta)0.110% приращения для ребалансировки

Сравнение с равновесным эталоном

Портфель с равными весами (1/N) служит удивительно сильным эталоном. Исследование DeMiguel et al. (2009) показало, что 1/N превосходит многие методы оптимизации на данных вне выборки благодаря ошибкам оценки в матрицах доходности и ковариации. Наш агент DQN должен продемонстрировать явные преимущества для оправдания своей сложности:

  1. Адаптация к режимам: Агент DQN может уменьшать экспозицию к активам, входящим в нисходящие тренды, тогда как равновесный портфель сохраняет фиксированные распределения при всех рыночных условиях.
  2. Таргетирование волатильности: Включая признаки волатильности в состояние, агент обучается уменьшать распределение в активы, испытывающие всплески волатильности.
  3. Захват импульса: Агент может научиться увеличивать веса активов с положительной недавней доходностью, захватывая межактивный моментум.

Ключевые выводы

  1. DQN естественно распространяется на управление портфелем, рассматривая распределение активов как задачу последовательного принятия решений. Состояние захватывает рыночные признаки и текущие позиции; действия — дискретные корректировки весов; вознаграждения — доходности с поправкой на риск.

  2. Double DQN необходим для финансовых приложений, поскольку смещение переоценки стандартного DQN приводит к чрезмерно концентрированным портфелям. Механизм разделённого выбора-оценки даёт более консервативные и стабильные распределения.

  3. Архитектура dueling ускоряет обучение, разделяя «хорошо ли это рыночное состояние?» (поток ценности) от «какое действие ребалансировки лучше здесь?» (поток преимущества). Это разложение особенно естественно для управления портфелем.

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

  5. Дискретные пространства действий — практический компромисс. Хотя непрерывные пространства действий (через DDPG или SAC) теоретически привлекательны, дискретные действия с шагами весов 5-10% достаточны для управления портфелем.

  6. Транзакционные издержки фундаментально формируют изученные политики. Без штрафов за издержки агент учится агрессивно торговать, создавая стратегии, прибыльные в симуляции, но неработающие на практике.

  7. Равновесный эталон трудно стабильно превзойти. Агенты DQN могут превосходить в трендовых рынках и при сменах режимов, но простота портфеля 1/N делает его конкурентоспособным на риск-скорректированной основе.

  8. Rust обеспечивает производительность производственного уровня для вычислительно интенсивного цикла обучения. Крейт ndarray обеспечивает эффективные матричные операции, а система типов Rust обнаруживает несоответствия размерностей во время компиляции.