Торговый агент на A2C/A3C
A3C (Asynchronous Advantage Actor-Critic) и A2C (его синхронный вариант) — алгоритмы параллельного обучения RL от DeepMind (2016). Множество параллельных агентов исследуют разные части пространства состояний одновременно. Для трейдинга: параллельное обучение на разных активах/периодах, быстрая сходимость.
A3C vs A2C: ключевое различие
A3C: асинхронный. N рабочих потоков параллельно собирают опыт и обновляют глобальную сеть. Нет синхронизации между потоками. CPU-based (нет нужды в GPU-exclusive операциях).
A2C: синхронный. N параллельных сред → дождаться всех → один батч-апдейт. Более детерминированный, проще в отладке, лучше использует GPU.
Для большинства торговых задач A2C предпочтительнее — GPU эффективность и воспроизводимость.
Advantage Function
Ключевая идея: обновлять policy не на сырой reward, а на Advantage A(s,a) = Q(s,a) - V(s). Advantage показывает, насколько действие лучше или хуже среднего ожидания в данном состоянии.
GAE (Generalized Advantage Estimation):
def compute_gae(rewards, values, next_value, dones, gamma=0.99, lam=0.95):
advantages = []
gae = 0
for step in reversed(range(len(rewards))):
delta = rewards[step] + gamma * next_value * (1 - dones[step]) - values[step]
gae = delta + gamma * lam * (1 - dones[step]) * gae
advantages.insert(0, gae)
next_value = values[step]
return advantages
λ=0.95 — баланс между bias (λ=0, чисто TD) и variance (λ=1, чисто MC).
Архитектура для торговли
class A2CTradingNet(nn.Module):
def __init__(self, state_dim, action_dim):
super().__init__()
self.shared = nn.Sequential(
nn.Linear(state_dim, 128), nn.ReLU(),
nn.Linear(128, 128), nn.ReLU()
)
self.actor = nn.Linear(128, action_dim) # logits
self.critic = nn.Linear(128, 1) # V(s)
def forward(self, x):
f = self.shared(x)
logits = self.actor(f)
value = self.critic(f)
return logits, value
def a2c_loss(logits, actions, advantages, values, returns, ent_coef=0.01):
dist = Categorical(logits=logits)
log_probs = dist.log_prob(actions)
actor_loss = -(log_probs * advantages.detach()).mean()
critic_loss = F.mse_loss(values.squeeze(), returns)
entropy_loss = -dist.entropy().mean()
return actor_loss + 0.5 * critic_loss + ent_coef * entropy_loss
Параллельность для трейдинга
A2C/A3C особенно полезны при:
Множество активов: 8 параллельных сред, каждая с другим активом (AAPL, MSFT, TSLA, ...). Агент учится на разнообразных рыночных условиях одновременно. Общая policy обобщается лучше.
Множество временных периодов: Параллельные среды с разными периодами истории. Обучение на bull/bear/sideways рынках одновременно.
Walk-forward parallelism: Каждый worker обрабатывает своё временное окно. Accelerated cross-validation.
from stable_baselines3 import A2C
from stable_baselines3.common.vec_env import SubprocVecEnv
def make_env(ticker, start, end):
return lambda: TradingEnv(ticker, start, end)
# 8 параллельных сред
envs = SubprocVecEnv([make_env(t, '2015', '2022') for t in tickers[:8]])
model = A2C(
"MlpPolicy",
envs,
learning_rate=7e-4,
n_steps=5, # короткие rollouts — быстрые апдейты
gamma=0.99,
gae_lambda=1.0,
ent_coef=0.01,
vf_coef=0.25,
max_grad_norm=0.5,
verbose=1
)
model.learn(total_timesteps=1_000_000)
n_steps=5: A2C классически использует очень короткие rollouts (5–20 шагов). Это ускоряет обновления но увеличивает variance.
Сравнение алгоритмов для трейдинга
| Алгоритм | Sample Eff. | Стабильность | Параллелизм | GPU |
|---|---|---|---|---|
| DQN | Высокая | Средняя | Нет | Да |
| A2C | Средняя | Высокая | Отличный | Да |
| PPO | Средняя | Высокая | Хороший | Да |
| SAC | Высокая | Высокая | Средний | Да |
A2C занимает нишу: проще SAC, параллельнее PPO. Для быстрых экспериментов с множеством конфигураций.
Сроки: 4–8 недель
A2C baseline с параллельными средами — 3 недели. LSTM actor, multi-asset с корреляциями, custom reward shaping — 6–8 недель.







