Разработка RL-агента для торговли на базе PPO

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1Все 1566 услуг
Разработка RL-агента для торговли на базе PPO
Сложный
~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

Торговый агент на PPO (Proximal Policy Optimization)

PPO — наиболее распространённый алгоритм для торговых RL-агентов. On-policy, стабильный, хорошо работает с continuous action spaces, устойчив к гиперпараметрам. Разработан OpenAI (2017), де-факто стандарт для portfolio management задач.

Почему PPO для трейдинга

PPO ограничивает размер обновлений policy через clip ratio (ε). Это предотвращает деструктивные обновления, которые в финансовых средах ведут к "забыванию" рабочих стратегий после одного плохого батча.

L_CLIP = E[min(r_t(θ) * A_t, clip(r_t(θ), 1-ε, 1+ε) * A_t)]

r_t(θ) = π_new(a|s) / π_old(a|s) — probability ratio. При ε=0.2: обновление не превышает 20% изменения вероятности действия.

Архитектура Policy Network

Actor-Critic:

import torch
import torch.nn as nn

class TradingActorCritic(nn.Module):
    def __init__(self, state_dim, action_dim):
        super().__init__()
        # Shared feature extractor
        self.shared = nn.Sequential(
            nn.Linear(state_dim, 256),
            nn.Tanh(),
            nn.Linear(256, 256),
            nn.Tanh()
        )
        # Actor head: mean + log_std для Gaussian policy
        self.actor_mean = nn.Linear(256, action_dim)
        self.actor_log_std = nn.Parameter(torch.zeros(action_dim))
        # Critic head: state value V(s)
        self.critic = nn.Linear(256, 1)

    def forward(self, state):
        feat = self.shared(state)
        mean = self.actor_mean(feat)
        std = self.actor_log_std.exp()
        value = self.critic(feat)
        return mean, std, value

LSTM расширение: Для учёта temporal dependencies рынка — LSTM вместо MLP в shared слое. Скрытое состояние передаётся между шагами эпизода.

Transformer: Market Transformer: multi-head attention над историей цен (lookback window 60 дней). Attention heads учатся смотреть на разные временные паттерны.

Настройка гиперпараметров для трейдинга

Параметр Типичный RL Трейдинг
clip_range ε 0.2 0.1–0.15 (консервативнее)
learning_rate 3e-4 1e-4 – 3e-4
n_steps 2048 252 (торговых дней)
batch_size 64 32–64
n_epochs 10 4–6
gamma (discount) 0.99 0.95–0.99
gae_lambda 0.95 0.9–0.95
ent_coef 0.0 0.001–0.01

ent_coef важен: небольшая entropy regularization предотвращает схлопывание policy в один детерминированный паттерн (overfitting к конкретному паттерну рынка).

Кастомная торговая среда

import gymnasium as gym
import numpy as np

class PPOTradingEnv(gym.Env):
    def __init__(self, df, initial_capital=100_000):
        self.df = df
        self.capital = initial_capital

        n_features = 20  # OHLCV + indicators
        self.observation_space = gym.spaces.Box(
            low=-np.inf, high=np.inf,
            shape=(n_features,), dtype=np.float32)

        # непрерывные действия: [-1, 1] для каждого актива
        self.action_space = gym.spaces.Box(
            low=-1, high=1,
            shape=(n_assets,), dtype=np.float32)

    def step(self, action):
        # перевод action [-1,1] в целевые веса портфеля
        weights = self._softmax_allocation(action)
        # ребалансировка с учётом transaction costs
        pnl = self._rebalance(weights)
        obs = self._get_obs()
        reward = np.log(1 + pnl / self.portfolio_value)
        done = self.current_step >= len(self.df) - 1
        return obs, reward, done, False, {}

Обучение и валидация

from stable_baselines3 import PPO
from stable_baselines3.common.vec_env import SubprocVecEnv

# параллельные среды для ускорения сбора данных
def make_env(df): return lambda: PPOTradingEnv(df)

vec_env = SubprocVecEnv([make_env(train_df)] * 8)

model = PPO(
    "MlpPolicy",
    vec_env,
    learning_rate=2e-4,
    n_steps=252,
    batch_size=64,
    n_epochs=5,
    clip_range=0.1,
    ent_coef=0.005,
    verbose=1,
    tensorboard_log="./ppo_tb/"
)
model.learn(total_timesteps=2_000_000)

Walk-forward validation: Обучение 2015–2020 → тест 2021 → сдвиг: обучение 2016–2021 → тест 2022. Средняя производительность по всем окнам — реальная метрика.

Сроки: 6–12 недель

Базовый PPO агент на акциях/фьючерсах — 4–6 недель. LSTM/Transformer policy, multi-asset с корреляциями, интеграция с live брокером — 10–12 недель.