
Динамика капитала на отложенных рыночных данных (период: 2025-03-01 — 2025-06-01), с учётом комиссий и проскальзываний.
Итоговое изменение баланса: +144.23%
Введение
Приветствую вас, уважаемые читатели!
Цель данной статьи — предоставить вам полное техническое руководство по созданию торгового агента (проект), обученного с помощью обучения с подкреплением (Reinforcement Learning), на основе архитектуры Dueling Double Deep Q-Network (D3QN) с использованием Prioritized Experience Replay (PER).
Агент разработан для торговли на фьючерсном рынке Binance Futures. Он принимает решения на основе минутных рыночных данных, включая: open
, high
, low
, close
, volume
, volume_weighted_average
, num_trades
.
Основная цель агента — максимизировать итоговый PnL (прибыль/убыток с учётом комиссий и проскальзывания), в данном проекте ключевым этапом оценки стратегии агента выступает реалистичный бэктест, моделирующий поведение в условиях, максимально приближенных к реальной торговле.
Задачи проекта
Построить интеллектуальную систему, способную:
Самостоятельно принимать прибыльные торговые решения в условиях высокой волатильности;
Эффективно выявлять скрытые закономерности из исторических данных;
Демонстрировать высокую обобщающую способность на ранее не встречавшихся данных.
Также в задачи проекта входит создание:
Гибкой архитектуры, пригодной для развития в сторону более продвинутых подходов (Dreamer, Soft Actor-Critic и др.);
Базовой платформы для тестирования новых гипотез, функций вознаграждения, архитектур нейросетей, буферов и метрик.
Что вы найдёте в статье
Я подготовил исчерпывающее описание всей системы. Все части проекта воспроизводимы. Код, данные и конфигурации доступны в открытом доступе, все ссылки представлены в конце данного раздела и в финальной части статьи.
Раздел | Содержание |
---|---|
Данные | Подробное описание логики формирования сигналов, критериев волатильности и структуры обучающих сессий. |
Среда | Механика торговли, детальный расчёт прибыли и убытков (PnL), описание ограничений и особенностей обработки действий агента. |
Агент | Архитектура D3QN, буфер Prioritized Experience Replay (PER) и стратегия ε-жадности, позволяющая агенту исследовать рынок и принимать оптимальные решения. |
Обучение | Логика тренировочного цикла, методы валидации, системы логирования и сохранения обученной модели. |
Тестирование | Финальные метрики, реальные примеры торговых сессий, подробная визуализация поведения агента. |
Бэктест | Реалистичная симуляция торговли: комиссии, проскальзывания, риск-менеджмент, интеллектуальный выбор действий и независимая оценка стратегии. |
Архитектура проекта | Модульная структура, взаимосвязи компонентов и принципы их взаимодействия. |
Выводы | Обзор ограничений текущей системы, перспективы дальнейшего развития и план по переходу к архитектурам следующего поколения (от DQN до Model-Based RL, SAC и др.). |
Об авторе
Меня зовут Юрий. Я «Senior Quantitative Researcher» с более чем десятилетним опытом в области машинного обучения и обучения с подкреплением (RL). Основная специализация — проектирование интерпретируемых, масштабируемых и воспроизводимых систем, применяемых на реальных финансовых рынках.
Мотивация
На большинстве доступных ресурсов тема RL в трейдинге либо чрезмерно упрощена, либо лишена инженерной строгости, либо не адаптирована к реалиям рынка. Основная мотивация — восполнить этот пробел, продемонстрировав, как построить работающую RL-систему:
на реальных рыночных данных;
с полным контролем качества и рисков;
с высокой воспроизводимостью.
Данный проект создан как реальная исследовательская лаборатория, способная:
генерировать и проверять гипотезы;
выявлять слабые места в RL для трейдинга;
сравнивать SOTA-агентов на реальных данных с честным baseline.
Надеюсь, этот проект пробудит в вас исследовательский интерес и станет вашим надёжным фундаментом для изучения возможностей и ограничений использования RL в алгоритмическом трейдинге.
Визуализация и контроль
Для глубокого понимания и эффективного мониторинга работы агента в проект встроены модули визуализации. Вы сможете отслеживать:
Динамику кривой награды и функции потерь, отражающие прогресс обучения агента;
Изменения показателя Win Rate, демонстрирующие долю прибыльных сделок;
Распределение PnL по тестовым сессиям, отражающее общую картину эффективности;
Подробную визуализацию действий агента, как в наиболее успешных, так и в наименее удачных торговых сессиях.
Исследовательский подход
Чтобы адекватно оценить производительность RL агента, я внедрил независимую baseline-модель — CNN классификатор, обученный в рамках классического обучения с учителем.
Данная модель использует те же тестовые данные, одинаковые метрики (mean PnL, win rate) и оформлена в отдельный модуль со своей конфигурацией.
Baseline-модель даёт нам отправную точку для адекватной оценки RL-агента.
Каждый эксперимент — это изолированная единица, определяемая конфигурацией:
Все гиперпараметры, пути и настройки определяются через
configs/*.py
;При запуске автоматически создаётся директория по имени эксперимента;
Внутри — логи, модели и графики: всё хранится по папкам, с учётом продакшен-подхода, применяемого в исследованиях.
Это избавляет от ручного контроля и делает проект масштабируемым и повторяемым.
Бонус
В конце статьи вас ждёт дополнительный бонус — возможность наблюдать за работой обученного ИИ-агента на Binance Futures в реальном времени.
📎 Код, данные:
Исходный код: github.com/YuriyKolesnikov/rl-trading-binance
Датасеты: huggingface.co/datasets/ResearchRL/open-rl-trading-binance-dataset
2. Описание и подготовка данных
Общая логика формирования обучающего датасета
Ключевая идея заключается в том, чтобы обучать агента только на тех участках рыночной истории, где возникла значимая волатильность, потенциально создающая благоприятные условия для краткосрочной торговли.
Вместо непрерывного сэмплирования рынка, как это часто делается в обобщённых RL-реализациях, здесь отбираются локальные торговые сессии, привязанные к рыночным аномалиям.
2.1 Обоснование
Минутные котировки демонстрируют нестационарное, шумовое поведение. В таких условиях эффективное обучение возможно только на ярко выраженных переходах — импульсах, определяющих ключевые моменты перераспределения ликвидности. Именно поэтому обучение проводится не на случайных точках, а на мощных волатильных сигналах, которые:
сопровождаются быстрым движением цены более чем на 5% в течение короткого временного интервала;
возникают на фоне предшествующей рыночной инерции (стабильность до сигнала);
потенциально вызывают сильное продолжение импульса или резкий откат.
2.2 Логика извлечения торговых сессий
Каждая торговая сессия строится вокруг скользящего окна длиной 10 минут, где выполняется условие:
Далее применяются фильтры:
Исключаются сигналы, окружённые шумом. Предшествующие 90 минут анализируются на отсутствие сильных движений:
Где — коэффициент контрастности (в данной реализации равен 5.0).
Если сигнал проходит фильтр, формируется обучающее окно:
Секция | Длина | Назначение |
---|---|---|
Пре-сигнал | 90 мин | Входные признаки для агента |
Пост-сигнал | 60 мин | Торговая сессия |
Общее окно | 150 мин | Единица обучающей выборки |
2.3 Структура датасета
Каждый элемент датасета представляет собой:
np.ndarray
формы(150, 7)
— 150 минут × 7 каналов;Каналы:
open
,high
,volume_weighted_average
,low
,close
,volume
,num_trades
;Уникальный ключ:
(TICKER, datetime)
.
Название | Кол-во примеров | Период | Назначение |
---|---|---|---|
Train | 24 104 | [2020-01-14 — 2024-08-31) | Обучение |
Validation | 1377 | [2024-09-01 — 2024-12-01) | Оценка модели |
Test | 3400 | [2024-12-01 — 2025-03-01) | Финальный тест |
Backtest | 3186 | [2025-03-01 — 2025-06-01) | Реалистичная эмуляция |
2.4 Примеры визуализаций
Для повышения прозрачности процесса реализована генерация графиков сигналов из всех данных.
Вертикальная линия на 90-й минуте указывает момент начала торговой сессии.
Визуализация строится по каналу
close
.Заголовок графика содержит:
Ticker Name
,datetime
(точное время сигнала в UTC)
Графики формируются для всех четырех подвыборок: Train, Validation, Test, Backtest.




2.5 Механика обработки и нормализации данных
Формирование корректного состояния на каждом шаге взаимодействия агента с рынком требует строгой обработки данных, включая:
фильтрацию и сортировку каналов;
преобразование в относительные значения;
нормализацию;
логарифмические преобразования;
защиту от не числовых и нестабильных значений.
Все ключевые функции реализованы в модуле utils.py
и являются частью единого data pipeline:
Функция | Описание |
---|---|
| Загружает датасет из |
| Выбирает подмножество каналов, например |
| Вычисляет среднее и стандартное отклонение по каналам |
| Формирует финальную версию состояния для обучения агента |
Вывод
Агент обучается не на всём рынке, а на отобранных высоковолатильных сессиях;
Структура данных воспроизводима и управляется конфигурацией;
Все этапы подготовки данных изолированы в модуле
utils
, обеспечивая чистую архитектуру и контроль качества входных данных.
3. Постановка задачи
Алгоритмическая торговля требует от агента принятия решений в условиях частичной информации, транзакционных издержек и изменчивой рыночной динамики.
В рамках данного проекта задача формализуется как эпизодическая задача обучения с подкреплением (RL), где агент учится оптимальной политике управления позицией в течение фиксированного временного интервала после появления сигнала высокой волатильности.
3.1 Формализация: RL как торговый процесс
Каждый эпизод начинается в момент возникновения сигнала высокой волатильности (см. раздел 2). Агенту предоставляется:
90 минут рыночной истории — в качестве входных признаков;
60 шагов торговой сессии — окно принятия решений (по одной минуте на шаг).
На каждом шаге выполняется следующий цикл взаимодействия агента со средой:
Агент получает текущее наблюдение
;
На основе состояния
прогнозирует оптимальное дискретное действие
;
Среда возвращает:
новое состояние
,
скалярную награду
,
флаг завершения эпизода;
Переход
сохраняется в буфер опыта;
При достаточном заполнении буфера агент обновляет параметры
-функции.
Формально цикл описывается следующей схемой:
3.2 Возможные действия агента
Код | Действие | Описание |
---|---|---|
0 | Hold / Wait | Ничего не делать |
1 | Open Long | Открыть длинную позицию |
2 | Open Short | Открыть короткую позицию |
3 | Close Position | Закрыть позицию |
Ограничения:
Нельзя открыть новую позицию, если активна текущая;
На последнем шаге сессии позиция закрывается принудительно.
Состояние:
Наблюдение включает:
Нормализованные рыночные данные за последние N минут;
Экстра-фичи: позиция, нереализованный PnL, прошедшее/оставшееся время;
One-hot кодированная история последних действий.
# Пример формирования состояния в среде:
extras = [position, unrealized_pnl, time_elapsed, time_remaining]
state = np.concatenate([normalized.flatten(), extras, action_history_onehot])
Награда:
Формируется по формуле:
reward = (pnl_change / initial_balance) - inaction_penalty
Где:
pnl_change
— реализованный доход при закрытии позиции;inaction_penalty
— штраф за бездействие.
Альтернативная математическая запись:
где ( = 0.001 ) — штраф за бездействие вне позиции.
3.3 Описание среды: step()
Функция step()
в среде TradingEnvironment
содержит всю необходимую логику, включая:
открытие / закрытие позиций,
расчёт прибыли,
комиссии,
проскальзывание.
3.4 Целевая функция: максимизация дисконтированной награды
Цель агента — стратегия: максимизирующая ожидаемую кумулятивную награду:
где:
(
= 60 ) — длительность сессии;
(
= 0.99 ) — коэффициент дисконтирования.
3.5 Уравнение Беллмана в контексте трейдинга
Используется модифицированное уравнение Беллмана для Double DQN:
Реализация в agent.learn()
:
next_actions = self.policy_net(next_states).argmax(dim=1)
next_q_values = self.target_net(next_states).gather(1, next_actions.unsqueeze(1)).squeeze(1)
target_q_values = rewards + gamma * next_q_values * (1 - dones)
loss = F.smooth_l1_loss(current_q_values, target_q_values)
Интерпретация:
Агент открыл Long, рынок вырос → (
> 0 ),
увеличивается;
Агент выбрал Hold при явной возможности войти → (
0 ),
снижается;
Target-сеть стабилизирует обучение через задержку обновлений.
3.6 Псевдокод обучения агента
FOR each episode:
s₀ ← env.reset()
FOR t = 1 to T:
aₜ ← ε-greedy(sₜ)
sₜ₊₁, rₜ ← env.step(aₜ)
buffer.add(sₜ, aₜ, rₜ, sₜ₊₁)
IF len(buffer) > TRAIN_START:
batch ← buffer.sample()
loss ← update_Q(batch)
sₜ ← sₜ₊₁
3.7 Ограничения среды
Элемент | Значение |
---|---|
Комиссия (Taker) | 0.04% от объёма |
Проскальзывание | ±0.05% |
Штраф за бездействие | −0.001 по умолчанию |
Эти параметры приближают поведение среды к реальной торговле на Binance Futures.
Заключение
Таким образом, агент решает задачу активного управления позицией в условиях высокой рыночной неопределённости, ограниченного времени, транзакционных издержек и штрафов за неэффективные действия.
Формализация задачи строго соответствует реалиям алгоритмической торговли, где каждое решение несёт как потенциальный риск, так и потенциальную прибыль.
4. Архитектура проекта
Проект построен как исследовательская платформа, пригодная для запуска массовых автоматизированных экспериментов.
Все модули управляются через конфигурации и поддерживают строгую изоляцию артефактов по экспериментам.
4.1 Поток данных
train.py
:загружает данные через
utils.load_npz_dataset()
;формирует среду:
TradingEnvironment(data[i])
;инициирует агента D3QN и буфер PER.
Внутри цикла:
агент получает
state
, выбираетaction
;env.step(action)
→next_state
,reward
,done
;буфер сохраняет переход; вызывается
agent.learn()
.
model.py
:обрабатывает
state
через CNN;вычисляется:
replay_buffer.py
:обновляет приоритеты на основе TD-ошибок;
обеспечивает семплирование важных переходов через SumTree.
Логгинг:
записываются
reward
,loss
,ε
,win_rate
;периодическая валидация - метрики сравниваются, сохраняется
best.pth
.
Бэктест и оптимизация:
backtest_engine.py
: запускает симуляцию торговли на новых данных;optimize_cfg.py
: автоматический поиск оптимальной стратегии через Optuna;Бэктест интегрирован в пайплайн: использует тот же агент, конфигурации и предобработку;
Поддерживает параллельные сделки, логгинг, стратегии фильтрации действий, риск-менеджмент.
4.2 Структура проекта
📦 rl_trading_binance/
│
├── train.py # Обучение агента
├── test_agent.py # Тестирование агента
├── backtest_engine.py # Симуляция торговли
├── optimize_cfg.py # Поиск оптимальной конфигурации
├── baseline_cnn_classifier.py # Baseline: CNN классификатор
├── config.py # Базовая структура конфигов (pydantic)
├── configs/ # Отдельные конфиги под эксперименты
│ ├── alpha.py
│ ├── alpha_baseline_cnn.py
│ └── ...
│
├── model.py # Dueling CNN + Q-value head
├── agent.py # D3QN Agent (PER + epsilon decay)
├── replay_buffer.py # Prioritized Experience Replay (SumTree)
├── trading_environment.py # RL-среда с расчётом PnL
├── utils.py # Логгинг, нормализация, визуализация, метрики
└── output/
└── experiment_name/ # Результат
├── logs/
├── plots/
├── saved_models/
└── optuna_cfg_optimization_results/
4.3 Конфигурационная система (cfg)
Я внедрил промышленный подход к управлению параметрами: все модули используют централизованный cfg-объект, основанный на pydantic.BaseModel
. Он разбит на логические блоки:
Конфиг-блок | Назначение |
---|---|
| Пути к данным, логам, моделям, артефактам |
| Структура входных последовательностей |
| Каналы (OHLCV и доп.), нормализация |
| Гиперпараметры RL обучения |
| Архитектура нейросети (CNN + Dueling) |
| Параметры логирования и валидации |
| Настройки стратегии выбора действия |
... | Другие: |
Каждый новый эксперимент описывается как отдельный configs/cfg_name.py
, например:
# configs/alpha.py
from config import MasterConfig
cfg = MasterConfig()
ACTION_HISTORY_LEN = 3
cfg.model.cnn_maps = [32, 64, 128]
cfg.model.cnn_kernels = [7, 5, 3]
cfg.model.cnn_strides = [2, 1, 1]
cfg.model.dense_val = [128, 64]
cfg.model.dense_adv = [128, 64]
cfg.model.additional_feats = 4 + ACTION_HISTORY_LEN * 4
cfg.model.dropout_p = 0.1
cfg.trainlog.num_val_ep = 3500
cfg.trainlog.val_freq = 1000
cfg.trainlog.episodes = 55_000
cfg.trainlog.plot_top_n = 10
cfg.per.buffer_size = 230_000
cfg.rl.batch_size = 16
cfg.rl.learning_rate = 1e-4
cfg.rl.train_start = 10_000
cfg.seq.agent_history_len = 30
cfg.seq.agent_session_len = 10
cfg.seq.action_history_len = ACTION_HISTORY_LEN
cfg.backtest_mode = True
cfg.backtest.max_parallel_sessions = 2
cfg.backtest.position_fraction = 0.5
cfg.backtest.selection_strategy = "advantage_based_filter"
При запуске:
python train.py configs/alpha.py
вся структура логирования, моделей и графиков будет сохранена по пути:
output/alpha/
├── logs/
├── plots/
└── saved_models/
Это делает весь проект воспроизводимым, масштабируемым и идеально управляемым.
4.4 CNN baseline модуль
В проекте реализованн один baseline-модуль, который оформлен как независимый .py
-скрипт. Он следуют тем же правилам запуска, что и основной агент:
Модуль | Описание |
---|---|
| Классификация при помощи CNN сети с числом параметров, равным RL-сети |
CNN baseline:
использует
cfg
изconfigs/*.py
;автоматически создаёт
output/name_cfg/
;логирует все метрики (
PnL
,WinRate
,ROC AUC
);обучается и валидируется отдельно (
cnn_classifier
);использует идентичную нормализацию, как и RL-агент (
calculate_normalization_stats
,apply_normalization
);предсказывает классы направления (↑/↓), где таргет: 1, если end_price > start_price; иначе 0.
Это позволяет честно сравнивать baseline-модель и RL-агента по метрикам:
mean PnL
— суммарный средний доход на сессию;win rate
— доля прибыльных сделок.
Вывод
Проект представляет собой целостную, инженерно выверенную систему, где каждая компонента решает строго определённую задачу. Архитектура легко расширяема, воспроизводима и готова к интеграции в продакшен-среду алгоритмической торговли.
5. RL-среда (TradingEnvironment)
Центральный элемент проекта — это симулированная торговая среда, построенная на базе gym.Env
(совместима с Gymnasium).
Она моделирует поведение крипторынка на основе исторических минутных котировок, управляет внутренним состоянием торговли, рассчитывает прибыль/убыток и формирует наблюдение для агента.
5.1 Ключевые элементы среды
Среда работает с одной торговой сессией продолжительностью N шагов. Каждый шаг моделирует одну минуту торговли.
Переменная | Описание |
---|---|
| Текущий баланс агента (в USD) |
| Текущая позиция: 1 — Long, -1 — Short, 0 — нет |
| Цена входа в позицию |
| Совокупный реализованный PnL за эпизод |
| Номер текущего шага в торговой сессии |
| Количество завершённых сделок |
| Количество сделок с положительным PnL |
| Последние k действий (для one-hot-истории) |
5.2 Пространства среды
Action Space (дискретный):
self.action_space = spaces.Discrete(4) # A = {0: Hold, 1: Long, 2: Short, 3: Close}
Observation Space:
self.observation_space = Box(
low=-inf,
high=inf,
shape=(obs_dim,),
dtype=np.float32
)
5.3 Reward Function
Награда формируется из реализованного изменения PnL, нормализованного на начальный баланс, плюс штраф за бездействие вне позиции.
Где:
(
) — прирост реализованной прибыли за текущий шаг
(
) — штраф за бездействие
(
), если агент вне позиции и выбрал
Hold
5.4 Торговая логика step(action)
def step(self, action: int) -> Tuple[np.ndarray, float, bool, bool, dict]:
...
Упрощенная логика действий:
if action == 1 and position == 0:
entry_price = price * (1 + slippage)
position = 1
elif action == 2 and position == 0:
entry_price = price * (1 - slippage)
position = -1
elif action == 3 and position != 0:
if position == 1:
pnl = (sell_price - entry_price) * qty
else:
pnl = (entry_price - buy_price) * qty
realized_pnl += pnl - fee
position = 0
Особенность: Action Masking на последнем шаге
В конце каждой торговой сессии, если позиция остаётся открытой, агенту принудительно навязывается единственное допустимое действие — CLOSE
. Это реализовано через механизм action masking:
if self.step_id == max_steps - 1 and self.position is not None:
forced_action = CLOSE
Чтобы минимизировать влияние принудительного закрытия, в вектор наблюдений были добавлены две временные характеристики: elapsed time
и remaining time
до окончания сессии. Эти признаки позволяют агенту учитывать временной контекст и самостоятельно принимать решение о закрытии позиции до наступления последнего шага.
Такой подход позволяет сместить поведение агента в сторону более осмысленного планирования, при котором сделки закрываются на пике прибыльности, а не в результате внешнего принуждения.
5.5 Формирование состояния (_get_observation())
Каждое состояние — это конкатенация нормализованного окна цен и дополнительных признаков.
Компоненты:
window = self.current_seq[start:end]
normalized = apply_normalization(window, stats, ...)
Extras:
extras = np.array([
float(self.position),
unrealized_pnl,
time_elapsed,
time_remaining
])
Action History:
hist_onehot = np.zeros(ACTION_HISTORY_LEN * NUM_ACTIONS)
for i, a in enumerate(history_actions):
if a is not None:
hist_onehot[i * NUM_ACTIONS + a] = 1
Финальное наблюдение:
state = np.concatenate([
normalized.flatten(),
extras,
hist_onehot
])
5.6 Псевдокод среды
initialize(balance=10_000, position=0, entry_price=0.0)
FOR each episode:
load sequence from data
FOR t in 0 to 59:
state ← get_observation()
action ← agent(state)
IF action == Open AND no position:
enter position
IF action == Close AND have position:
exit position
update balance, position, realized_pnl
reward ← calc_reward(pnl, penalty_if_no_actions)
obs_next ← get_observation()
done ← (t == N)
return (obs_next, reward, done, info)
Вывод
Торговая среда эмулирует реалистичную рыночную механику с высоким уровнем детализации.
TradingEnvironment:
учитывает комиссии, проскальзывание, штрафы
предоставляет агенту частичные наблюдения с памятью действий
защищает от некорректных действий с помощью action masking
возвращает релевантные награды, способствующие обучению прибыльного поведения
6. Архитектура агента (D3QN + PER)
Алгоритм, лежащий в основе агента, - это Dueling Double Deep Q-Network с Prioritized Experience Replay (D3QN + PER). Выбор данной архитектуры обусловлен следующими требованиями:
стабильность обучения и высокая способность обобщения;
способность различать «важные» состояния от неинформативных;
снижение эффекта переоценки Q-функции (overestimation).
6.1 Почему Dueling DQN особенно эффективен в трейдинге?
Классический DQN напрямую оценивает значение каждого действия в состоянии Q(s, a), не разделяя вклад самого состояния и специфики действия. Это делает модель чувствительной к рыночному шуму и усложняет обучение в ситуациях, где различия между действиями несущественны.
В Dueling DQN эта проблема решается через декомпозицию функции ценности на две составляющие:
V(s) - скалярная оценка полезности состояния вне зависимости от действия;
A(s, a) - преимущество действия a относительно среднего уровня действий в этом состоянии.
Формула:
Такой подход особенно полезен в трейдинге, где зачастую важно понять не что делать, а стоит ли делать что-либо вообще.
Пример:
Рассмотрим два сценария:
Пустое состояние ближе к концу сессии: цены стабильны, объёмы снижаются, сигналов нет.
V(s) будет низким: рыночная ситуация не представляет интереса.
A(s, a) ≈ 0 для всех a: ни одно из действий не даёт ощутимого преимущества.
Сильный импульс на рынке: высокая волатильность и явная направленность движения.
V(s) будет высоким: ситуация потенциально прибыльная.
A(s, Long) >> A(s, Short): преимущество действия Long ярко выражено.
Таким образом, Dueling DQN позволяет агенту более чётко дифференцировать рыночные состояния, эффективно игнорировать нейтральные фазы и сфокусироваться на действительно ценных возможностях для входа в позицию.
Double DQN
Решает проблему переоценки Q-значений путём разнесения действий:
одна сеть выбирает действие (policy);
вторая оценивает результат (target).
Формула:
Применяется в методе learn()
.
Prioritized Experience Replay (PER)
Обеспечивает фокусировку обучения на значимых переходах. Вероятность выборки пропорциональна TD-ошибке:
Где ( ) — TD-ошибка, (
) — сглаживающий параметр.
6.2 Класс агента D3QN_PER_Agent
Описан в agent.py
. Реализует:
инициализацию policy и target сетей;
(
)-жадную стратегию;
буфер PER;
логику обучения.
Кэш предсказаний для бэктеста
Чтобы ускорить массовую симуляцию и повторное использование модели, агент поддерживает дисковое кэширование Q-значений:
Каждое состояние ассоциируется с ключом (тикер, время), по которому сохраняются Q-оценки;
При следующем обращении к тому же состоянию, модель не вызывается — результат берётся из
qval_cache.pkl
;Это снижает время бэктеста в десятки раз и делает возможным реальный перебор сотен конфигураций в Optuna;
Кэш автоматически сохраняется и загружается при запуске агента.
# Пример использования кэша:
action = agent.select_action(
state, training=False, use_cache=True, cache_key=("BTCUSDT", datetime.utcnow())
)
6.3 Псевдокод D3QN + PER
FOR each episode:
s₀ ← env.reset()
FOR t = 1 to T:
aₜ ← ε-greedy(sₜ)
sₜ₊₁, rₜ ← env.step(aₜ)
buffer.add(sₜ, aₜ, rₜ, sₜ₊₁)
IF len(buffer) ≥ TRAIN_START:
B ← buffer.sample(BATCH_SIZE)
Compute target_q via Double DQN
Compute loss = SmoothL1(Q - target)
Backprop with PER weights
Clip gradients
Update policy_net
Every N steps: sync target_net
Вывод
Архитектура D3QN + PER объединяет лучшие практики обучения с подкреплением:
Dueling — разделение оценки состояния и действий;
Double — снижение переоценки Q-значений;
PER — фокусировка на значимых обучающих переходах;
Clip Gradients, Target Sync и Epsilon Decay — стабильность и устойчивость обучения.
Результат — надёжная и масштабируемая реализация D3QN, подходящая для сложных рыночных условий.
7. Нейронная сеть (Dueling CNN-Net)
Для аппроксимации Q-функции используется гибридная архитектура, включающая:
Сверточный блок (CNN) — извлекает краткосрочные рыночные паттерны из временных рядов;
Dueling head — разделённые потоки Value и Advantage, объединяемые в итоговые Q-значения.
Такой дизайн обеспечивает устойчивость к шуму, адаптивность к рыночному контексту и интерпретируемость поведения модели.
7.1 Почему CNN?
На первом этапе я использовал сверточную нейросеть (CNN) как стартовую архитектуру по следующим причинам:
CNN хорошо подходит для обработки локальных паттернов в временных рядах;
она проста в реализации, быстро обучается и легко масштабируется;
структура CNN хорошо отражает идею движущегося окна, что интуитивно соответствует анализу рыночных данных.
Выбор CNN продиктован стратегией постепенного наращивания сложности: сначала — интерпретируемый, стабильный baseline, затем — переход к более выразительным архитектурам, таким как:
iTransformer (Inverted Transformers) — специализируется на time-series;
Perceiver IO — эффективно обрабатывает данные переменной длины;
Temporal Fusion Transformer — SOTA в мультивариативных временных рядах.
CNN выступает как инженерный якорь, позволяющий выстроить надёжный и прозрачный фундамент, прежде чем двигаться к более сложным и вычислительно затратным подходам.
7.2 Основные компоненты
Feature Extractor (CNN):
for i in range(len(cnn_maps)):
Conv2D(in_channels → out_channels, kernel=(k, 1), stride=(s, 1))
ReLU
Concatenation:
combined = torch.cat([cnn_flat, extras], dim=1)
Value Head:
value = self.value_stream(combined) # shape: (batch, 1)
Advantage Head:
advantage = self.advantage_stream(combined) # shape: (batch, num_actions)
Q-финализация:
q_value = value + (advantage - advantage.mean(dim=1, keepdim=True))
7.3 Потенциал для расширения
Возможные направления для дальнейшего развития:
Замена CNN на более выразительные архитектуры (см. раздел 7.1): Perceiver IO, TFTransformer, iTransformer;
Увеличение receptive field через dilated convolutions — для захвата более длительных рыночных зависимостей.
Вывод
Несмотря на простоту, классическая CNN демонстрирует высокую эффективность при работе с рыночными временными рядами.
CNN:
обучается быстро;
обладает компактной реализацией (подходит для embedded / edge-сценариев);
легко интерпретируема и отлаживаема;
и главное — достаточна для достижения конкурентоспособных результатов, что подтверждается проведёнными экспериментами.
Такой баланс делает её оптимальной отправной точкой для RL-проектов, ориентированных на реальные рынки и продакшн-развёртывание.
8. Буфер PER (Prioritized Experience Replay)
Буфер воспроизведения опыта с приоритетами (PER) — это ключевая техника ускорения обучения в DQN-семействе. Вместо равновероятной выборки опытов, как в классическом replay buffer, здесь применяется динамическая приоритезация на основе ошибки обучения (TD-ошибки).
Это позволяет чаще повторно обучаться на важных переходах, ускоряя сходимость и повышая стабильность обучения.
8.1 Идея Prioritized Experience Replay
Prioritized Experience Replay (Schaul et al., 2015) предлагает выбирать те переходы, на которых агент ошибается сильнее. Каждому элементу i сопоставляется приоритет pᵢ, определяющий вероятность выборки:
где:
(
) — TD-ошибка с защитой от нуля;
(
) — степень приоритезации ((
) равномерная);
( ε ) — положительная константа, исключающая нулевые приоритеты.
8.2 Реализация через SumTree
Для эффективного семплирования по приоритету используется дерево отрезков — SumTree. Это бинарное дерево, в котором каждый узел хранит сумму приоритетов поддерева.
Свойства SumTree:
Корень:
Листья: приоритеты отдельных элементов
Пример:
[30]
/ \
[12] [18]
/ \ / \
[5] [7] [10] [8]
8.3 Псевдокод буфера
class PrioritizedReplayBuffer:
def add(exp, td_error):
p = (abs(td_error) + eps) ** alpha
sum_tree.add(p)
data[ptr] = exp
ptr = (ptr + 1) % capacity
def sample(batch_size):
segment = sum_tree.total / batch_size
batch = []
for i in range(batch_size):
z = uniform(i * segment, (i+1) * segment)
idx, p = sum_tree.find(z)
prob = p / sum_tree.total
w = (1 / (N * prob)) ** beta
batch.append((data[idx], w, idx))
return batch
def update_priorities(indices, td_errors):
for i, delta in zip(indices, td_errors):
p = (abs(delta) + eps) ** alpha
sum_tree.set(i, p)
8.4 Связь с агентом
Буфер интегрирован в agent.learn()
следующим образом:
batch = buffer.sample(batch_size)
...
td_errors = abs(target_q - current_q)
buffer.update_priorities(indices, td_errors)
Таким образом:
Агент фокусирует внимание на самых проблемных примерах;
Но сохраняет контроль над смещением (через importance sampling weights).
Вывод
PER — ключевой компонент в условиях высокой нестабильности, где:
важные события редки;
сигналы асимметричны;
цена ошибки велика.
SumTree и TD-ошибка позволяют систематически и с приоритетом обучаться на значимых ситуациях, избегая потери времени на бессмысленные шаги.
9. Обучение
Процесс обучения реализован в модуле train.py
и включает:
загрузку и предобработку данных;
инициализацию среды, агента и буфера;
запуск цикла обучения с валидацией;
логирование и сохранение лучших весов;
генерацию графиков и отчётных артефактов.
9.1 Цикл обучения
Центральный цикл реализует классическую схему обучения агента с использованием буфера воспроизведения и механизма ε-жадности:
FOR episode IN range(1, EPISODES + 1):
obs ← env.reset()
total_reward ← 0
losses ← []
WHILE not done:
action ← agent.select_action(obs)
next_obs, reward, done, _, info ← env.step(action)
agent.store_experience(obs, action, reward, next_obs, done)
IF buffer.ready():
loss ← agent.learn()
IF loss:
losses.append(loss)
agent.increment_step()
obs ← next_obs
total_reward += reward
логгирование: reward, avg_loss, epsilon, win_rate
IF валидация включена AND episode % VAL_FREQ == 0:
metrics ← evaluate(agent, val_env)
IF улучшение:
save best.pth
В процессе обучения используется механизм delayed reward, отражающий отложенное влияние решения на итоговую прибыль.
9.2 Логирование и контроль
В проект встроено детальное логирование всех ключевых величин:
используется
logging
(stdout + файл) иtqdm
для визуального контроля;создаются отдельные директории логов и графиков для каждого эксперимента:
output/logs/
,output/plots/
;сохраняются: значения на каждом шаге + сглаженное среднее (moving average).
9.3 Метрики обучения
Reward
Суммарная награда за эпизод. Отражает изменение баланса с учётом позиции, комиссии и проскальзывания.Loss
Ошибка TD-обновления. Служит индикатором стабильности обучения. Рост может сигнализировать о переобучении или расхождении Q-функции.Win Rate
Процент торговых сессий, завершившихся положительным итоговым PnL.
Проект автоматически сохраняет визуализации всех ключевых метрик:
График | Назначение |
---|---|
| Награда по эпизодам |
| Ошибка TD обучения |
| Процент успешных сессий |
| Динамика ε-жадности |
Все графики сохраняются в папке output/plots/
.
Пример: training_rewards.png

Анализ обучающей динамики:
Начало обучения: средние награды находятся около нуля. Это нормально — агент только начинает осваивать среду и действует почти случайно.
Положительная динамика: скользящее среднее демонстрирует плавный рост, а расширение верхнего хвоста распределения наград указывает на постепенное освоение стратегии. Несмотря на сохраняющуюся волатильность отдельных эпизодов агент уверенно начинает извлекать выгоду из структуры среды.
Конец обучения: к финалу обучения скользящее среднее стабилизируется выше нуля, без резких провалов — это признак того, что агент научился избегать грубых ошибок и всё лучше справляется с задачей принятия решений.
Итог:
Агент демонстрирует стабильное обучение, однако тренд указывает на то, что потенциал далеко не исчерпан.
После завершения обучения сохраняется:
лучшая модель
best.pth
(по метрике на валидации);финальная модель, которая фиксирует веса в конце обучения
final.pth
.
Вывод
Обучающий pipeline выстроен по всем стандартам индустриального RL:
регулярная валидация и логирование;
контроль динамики метрик;
автоматическое сохранение моделей;
полная воспроизводимость через конфигурационный запуск.
10. Тестирование и визуализация
Оценка качества обученного агента проводится в модуле test_agent.py
на отложенных, ранее не встречавшихся данных (test_data.npz
).
Цель — проверить способность модели обобщать стратегию на новых рыночных сценариях без утечек данных из train/val.
10.1 Структура скрипта test_agent.py
Последовательность действий:
Загрузка тестового датасета.
Подготовка входных данных.
Инициализация среды с тестовыми сессиями.
Загрузка лучшей обученной модели.
Прогон заданного числа тестовых эпизодов.
Расчёт метрик, отрисовка результатов, сохранение артефактов.
10.2 Примеры сессий
Скрипт отрисовывает лучшие и худшие торговые сессии по заданной метрике (pnl или win_rate).
Отрисовка выполняется через plot_sessions()
.
На каждом графике отображаются:
кривая цен закрытия;
вертикальная линия начала сессии;
действия агента в виде цветных маркеров: ◦ серый — Hold ◦ зелёный — Long ◦ синий — Short ◦ красный — Close
подпись: тикер, время, метрика (PnL или win rate)
Пример: profitable_session_1

Profitable Session 1
Тикер: HIGHUSDT
Агент открыл LONG практически в момент локального минимума и зафиксировал прибыль на резком отскоке вверх.
Результат: +1805.02 USDT
Пример: profitable_session_2

Profitable Session 2
Тикер: COOKIEUSDT
В данной сессии агент закрывает две прибыльные позици, вначале открывает LONG эксплуатируя сильный положительный импульс, далее фиксирует прибыль и открывает короткую позицию которую также закрывает в плюсе.
Результат: +2562.19 USDT
Пример: unprofitable_session_1

Unprofitable Session 1
Тикер: BRETTUSDT
Агент открыл LONG сразу после просадки цены, далее на первых минутах после открытия позиции Тикер показывал ожидаемое поведение, но затем последовал резкий спад.
Результат: −577.59 USDT
Вывод: стратегия удержания агента не учла нарастающий нисходящий импульс. Но в реальной торговле подобные ситуации перекрываются риск-менеджментом (Stop Loss).
Пример: unprofitable_session_2

Тикер: ARCUSDT
Агент стартует с SHORT в момент, когда цена достигает нисходящего пика сигнала, но рынок быстро отскакивает и агент понимая это закрывает позицию. Далее агент вероятно попытался компенсировать убыток, открыв LONG на откате, но движение вверх оказалось слабым, и позиция была закрыта без существенного восстановления.
Результат: −161.46 USDT
Вывод: стратегия входа была ошибочной, но попытка переориентироваться в середине сессии демонстрирует адаптивное поведение агента.
Такой формат визуализации действий позволяет глубоко понять логику агента: когда вошёл, когда вышел, насколько эффективно распознал импульс или флэт.
10.3 Метрики качества
Во время теста вычисляются агрегированные метрики:
Метрика | Описание |
---|---|
Test_mean_reward | Средняя награда за эпизод |
Test_mean_pnl | Средний реализованный PnL за эпизод |
Test_win_rate | Средняя доля прибыльных сделок |
Test_all_pnls | Массив PnL по всем сессиям (для гистограммы) |
Финальные результаты RL-агента на тестовых данных:
▸ Средняя награда (mean_reward):
0.00285
▸ Средний PnL за сессию (mean_pnl):
+28.47 USDT
▸ Доля прибыльных сессий (win_rate):
55.67%
> Важно подчеркнуть:
Эти результаты были получены при условиях, далёких от максимума возможностей архитектуры.
В конфигурации эксперимента намеренно использовались укороченные сессии (10 минут торговли вместо 60) и ограниченный исторический контекст (30 минут вместо 90).
Цель — обеспечить визуальную интерпретируемость и возможность воспроизведения на обычной CPU-машине.
Несмотря на столь сжатый временной горизонт, агент демонстрирует стабильное поведение и положительное математическое ожидание, превышающее уровень комиссий и проскальзывания.
Это указывает на то, что даже в "демо-режиме" RL-агент уже способен обучиться распознаванию рыночных паттернов, адекватной стратегии входа/выхода и управлению позицией.
Форма распределения наград и стабильность поведения на ранее не встречавшихся данных (test_data.npz
) подтверждают обобщающую способность стратегии. На практике это означает, что агент не переобучается под конкретные сценарии, а усваивает общие принципы, применимые к широкому спектру рыночных условий.
Для оценки состоятельности RL-агента в проект был внедрён честный baseline — сверточный классификатор (CNN), обученный в парадигме supervised learning.
Результаты baseline-модели:
▸ Средний PnL:
–27.95 USDT
▸ Win Rate:
47.85%
CNN-модель, несмотря сопоставимое число параметров (~256k), не смогла обучиться прибыльной стратегии, она уступает RL-агенту по всем метрикам, что указывает на слабую способность различать прибыльные и убыточные сессии.
Вероятная причина: supervised-подход обучается на статической разметке, не видя последствий своих решений. В то время как агент в рамках RL оптимизирует стратегию с учётом delayed reward, комиссий, риска и временного контекста. Это фундаментальное преимущество подхода обучения с подкреплением в торговле.
10.4 Распределения
Распределение PnL:
Показывает, как часто агент зарабатывает или теряет в рамках одной сессии.
Идеально:
распределение асимметрично сдвинуто вправо. Это означает, что агент ограничивает убытки и старается максимизировать прибыль.
Распределение Win Rate:
Показывает долю прибыльных сделок на одну сессию.
Чем ближе к 1.0, тем стабильнее стратегия.
10.5 Визуализация
Все графики сохраняются автоматически:
test_pnl_distribution.png
test_win_rate_distribution.png
profitable_session_*.png
unprofitable_session_*.png
Путь: output/plots/
Вывод
Скрипт test_agent.py
позволяет:
объективно оценить обобщающую способность агента;
визуально проверить решения агента на новых данных;
получить графическую и статистическую обратную связь о качестве стратегии.
Этот этап критически важен, так как демонстрирует, насколько поведение агента надёжно и воспроизводимо в новых рыночных условиях.
11. Бэктест: реалистичная оценка торгового агента
Оценка стратегии в условиях, приближенных к реальной торговле, требует тщательно спроектированного бэктеста.
В рамках данного проекта я реализовал модуль backtest_engine.py — независимый компонент системы, предназначенный для симуляции реальных торговых условий и объективной оценки производительности агента на ранее не использовавшихся данных.
Цель бэктеста это проверить способность агента адаптироваться к рыночной неопределённости, проявлять инициативу и соблюдать дисциплину управления капиталом.
11.1 Особенности реализации
Бэктест реализован как полноценный симулятор торговли, с учётом всех ключевых аспектов реального рынка:
Реалистичность исполнения:
Учитываются комиссии (0.04%) и проскальзывания (±0.05%);
Поддерживается риск-менеджмент: стоп-лосс, тейк-профит, трейлинг-стоп.
Логгинг сделок:
Все действия агента, включая направление, объём, результат, изменение цены и влияние на баланс, записываются в лог backtest_session.log с привязкой к времени.
11.2 Интеллектуальные стратегии выбора действий
Агент может использовать одну из двух стратегий принятия решения:
Advantage-based filter, действие принимается только если его advantage превосходит заданный порог уверенности:
Ensemble Q-Filter (MC Dropout), выполняется несколько стохастических проходов по сети:
вычисляются средние Q-значения и дисперсия (неуверенность);
действие принимается, только если одновременно выполнены условия по уверенности и допустимому уровню неопределённости
, такой подход имитирует логику "soft ensemble" и позволяет гибко управлять допустимым уровнем риска.
11.3 Оптимизация через Optuna
Для нахождения оптимальных гиперпараметров стратегии реализован отдельный модуль optimize_cfg.py, построенный на базе Optuna:
Параметры поиска включают:
пороги уверенности (long_thr, short_thr, close_thr);
включение/отключение риск-менеджмента;
значения stop_loss, take_profit, trailing_stop;
ограничение на дисперсию в ensemble_q_filter.
Бэктест вызывается внутри каждой trial-сессии (run_backtest()), используя кэшированные предсказания;
Каждая конфигурация сохраняется, логи ведутся отдельно по триалам;
Лучшее решение сохраняется как best_backtest_cfg.json, а графики (optuna_history.png, pareto.png) визуализируют динамику поиска.
11.4 Метрики бэктеста
Система метрик реализована в MetricsCollector и предоставляет полный срез поведения агента. Все метрики автоматически логируются и могут использоваться в качестве целевых для Optuna.
Метрика | Описание |
---|---|
final_balance_change | Финальное изменение капитала в % |
total_trades | Общее число совершённых сделок |
profit_days | Доля торговых дней с положительным результатом |
accuracy | Доля правильных предсказаний |
sharpe, sortino | Классические risk-adjusted показатели |
max_drawdown | Максимальная просадка по балансу |
avg_trade_amount | Средний размер сделки |
total_commission | Общие потери на комиссиях |
correct_avg_change | Среднее изменение цены при верных сделках |
incorrect_avg_change | Среднее изменение цены при ошибках |
Финальные метрики симуляции на отложенном датасете (backtest_data.npz):
▸ Финальная доходность портфеля: +144.23%
▸ Sharpe коэффициент: 1.85
▸ Sortino коэффициент: 2.05
▸ Accuracy сигналов: 69.6%
▸ Максимальная просадка: –22.49%
▸ Кол-во торговых дней: 56
▸ Прибыльных дней: 44 (78.57%)
▸ Общее число сделок: 112
▸ Средняя сделка: 11,324.29 USDT
▸ Сделок в день: ~2.00
▸ Комиссионные издержки: –9.68%
Помимо аггрегированных метрик, сохраняется кривая баланса backtest_balance_curve.png
(данный график уже был продемонстрирован в начале статьи) и полный лог сделок.

Агент демонстрирует сбалансированный профиль риск-доходности:
достигнута итоговая доходность +144.23%, что соответствует среднему дневному приросту капитала на уровне +1.61%.
Значения коэффициентов Sharpe (1.85) и Sortino (2.05) указывают на то, что стратегия обеспечивает положительное соотношение доходности к риску, без чрезмерной зависимости от редких экстремальных результатов.
Примечательно также поведение на уровне микростатистики:
▸ Доля верных long-сделок: 69.9% (из 93 позиций)
▸ Доля верных short-сделок: 68.4% (из 19 позиций)
▸ Среднее изменение цены при успешных трейдах: +4.38%
▸ Средний убыток при ошибке: –3.67%
Результаты были получены с теми же ограничениями, что и на тренировке: модель с 256k параметров, сессии по 10 минут, контекст — 30 минут. Это всего лишь малая часть от потенциала, заложенного в архитектуру проекта.
Демонстрационный режим: скрытый потенциал, ограничения модели и данных.
Чтобы обеспечить высокую воспроизводимость эксперимента на любой машине (включая ноутбук без GPU), а также упростить визуальный анализ поведения агента, в проекте был активирован облегчённый режим:
▸ Размер модели: ~256,000 параметров
▸ История: 30 минут (вместо 90)
▸ Сессия: 10 минут (вместо 60)
Такая конфигурация была выбрана осознанно, чтобы:
ускорить цикл обучения и тестирования;
дать пользователю возможность запустить весь пайплайн даже на CPU;
показать поведение агента на коротких трейдах — с полной визуализацией всех шагов.
Реалистичная длина сессии в продакшене предполагает:
Контекст: 90 минут
Длительность: 60 минут
Модель > 1 млн параметров
Таким образом, продемонстрированные результаты — это лишь незначительная доля от потенциальных возможностей проекта. Это делает текущую реализацию идеальной отправной точкой для масштабирования и развития:
Увеличить глубину модели
Расширить временной горизонт
Применить более мощные архитектуры: iTransformer, Perceiver IO
11.5 Режим использования
Бэктест и оптимизация запускаются командами:
# Запуск бэктеста для накопления кэша
python backtest_engine.py configs/alpha.py
# Оптимизация стратегии
python optimize_cfg.py configs/alpha.py --trials 100 --jobs 1
После завершения — можно загрузить best_backtest_cfg.json и использовать найденную стратегию в реальной торговле.
11.6 Пример логов бэктеста
Логирование торговли и метрик реализовано в духе классических торговых платформ. Ниже фрагменты реального лога:
Начало сессии и действия агента:
[Starting backtest...]:
[INFO] : Got 1 signals @ Date: 2025-03-04 Time: 05:19 For Tickers -> GPSUSDT
[INFO] : (SHORT) SELL 27445.27879275 GPSUSDT for 0.17786 at 2025-03-04 05:20
[INFO] : (CLOSE) BUY TP 27434.30068123 GPSUSDT for 0.15744 at 2025-03-04 05:21 PnL = +556.42
...
[INFO] : Got 1 signals @ Date: 2025-04-06 Time: 21:43 For Tickers -> AUCTIONUSDT
[INFO] : (LONG) BUY 653.41295438 AUCTIONUSDT for 13.64841 at 2025-04-06 21:43
[INFO] : (CLOSE) SELL TP 653.15158920 AUCTIONUSDT for 13.97151 at 2025-04-06 21:46 PnL = +203.81
Сводка всех сделок:
[Trades Summary]:
...
[INFO] : 2025-03-27 17:31 LONG MUBARAKUSDT 5903: +601.23 (+10.18% | +5.09%) PRICE CHANGE: +10.27%
[INFO] : 2025-04-14 15:26 LONG OMUSDT 11094: +893.56 ( +8.05% | +4.03%) PRICE CHANGE: +8.14%
[INFO] : 2025-04-29 06:14 LONG INITUSDT 12111: -236.20 ( -1.95% | -0.98%) PRICE CHANGE: -1.87%
[INFO] : 2025-05-21 02:31 LONG SXTUSDT 13663: +611.52 ( +4.48% | +2.24%) PRICE CHANGE: +4.56%
...
Финальные метрики:
[Final Metrics]:
[INFO] : total_commission = -9.68%
[INFO] : avg_commission = -9.13
[INFO] : max_loss = -3474.09
[INFO] : max_profit = 5119.57
[INFO] : total_trade_days = 56
[INFO] : profit_days = 44 (78.57%)
[INFO] : final_balance_change = 144.23%
[INFO] : exp_day_change = 1.61%
[INFO] : max_drawdown = -22.49%
[INFO] : sharpe = 1.85
[INFO] : sortino = 2.05
[INFO] : trades_sharpe = 0.18
[INFO] : trades_sortino = 0.19
[INFO] : accuracy = 69.6%
[INFO] : total_trades = 112
[INFO] : total_longs = 93
[INFO] : total_shorts = 19
[INFO] : longs_correct = 65 (69.9%)
[INFO] : shorts_correct = 13 (68.4%)
[INFO] : correct_avg_change = 4.38%
[INFO] : incorrect_avg_change = -3.67%
[INFO] : avg_trade_amount = 11324.29
[INFO] : trades_per_day = 2.00
Вывод:
Модуль бэктеста в проекте реализован с прицелом на максимальную инженерную реалистичность. Он моделирует реальные торговые условия, включает механизмы контроля риска и позволяет проводить масштабную гиперпараметрическую оптимизацию.
Благодаря множеству метрик, система предоставляет глубокую аналитику поведения агента и его устойчивости на новых, ранее не виденных рыночных данных.
12. Выводы
12.1 Итоговый результат
В рамках данного проекта я спроектировал, реализовал и обучил торгового агента на базе обучения с подкреплением (Reinforcement Learning) с использованием Dueling Double DQN и Prioritized Experience Replay для краткосрочной торговли на Binance Futures.
Агент получает нормализованные окна минутных рыночных данных и принимает одно из четырёх действий: HOLD, LONG, SHORT, CLOSE.
Система продемонстрировала:
устойчивое обучение на тысячах рыночных сессий;
положительный средний PnL на тестовых данных;
интерпретируемое поведение с возможностью визуализации;
масштабируемость, конфигурационную гибкость и модульность.
12.2 Поведенческие шаблоны агента
В процессе анализа я выявил, что агент обучается не просто максимизировать краткосрочную прибыль, но и развивает поведенческие паттерны, характерные для рационального трейдера:
Идентификация импульсов - например, вход в SHORT на экстремумах с последующим выходом при признаках отката;
Избежание сделок на флэтовых участках - сниженная активность при малой волатильности;
Дисциплина во времени - грамотное завершение позиций ближе к окончанию сессии, до принудительного закрытия;
12.3 Обоснование эффективности
Для объективной оценки агент был сопоставлен с CNN baseline-моделью:
Сверточный классификатор (CNN) - архитектура сопоставимая по мощности с агентной моделью.
Результат: агент превзошёл baseline-модель по метрикам mean PnL и Win Rate, что подтверждает состоятельность его стратегии в условиях частично наблюдаемой среды и задержанного вознаграждения.
12.5 Заключение
Проект демонстрирует архитектуру, способную решать прикладные задачи в трейдинге с помощью Reinforcement Learning в условиях высокой волатильности и ограниченности данных.
Данная реализация является инфраструктурным фундаментом для дальнейшего исследовательского и инженерного прогресса:
Переход от value-based к policy-based методам: Actor-Critic, A3C, PPO, SAC;
Модельно-ориентированное обучение: внедрение Dreamer и MuZero с внутренним прогнозированием среды;
Расширение пространства действий: от дискретных к непрерывному управлению объёмом и риском (DDPG, TD3);
Интеграция ансамблей агентов и адаптивных reward shaping функций;
Надеюсь этот проект послужит основой для вашего следующего шага, где вы построите продвинутую архитектуру RL агента, способного планировать и обучаться во внутренней модели мира с целью адаптироваться к сложной, стохастической природе финансовых рынков.
Бонус: Наблюдайте за агентом в реальном времени
Чтобы продемонстрировать работоспособность данной системы на практике, запущен онлайн AI-агент с более продвинутой архитектурой, который в реальном времени анализирует рынок Binance Futures и публикует свои действия в Telegram.
Что делает агент:
Мониторит рынок по всем тикерам, каждую минуту.
Фиксирует сигналы: публикует тикер, направление сделки и уровень уверенности.
Входит и выходит из позиции при оптимальном соотношении риск/награда.
Публикует результат сделки: прибыль или убыток.

Вы можете:
Наблюдать за поведением агента в реальных рыночных условиях.
Анализировать его логику для совершенствования навыков торговли.
Использовать его аналитику для принятия решений.
Важное примечание: агент работает в экспериментальном режиме. Все решения, принимаемые пользователями на основе информации из канала, осуществляются под их личную ответственность.
Проект является исследовательским и предоставляется бесплатно исключительно в образовательных целях.
Что дальше: путь к полной автономии
В рамках этого проекта мы с вами реализовали центральный элемент торговой системы - интеллектуального агента на базе RL, способного обучаться, принимать осмысленные решения и адаптироваться к рынку.
Но для перехода от исследовательского проекта к полноценной автономной торговой системе потребуется ещё два важных компонента:
1. Поток рыночных данных (Stream Layer)
Чтобы агент мог действовать в режиме реального времени или обучаться на исторических данных, необходимо обеспечить непрерывный поток актуальных данных с биржи.
Что для этого нужно:
Подключение к Binance API (python-binance, ccxt):
Загрузка исторических данных (kline 1m);
Подписка на WebSocket для live-обновлений.
Локальное хранилище:
PostgreSQL + TimescaleDB - отличное решение для временных рядов;
Запись данных по всем тикерам.
Автоматизация:
Используйте Airflow для оркестрации задач;
Контролируйте полноту, корректность и актуальность данных.
Минимальный стек:
python-binance - данные
PostgreSQL + TimescaleDB - база
Airflow - расписание
2. Исполнение торговых решений (Execution Layer)
Решения агента необходимо конвертировать в прибыльные сделки на реальной бирже.
Что для этого нужно:
Интерпретация действий:
LONG / SHORT → MARKET / LIMIT - ордер;
CLOSE → отмена / закрытие позиции.
Связь с Binance (через REST API):
Получение баланса, открытие и контроль ордеров;
Проверка исполнения и расчёт PnL.
Безопасность и контроль:
Запуск через Binance Testnet;
Поддержка dry-run (логика без реальных сделок);
Система алертов (Telegram / email).
Минимальный стек:
python-binance - исполнение
Telegram Bot API - нотификации
Практический вывод
У вас уже есть мозг системы - стратегически мыслящий RL-агент.
Вам необходимо добавить:
Поток данных → агент начнёт видеть рынок в реальном времени;
Модуль исполнения → агент сможет действовать и зарабатывать.
Реализация этих модулей это отличная возможность усовершенствовать свои навыки и глубже понять:
работу с API бирж;
потоковую обработку данных;
надежную автоматизацию и fault-tolerant дизайн.
Начните с малого: напишите стример данных в базу и модуль dry-run исполнения.
Вы удивитесь, как быстро из прототипа вырастает полноценная торговая система.
Если вы дошли до этого раздела, то я хочу вас поздравить, вы уже на другом уровне.
Теперь ваша следующая задача - завершить систему и стать архитектором собственной AI-трейдинговой платформы.
Исходный код, датасеты и работа агента в режиме реального времени:
Репозиторий с кодом: github.com/YuriyKolesnikov/rl-trading-binance
Датасеты на Hugging Face: huggingface.co/datasets/ResearchRL/open-rl-trading-binance-dataset
Онлайн-сигналы и верификация прогнозов агента: t.me/binance_ai_agent