Динамика капитала на отложенных рыночных данных (период: 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
Автор: quantAIengineer


