Баланс прибыли и риска в обучении трейдингового агента
Улучшение функции награды с учётом просадок и торговых издержек
Введение: необходимость учёта просадок и издержек
В алгоритмическом трейдинге на основе обучения с подкреплением (RL) цель агента — максимизировать прибыль. Однако погоня за прибылью без учёта риска может приводить к стратегиям с опасно высокими просадками и чрезмерными торговыми издержками.
Ключевые понятия:
- Просадка (drawdown) — снижение капитала от предыдущего максимума до минимальной точки
- Максимальная просадка — наибольшее процентное падение от пика до последующего дна
- Торговые издержки — комиссии и проскальзывание, влияющие на реальную прибыль
Реальные рынки сопряжены с комиссиями и проскальзыванием. Пренебрежение этими факторами может привести к стратегиям с чрезмерной частотой торговли или неоптимальными объёмами позиций. Учёт этих факторов в функции награды обеспечивает более стабильную и реалистичную стратегию.
Бонус за снижение просадки и штраф за просадку
При включении просадки в функцию награды возникает вопрос о конкретной реализации. Основная идея заключается в поощрении агента за уменьшение просадки и штрафовании за превышение допустимого порога просадки.
Логика применения
Поощрение за восстановление
Агент получает бонус за сокращение просадки, приближаясь к новым вершинам капитала
Штраф за глубокую просадку
При превышении порога просадки (например, 10%) применяется штраф
Правильный порядок применения бонуса и штрафа критически важен. Рекомендуется следующий подход:
# Базовая награда за шаг
reward = profit_change
# Шаг 1: штраф за просадку сверх порога
if current_drawdown > DD_THRESHOLD:
excess = current_drawdown - DD_THRESHOLD
reward -= PENALTY_RATE * excess * volume
# Шаг 2: бонус за сокращение просадки
if drawdown_reduced:
reward *= (1 + K_BONUS * dd_gain_fraction)Преимущество: Такой порядок обеспечивает интуитивное понимание: сначала наказывается плохое состояние, затем поощряется улучшение ситуации.
Реализация логики «палка → пряник»
Конкретная реализация системы штрафов и бонусов в функции награды агента включает последовательную обработку базовой награды с учётом просадки и объёма торгов.
Схема расчёта награды
# 1. Базовая награда total_base_reward = raw_pnl - commission - slippage # 2. Обновление баланса и расчёт просадки old_peak = self.peak_balance prelim_balance = prev_balance + total_base_reward new_peak = max(old_peak, prelim_balance) drawdown = (new_peak - prelim_balance) / (new_peak + 1e-8) * 100 # 3. Штраф за превышение порога просадки excess_dd_pct = max(0.0, drawdown - self.drawdown_threshold) / 100 drawdown_penalty = excess_dd_pct * operating_volume reward_after_penalty = total_base_reward - drawdown_penalty
После применения штрафа за просадку рассчитывается бонус за её сокращение:
# 4. Бонус/штраф за изменение просадки
dd_before = self.last_drawdown
dd_after = drawdown
dd_gain = max(0.0, dd_before - dd_after) # просадка ↓
dd_loss = max(0.0, dd_after - dd_before) # просадка ↑
thr = self.drawdown_threshold + 1e-8
k_plus = self.k_bonus # напр. 0.5
k_minus = getattr(self, "k_penalty", 0.2) # можно добавить в config
scale_up = 1 + k_plus * (dd_gain / thr) # 1 ... 1+k_plus
scale_down = 1 - k_minus * (dd_loss / thr) # 1 ... (1-k_minus)
# Гарантируем неотрицательный множитель
net_scale = max(scale_up * scale_down, 0.0)
reward_after_bonus = reward_after_penalty
if reward_after_bonus > 0: # усиливаем только прибыль
reward_after_bonus *= net_scale
else: # а убыток можно ужесточить
reward_after_bonus *= (1 + k_minus * (dd_loss / thr))Дополнительно может применяться бонус за уменьшение объёма торгов:
# 5. Бонус за уменьшение объёма (опционально)
growth = max(prelim_balance - old_peak, 0.0)
volume_bonus = (growth if self.use_volume_decrease_bonus else 0.0) \
* (1 / (1 + total_trade_volume / operating_volume))
total_reward = reward_after_bonus + volume_bonus
norm_total_reward = total_reward / operating_volumeПсихологические преимущества:
- Сначала показывается «кнут» — убирается фиксированная сумма за превышение порога просадки
- Затем «пряник» — премирование за уменьшение просадки по сравнению с предыдущим шагом
- Агент видит, что любое ухудшение просадки сразу обнуляет или съедает будущий бонус
После расчёта награды обновляются внутренние состояния агента:
# Обновление состояний self.current_balance = prelim_balance + volume_bonus # уже учли penalty/bonus self.peak_balance = new_peak self.last_drawdown = drawdown self.max_drawdown = max(self.max_drawdown, drawdown)
Детали симметричного штрафа за рост просадки
Симметричный штраф за увеличение просадки реализуется через параметр k_penalty, который можно добавить в конфигурацию с значением по умолчанию 0.2-0.3.
Примеры работы штрафа:
- Если просадка выросла на 50% от порога при k_penalty = 0.2, множитель ≈ 0.9 (награда ↓ на 10%)
- Если просадка превысила порог полностью (dd_loss / thr ≥ 1), награда на этом шаге обнуляется
- Сверхпороговые значения дополнительно штрафуются через drawdown_penalty
Такой подход обеспечивает баланс между поощрением за улучшение ситуации и наказанием за её ухудшение, что способствует формированию более стабильных торговых стратегий.
Симметричный штраф за увеличение просадки
Традиционный подход предусматривает бонус за сокращение просадки, но отсутствие санкций за её увеличение может приводить к нежелательному поведению. Агент может рискованно наращивать позиции или удерживать убыточные сделки, углубляя просадку.
Проблема традиционного подхода:
Отсутствие штрафа за увеличение просадки может поощрять рискованное поведение в надежде на последующее восстановление и получение бонуса.
Симметричный подход предполагает штраф за рост просадки, аналогичный бонусу за её сокращение:
# Штраф за увеличение просадки
if drawdown_increased:
reward *= (1 - K_PENALTY * dd_loss_fraction)
# где dd_loss_fraction = на сколько выросла просадкаВажно: Баланс между поощрением и штрафом требует тщательной настройки. Слишком сильный штраф может сделать агента излишне консервативным.
Учёт оборота и проскальзывания: нелинейные торговые издержки
Помимо управления риском через просадки, критически важен учёт торговых издержек. Традиционный подход включает линейную комиссию за объём сделки, но реальные рынки характеризуются нелинейным ростом издержек с увеличением объёма.
Квадратичный закон влияния
Исследования показывают, что влияние сделки на цену масштабируется по закону квадратного корня:
impact ≈ C · σ · √(Q/V) где: Q — объём сделки V — типичный объём (дневной оборот) σ — волатильность C — константа
Реализация нелинейных издержек в функции награды:
linear_cost = COMM_RATE * volume impact_cost = IMPACT_COEFF * sqrt(volume_ratio) total_cost = linear_cost + impact_cost reward = profit_change - total_cost
Результат: Агент учится торговать более экономно, избегая лишних сделок и разбивая крупные позиции на меньшие части.
Расширенные критерии отбора лучшей модели
При обучении агента периодически сохраняется «лучшая» модель на основе определённых критериев. Традиционно таким критерием служила суммарная прибыль (PNL), но комплексная оценка требует учёта риска и эффективности.
Ключевые метрики оценки
Коэффициент Шарпа
Измеряет доходность на единицу принятого риска (волатильности доходности)
Оборачиваемость капитала
Количество сделок и связанные с ними издержки
Максимальная просадка
Наибольшее падение капитала от пика до минимума
Коэффициент Кальмара
Отношение доходности к максимальной просадке
Композиционный критерий отбора модели:
def is_better_model(new, best):
# Проверка основной доходности
if new.profit > best.profit * (1 + 0.01):
return True
# При равной прибыли сравниваем риски
if abs(new.profit - best.profit) < best.profit * 0.01:
if new.max_drawdown < best.max_drawdown * 0.9:
return True # просадка существенно ниже
if new.turnover < best.turnover * 0.7:
return True # оборот значительно ниже
if new.sharpe > best.sharpe:
return True # лучший коэффициент Шарпа
return FalseДополнительные метрики оценки
Помимо коэффициента Шарпа существуют другие метрики для оценки качества стратегий:
| Метрика | Формула | Особенности |
|---|---|---|
| Коэффициент Сортино | (R - Rf) / σd | Учитывает только нижнюю полуволатильность, сильнее штрафует за просадки |
| Коэффициент Кальмара | Годовая доходность / Max DD | Прямое отношение доходности к максимальной просадке |
| Коэффициент Стерлинга | (R - Rf) / (Max DD - 10%) | Учитывает минимальную просадку в 10% как базовый риск |
Заключение: ценность комплексного подхода
Внедрение рассмотренных методов обеспечивает следующие преимущества:
Ограничение рисков просадки
Просадки становятся «дорогими» в функции награды, что приближает поведение агента к поведению опытного трейдера, ценящего сохранение капитала
Учёт реальных издержек
Нелинейный штраф за оборот имитирует рыночный импакт, делая стратегии более реалистичными
Повышение устойчивости
Стратегии становятся более устойчивыми к рыночным шокам и изменениям условий торговли
Комплексная оценка качества
Расширенные критерии отбора обеспечивают выбор стратегий с оптимальным соотношением риск-доходность
Результат: Комплексный подход к обучению трейдингового агента обеспечивает создание стратегий, которые не только прибыльны, но и устойчивы, реалистичны и готовы к применению в реальных рыночных условиях.