Обучение RL-агента (PPO/SAC/DQN) для торговой стратегии

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1Все 1306 услуг
Обучение RL-агента (PPO/SAC/DQN) для торговой стратегии
Сложный
от 2 недель до 3 месяцев
Часто задаваемые вопросы

Направления блокчейн-разработки

Этапы блокчейн-разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1288
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    902
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1122
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    859

Обучение RL-агента (PPO/SAC/DQN) для торговой стратегии

Три наиболее используемых RL алгоритма в алготрейдинге имеют разные сильные стороны. Выбор алгоритма зависит от архитектуры стратегии: дискретный или непрерывный action space, on-policy или off-policy обучение.

DQN (Deep Q-Network)

Подходит для: дискретные действия (buy/hold/sell), простые стратегии, достаточная стабильность.

DQN обучает Q-функцию: Q(state, action) — ожидаемая дисконтированная награда при выборе действия action в состоянии state.

import torch
import torch.nn as nn
from collections import deque
import random

class DQNNetwork(nn.Module):
    def __init__(self, state_dim, n_actions, hidden_dim=256):
        super().__init__()
        # Dueling architecture: отдельные Value и Advantage потоки
        self.shared = nn.Sequential(
            nn.Linear(state_dim, hidden_dim),
            nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU()
        )
        self.value_stream = nn.Linear(hidden_dim, 1)
        self.advantage_stream = nn.Linear(hidden_dim, n_actions)
    
    def forward(self, x):
        shared = self.shared(x)
        value = self.value_stream(shared)
        advantage = self.advantage_stream(shared)
        # Dueling: Q = V + (A - mean(A))
        q_values = value + (advantage - advantage.mean(dim=1, keepdim=True))
        return q_values

class PrioritizedReplayBuffer:
    """Prioritized Experience Replay — чаще семплируем важные transitions"""
    def __init__(self, capacity=50000, alpha=0.6):
        self.buffer = deque(maxlen=capacity)
        self.priorities = deque(maxlen=capacity)
        self.alpha = alpha
    
    def push(self, state, action, reward, next_state, done, td_error=1.0):
        priority = (abs(td_error) + 1e-5) ** self.alpha
        self.buffer.append((state, action, reward, next_state, done))
        self.priorities.append(priority)
    
    def sample(self, batch_size, beta=0.4):
        probs = np.array(self.priorities) / sum(self.priorities)
        indices = np.random.choice(len(self.buffer), batch_size, p=probs)
        
        # Importance sampling weights
        weights = (len(self.buffer) * probs[indices]) ** (-beta)
        weights /= weights.max()
        
        batch = [self.buffer[i] for i in indices]
        return batch, indices, weights

Double DQN: устраняет overestimation Q-значений. Используем online сеть для выбора действия, target сеть для оценки.

# Double DQN target calculation
with torch.no_grad():
    next_actions = online_net(next_states).argmax(dim=1)  # online net выбирает
    next_q = target_net(next_states).gather(1, next_actions.unsqueeze(1))  # target оценивает
    targets = rewards + gamma * next_q * (1 - dones)

PPO (Proximal Policy Optimization)

Подходит для: дискретные и непрерывные действия, on-policy, стабильное обучение.

PPO ограничивает размер обновления политики через clipping:

class PPOActor(nn.Module):
    def __init__(self, state_dim, action_dim, hidden_dim=256):
        super().__init__()
        self.network = nn.Sequential(
            nn.Linear(state_dim, hidden_dim),
            nn.Tanh(),
            nn.Linear(hidden_dim, hidden_dim),
            nn.Tanh()
        )
        self.policy_head = nn.Linear(hidden_dim, action_dim)
        self.value_head = nn.Linear(hidden_dim, 1)
    
    def forward(self, x):
        features = self.network(x)
        logits = self.policy_head(features)
        value = self.value_head(features)
        return logits, value

def ppo_update(model, optimizer, states, actions, old_log_probs, 
               advantages, returns, clip_eps=0.2, n_epochs=4):
    for _ in range(n_epochs):
        logits, values = model(states)
        dist = torch.distributions.Categorical(logits=logits)
        new_log_probs = dist.log_prob(actions)
        entropy = dist.entropy()
        
        # PPO clipped objective
        ratio = (new_log_probs - old_log_probs).exp()
        surr1 = ratio * advantages
        surr2 = torch.clamp(ratio, 1 - clip_eps, 1 + clip_eps) * advantages
        
        actor_loss = -torch.min(surr1, surr2).mean()
        critic_loss = (returns - values.squeeze()).pow(2).mean()
        entropy_loss = -entropy.mean()
        
        total_loss = actor_loss + 0.5 * critic_loss + 0.01 * entropy_loss
        
        optimizer.zero_grad()
        total_loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), 0.5)
        optimizer.step()

SAC (Soft Actor-Critic)

Подходит для: непрерывный action space (позиционирование 0%–100% капитала), off-policy, максимальная sample efficiency.

SAC максимизирует: J(π) = E[Σ γ^t (r_t + α H(π(·|s_t)))]

Дополнительный член с энтропией H побуждает агента к exploration и предотвращает преждевременную сходимость.

class SACActorContinuous(nn.Module):
    def __init__(self, state_dim, action_dim, hidden_dim=256):
        super().__init__()
        self.network = nn.Sequential(
            nn.Linear(state_dim, hidden_dim), nn.ReLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.ReLU()
        )
        self.mean_head = nn.Linear(hidden_dim, action_dim)
        self.log_std_head = nn.Linear(hidden_dim, action_dim)
    
    def forward(self, x):
        features = self.network(x)
        mean = self.mean_head(features)
        log_std = self.log_std_head(features).clamp(-20, 2)
        std = log_std.exp()
        
        dist = torch.distributions.Normal(mean, std)
        action = dist.rsample()  # reparameterization trick
        # Squash to [-1, 1]
        action_tanh = torch.tanh(action)
        log_prob = dist.log_prob(action) - torch.log(1 - action_tanh.pow(2) + 1e-6)
        
        return action_tanh, log_prob.sum(-1, keepdim=True)

Сравнение алгоритмов для крипто-торговли

Алгоритм Action Space Sample Efficiency Стабильность Лучшее применение
DQN Дискретный Средняя Средняя Простые buy/sell стратегии
PPO Оба Низкая (on-policy) Высокая Общее применение, надёжен
SAC Непрерывный Высокая Высокая Position sizing как action

Multi-agent trading

Несколько RL агентов на разных таймфреймах:

  • Macro агент (1D): определяет overall direction
  • Micro агент (1H): timing entry/exit
  • Исполнительный агент (15M): optimal execution

Macro агент передаёт сигнал как часть state микро-агента.

Ключевые сложности

Нестационарность рынка: агент обученный на 2020–2021 может плохо работать в 2022–2023. Continuous learning / periodic retraining обязательны.

Reward hacking: агент может найти способы получать reward, не соответствующий торговой прибыли. Тщательный reward design критичен.

Overfitting к training data: агент может «запомнить» конкретные паттерны training периода. Evaluation на completely held-out тестовых данных.

Разрабатываем RL торгового агента с выбором оптимального алгоритма (DQN/PPO/SAC) под задачу, кастомной trading environment, reward shaping, walk-forward evaluation и MLflow tracking.