Розробка RL-агента для торгівлі на базі DQN/DDQN

Проектуємо та впроваджуємо системи штучного інтелекту: від прототипу до production-ready рішення. Наша команда поєднує експертизу в машинному навчанні, дата-інжинірингу та MLOps, щоб AI працював не в лабораторії, а в реальному бізнесі.
Показано 1 з 1Усі 1566 послуг
Розробка RL-агента для торгівлі на базі DQN/DDQN
Складний
~2-4 тижні
Часті запитання

Напрямки AI-розробки

Етапи розробки AI-рішення

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    901
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1119
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    853

Торговий агент на DQN (Deep Q-Network)

DQN — першим deep RL алгоритм, що продемонстрував superhuman performance (Atari, DeepMind 2015). Для трейдингу: дискретний action space (buy/sell/hold), experience replay, target network. Підходить для single-asset торговлі з чіткими точками входу/виходу.

DQN для трейдингу

Оригінальний DQN працює з дискретними діями. Це робить його природним для сигнальних стратегій:

Action space:

  • 0: Hold (не робити нічого)
  • 1: Buy (відкрити довгу позицію)
  • 2: Sell / Close (закрити позицію / відкрити short)

Для single-asset це розумно. Для multi-asset потрібен DQN із factored action space або перехід на SAC/PPO.

Q-функція: Q(s, a) — очікувана сумарна дисконтована награда зі стану s при дії a.

Архітектура

import torch
import torch.nn as nn

class DQNTrading(nn.Module):
    def __init__(self, state_dim, n_actions=3, hidden=256):
        super().__init__()
        # Dueling DQN архітектура
        self.feature = nn.Sequential(
            nn.Linear(state_dim, hidden), nn.ReLU(),
            nn.Linear(hidden, hidden), nn.ReLU()
        )
        # Value stream: V(s)
        self.value = nn.Sequential(
            nn.Linear(hidden, 128), nn.ReLU(),
            nn.Linear(128, 1)
        )
        # Advantage stream: A(s, a)
        self.advantage = nn.Sequential(
            nn.Linear(hidden, 128), nn.ReLU(),
            nn.Linear(128, n_actions)
        )

    def forward(self, x):
        feat = self.feature(x)
        V = self.value(feat)
        A = self.advantage(feat)
        # Q = V + (A - mean(A))
        return V + (A - A.mean(dim=1, keepdim=True))

Dueling DQN: розділяє V(s) та A(s,a). У трейдингу: стан ринку часто визначає загальну "цінність" (V), а вибір дії — відносне переваги (A). Зазвичай сходиться швидше.

Experience Replay та Target Network

Два ключові інновації DQN:

Experience replay buffer:

from collections import deque
import random

class ReplayBuffer:
    def __init__(self, capacity=100_000):
        self.buffer = deque(maxlen=capacity)

    def push(self, state, action, reward, next_state, done):
        self.buffer.append((state, action, reward, next_state, done))

    def sample(self, batch_size):
        batch = random.sample(self.buffer, batch_size)
        states, actions, rewards, next_states, dones = zip(*batch)
        return (torch.FloatTensor(np.array(states)),
                torch.LongTensor(actions),
                torch.FloatTensor(rewards),
                torch.FloatTensor(np.array(next_states)),
                torch.FloatTensor(dones))

Target network (заморожена копія Q-мережі):

# оновлення кожні C кроків
if step % target_update_freq == 0:
    target_net.load_state_dict(online_net.state_dict())

Без target network: Q-targets рухаються одночасно з Q-predictions → нестабільність → divergence.

Навчання

def train_step(batch, online_net, target_net, optimizer, gamma=0.99):
    states, actions, rewards, next_states, dones = batch

    # поточні Q-значення
    q_values = online_net(states).gather(1, actions.unsqueeze(1))

    # Double DQN: online вибирає дію, target оцінює
    with torch.no_grad():
        next_actions = online_net(next_states).argmax(1)
        next_q = target_net(next_states).gather(1, next_actions.unsqueeze(1))
        target_q = rewards.unsqueeze(1) + gamma * next_q * (1 - dones.unsqueeze(1))

    loss = nn.SmoothL1Loss()(q_values, target_q)  # Huber loss
    optimizer.zero_grad()
    loss.backward()
    nn.utils.clip_grad_norm_(online_net.parameters(), 10)  # gradient clipping
    optimizer.step()
    return loss.item()

Double DQN: усуває overestimation bias оригінального DQN. У шумних фінансових середовищах це критично — без Double DQN Q-значення систематично завищені.

Epsilon-greedy для фінансових середовищ

# Експоненціальний decay epsilon
epsilon = max(epsilon_min, epsilon_start * (epsilon_decay ** step))

if np.random.random() < epsilon:
    action = env.action_space.sample()  # випадкове дослідження
else:
    with torch.no_grad():
        q_vals = online_net(state_tensor)
        action = q_vals.argmax().item()

Фінансова специфіка epsilon:

  • epsilon_start = 1.0 (повне дослідження спочатку)
  • epsilon_min = 0.01 (1% випадкових дій завжди)
  • Повільний decay — ринки складніше Atari

Rainbow DQN

Комбінація всіх вдосконалень: Double + Dueling + PER + Multi-step + Distributional + Noisy Networks.

Для трейдингу найцінніші:

  • Distributional (C51/QR-DQN): передбачає розподіл returns, не тільки mean. Risk-aware політика: агент бачить не тільки очікуваний прибуток, але й волатильність.
  • Multi-step returns (n=3–5): менш sparse reward, краще credit assignment.
  • PER: пріоритизує рідкі ринкові事件 (великі рухи).

Коли DQN, коли SAC/PPO

DQN доцільний для: single-asset, чіткі сигнали buy/sell, невеликий action space (3–10 дій), binary decision making.

SAC/PPO бажаніші для: multi-asset портфеля, continuous position sizing, коли розмір позиції має значення.

Терміни: 4–8 тижнів

Базовий DQN агент — 2–3 тижні. Rainbow з PER, Distributional, multi-step — 6–8 тижнів. Live trading інтеграція з risk management — додаткові 3–4 тижні.