Торговий агент на SAC (Soft Actor-Critic)
SAC — алгоритм off-policy з maximum entropy reinforcement learning. Оптимізує не тільки reward, але й ентропію політики — агент учиться бути ефективним І максимально різноманітним. Для трейдингу це означає: не застрявати в одній стратегії, краще досліджувати режими ринку.
Принцип Maximum Entropy RL
Стандартний RL: max E[R]. SAC: max E[R + α·H(π)].
H(π) = -E[log π(a|s)] — ентропія політики. α — температура (auto-tuning у SAC v2).
Практично: агент віддає перевагу двом однаково прибутковим стратегіям тій, що більш стохастична. У трейдингу: стійкість до переобучення на конкретному режимі ринку.
SAC vs PPO для трейдингу
| Характеристика | SAC | PPO |
|---|---|---|
| Тип | Off-policy | On-policy |
| Replay buffer | Є (1M+) | Немає |
| Sample efficiency | Висока | Середня |
| Стабільність навчання | Висока | Висока |
| Action space | Continuous (краще) | Continuous/Discrete |
| Інфраструктура | Складніше (replay) | Простіше |
SAC бажаний при: обмеженому обсязі історичних даних, неперервних діях (ваги портфеля), необхідності sample-efficient навчання.
Архітектура SAC
Три мережі:
- Policy network π_θ(a|s): Gaussian політика з reparameterization trick
- Two Q-networks Q_φ1, Q_φ2: double Q trick для зменшення overestimation bias
- Target Q-networks (EMA копії): стабілізація навчання
import torch
import torch.nn as nn
from torch.distributions import Normal
class SACPolicy(nn.Module):
def __init__(self, state_dim, action_dim, hidden=256):
super().__init__()
self.net = nn.Sequential(
nn.Linear(state_dim, hidden), nn.ReLU(),
nn.Linear(hidden, hidden), nn.ReLU()
)
self.mean_layer = nn.Linear(hidden, action_dim)
self.log_std_layer = nn.Linear(hidden, action_dim)
self.LOG_STD_MIN, self.LOG_STD_MAX = -20, 2
def forward(self, state):
feat = self.net(state)
mean = self.mean_layer(feat)
log_std = self.log_std_layer(feat).clamp(self.LOG_STD_MIN, self.LOG_STD_MAX)
std = log_std.exp()
dist = Normal(mean, std)
# reparameterization: a = tanh(mean + std * ε)
action = torch.tanh(dist.rsample())
log_prob = dist.log_prob(action).sum(-1, keepdim=True)
# поправка для tanh squashing
log_prob -= torch.log(1 - action.pow(2) + 1e-6).sum(-1, keepdim=True)
return action, log_prob
Автоматична настройка температури α
SAC v2 усуває ручну настройку α. Цільова ентропія = -dim(action_space):
target_entropy = -action_dim # для 5 активів = -5
log_alpha = torch.zeros(1, requires_grad=True)
alpha_optimizer = torch.optim.Adam([log_alpha], lr=3e-4)
# alpha loss (оновлюється кожен крок)
alpha_loss = -(log_alpha * (log_pi + target_entropy).detach()).mean()
alpha_optimizer.zero_grad()
alpha_loss.backward()
alpha_optimizer.step()
alpha = log_alpha.exp().item()
Replay Buffer для фінансових часових рядів
Стандартний uniform replay buffer не враховує часову структуру. Prioritized Experience Replay (PER): вибирає transitions з високою TD-error частіше.
Temporal replay buffer: зберігає не i.i.d. transitions, а послідовності (для LSTM політики):
- Sequence length = 20 (20 днів контексту)
- При вибірці берється випадковий неперервний відрізок
- BPTT через всю послідовність
class SequenceReplayBuffer:
def __init__(self, capacity, seq_len):
self.buffer = deque(maxlen=capacity)
self.seq_len = seq_len
def sample_sequences(self, batch_size):
starts = np.random.randint(0, len(self.buffer) - self.seq_len, batch_size)
return [list(self.buffer)[s:s+self.seq_len] for s in starts]
Реалізація через Stable Baselines3
from stable_baselines3 import SAC
model = SAC(
"MlpPolicy",
env,
learning_rate=3e-4,
buffer_size=1_000_000,
learning_starts=10_000, # прогрів без оновлень
batch_size=256,
tau=0.005, # EMA для target networks
gamma=0.99,
train_freq=1,
gradient_steps=1,
ent_coef='auto', # auto-tuning α
target_entropy='auto',
verbose=1
)
model.learn(total_timesteps=500_000)
learning_starts критичний для трейдингу: перші 10K кроків — випадкове дослідження без оновлення мереж. Заповнює replay buffer різноманітними experiences.
Порівняння продуктивності
При прочих рівних SAC зазвичай перевершує PPO на 10–15% по Sharpe Ratio за рахунок кращого дослідження і sample efficiency. Але потребує більше GPU пам'яті (replay buffer) і складніше в налагодженні.
Терміни: 6–10 тижнів
Базовий SAC на OHLCV даних — 3–5 тижнів. PER + sequence replay, LSTM політика, live підключення до брокера — 8–10 тижнів.







