Перейти к содержимому

Глава 39: Конформное предсказание — Торговля с калиброванной неопределённостью

Обзор

Конформное предсказание (Conformal Prediction, CP) — это мощный фреймворк для количественной оценки неопределённости, предоставляющий калиброванные интервалы предсказания с гарантированным покрытием. В отличие от стандартных моделей машинного обучения, которые часто дают чрезмерно самоуверенные прогнозы, конформное предсказание обеспечивает честные оценки неопределённости при минимальных предположениях.

Ключевая идея для торговли: торгуем только когда модель уверена, и размер позиции обратно пропорционален неопределённости. Этот подход естественным образом избегает сделок в периоды высокой неопределённости (рыночный стресс, смена режимов) и концентрирует капитал, когда прогнозы надёжны.

Почему конформное предсказание для торговли?

  1. Гарантированное покрытие: Если вы целитесь на 90% покрытие, примерно 90% ваших интервалов предсказания будут содержать истинное значение
  2. Свобода от распределения: Работает с любой базовой моделью без параметрических предположений
  3. Валидность на конечной выборке: Гарантии выполняются для любого размера выборки, а не только асимптотически
  4. Адаптивность: Интервалы естественно расширяются в волатильные периоды и сужаются в стабильные
  5. Модель-агностичность: Обёртывает любую ML-модель (нейросети, градиентный бустинг и др.) конформным предсказанием

Содержание

  1. Теоретические основы
  2. Методы конформного предсказания
  3. Проектирование торговой стратегии
  4. Реализация
  5. Бэктестинг и оценка
  6. Ресурсы и литература

Теоретические основы

Взаимозаменяемость и гарантии покрытия

Конформное предсказание опирается на предположение о взаимозаменяемости (exchangeability): совместное распределение точек данных инвариантно к перестановкам. Это слабее, чем предположение i.i.d., и допускает зависимые данные при определённых условиях.

Ключевая теорема (Vovk et al., 2005): Для взаимозаменяемых данных $(X_1, Y_1), \ldots, (X_n, Y_n), (X_{n+1}, Y_{n+1})$ множество конформного предсказания $C(X_{n+1})$, построенное на уровне $1-\alpha$, удовлетворяет:

$$P(Y_{n+1} \in C(X_{n+1})) \geq 1 - \alpha$$

Эта гарантия является маргинальной (усреднённой по всем тестовым точкам) и выполняется точно на конечных выборках.

Баллы неконформности

Ядро конформного предсказания — балл неконформности — функция, измеряющая насколько «необычна» точка данных относительно других. Распространённые варианты:

  • Абсолютный остаток: $s(x, y) = |y - \hat{f}(x)|$
  • Нормализованный остаток: $s(x, y) = \frac{|y - \hat{f}(x)|}{\hat{\sigma}(x)}$
  • На основе квантилей: $s(x, y) = \max(\hat{q}{\alpha/2}(x) - y, y - \hat{q}{1-\alpha/2}(x))$

Выбор функции баллов влияет на форму и адаптивность интервалов предсказания.


Методы конформного предсказания

Раздельное конформное предсказание

Простейший и наиболее практичный метод:

  1. Разделение данных на обучающую и калибровочную выборки
  2. Обучение базовой модели на обучающей выборке
  3. Калибровка путём вычисления баллов неконформности на калибровочной выборке
  4. Предсказание путём нахождения $1-\alpha$ квантиля калибровочных баллов
import numpy as np
from sklearn.model_selection import train_test_split
class SplitConformalPredictor:
"""
Раздельное конформное предсказание для регрессии с гарантированным покрытием.
Гарантия покрытия: P(Y ∈ [lower, upper]) ≥ 1 - alpha
"""
def __init__(self, model, alpha=0.1):
self.model = model
self.alpha = alpha # Уровень непокрытия (1 - alpha = покрытие)
self.calibration_scores = None
self.q_hat = None
def fit(self, X_train, y_train, X_calib, y_calib):
"""
Обучение модели и калибровка на отложенной выборке.
Параметры:
----------
X_train : array-like, Обучающие признаки
y_train : array-like, Обучающие цели
X_calib : array-like, Калибровочные признаки (отложенные от обучения)
y_calib : array-like, Калибровочные цели
"""
# Шаг 1: Обучение базовой модели
self.model.fit(X_train, y_train)
# Шаг 2: Получение предсказаний на калибровочной выборке
y_pred_calib = self.model.predict(X_calib)
# Шаг 3: Вычисление баллов неконформности (абсолютные остатки)
self.calibration_scores = np.abs(y_calib - y_pred_calib)
# Шаг 4: Вычисление квантиля для интервалов предсказания
# Квантиль (1-alpha)(1 + 1/n) обеспечивает покрытие на конечной выборке
n = len(self.calibration_scores)
q_level = np.ceil((n + 1) * (1 - self.alpha)) / n
q_level = min(q_level, 1.0) # Ограничение сверху
self.q_hat = np.quantile(self.calibration_scores, q_level)
return self
def predict(self, X):
"""
Возвращает точечное предсказание и интервал предсказания.
Возвращает:
-----------
dict с ключами: 'prediction', 'lower', 'upper', 'interval_width'
"""
y_pred = self.model.predict(X)
lower = y_pred - self.q_hat
upper = y_pred + self.q_hat
return {
'prediction': y_pred,
'lower': lower,
'upper': upper,
'interval_width': np.full_like(y_pred, 2 * self.q_hat)
}
def coverage(self, X_test, y_test):
"""Вычисление эмпирического покрытия на тестовой выборке."""
pred = self.predict(X_test)
covered = (y_test >= pred['lower']) & (y_test <= pred['upper'])
return covered.mean()

Конформизированная квантильная регрессия (CQR)

CQR создаёт адаптивные интервалы, ширина которых варьируется в зависимости от входных признаков. Это критически важно для финансовых данных, где неопределённость существенно различается в разных рыночных режимах.

from sklearn.ensemble import GradientBoostingRegressor
class ConformizedQuantileRegression:
"""
CQR: Конформизированная квантильная регрессия
Создаёт гетероскедастические интервалы, адаптирующиеся к локальной неопределённости.
Более информативна, чем раздельное конформное предсказание для финансовых данных.
"""
def __init__(self, alpha=0.1):
self.alpha = alpha
# Обучение квантильных моделей для нижней и верхней границ
self.lower_model = GradientBoostingRegressor(
loss='quantile', alpha=alpha/2, n_estimators=100
)
self.upper_model = GradientBoostingRegressor(
loss='quantile', alpha=1-alpha/2, n_estimators=100
)
self.q_hat = None
def fit(self, X_train, y_train, X_calib, y_calib):
"""Обучение квантильных моделей и калибровка."""
# Обучение квантильных моделей
self.lower_model.fit(X_train, y_train)
self.upper_model.fit(X_train, y_train)
# Получение начальных интервалов на калибровочной выборке
lower_calib = self.lower_model.predict(X_calib)
upper_calib = self.upper_model.predict(X_calib)
# Вычисление баллов конформности
# Балл = насколько интервал должен расшириться для покрытия истинного значения
scores = np.maximum(
lower_calib - y_calib, # Нижняя граница слишком высока
y_calib - upper_calib # Верхняя граница слишком низка
)
# Квантиль для гарантированного покрытия
n = len(scores)
q_level = np.ceil((n + 1) * (1 - self.alpha)) / n
q_level = min(q_level, 1.0)
self.q_hat = np.quantile(scores, q_level)
return self
def predict(self, X):
"""Возвращает адаптивные интервалы предсказания."""
lower = self.lower_model.predict(X) - self.q_hat
upper = self.upper_model.predict(X) + self.q_hat
return {
'lower': lower,
'upper': upper,
'interval_width': upper - lower,
'midpoint': (upper + lower) / 2
}

Адаптивный конформный вывод для временных рядов

Стандартное конформное предсказание предполагает взаимозаменяемость, которая нарушается во временных рядах. Адаптивный конформный вывод (ACI) решает эту проблему путём динамической корректировки уровня покрытия на основе недавней производительности.

class AdaptiveConformalPredictor:
"""
Адаптивный конформный вывод (ACI) для временных рядов.
Динамически корректирует уровень покрытия на основе недавних ошибок,
поддерживая приблизительное покрытие при сдвиге распределения.
Ссылка: Gibbs & Candès (2021) "Adaptive Conformal Inference
Under Distribution Shift"
"""
def __init__(self, model, target_coverage=0.9, gamma=0.05):
self.model = model
self.target_coverage = target_coverage
self.gamma = gamma # Скорость обучения для адаптации
self.alpha_t = 1 - target_coverage # Текущий уровень непокрытия
self.history = [] # Отслеживание покрытия во времени
def update(self, y_true, lower, upper):
"""
Обновление alpha на основе того, было ли y_true покрыто.
Реализует онлайн-обучение уровня покрытия:
- Если покрытие больше целевого: уменьшаем интервалы (снижаем alpha)
- Если покрытие меньше целевого: увеличиваем интервалы (повышаем alpha)
"""
covered = (lower <= y_true) and (y_true <= upper)
self.history.append(covered)
# Градиентное обновление: двигаем alpha к достижению целевого покрытия
if covered:
# Покрыто -> можем позволить более узкие интервалы
self.alpha_t = self.alpha_t + self.gamma * (self.alpha_t - 0)
else:
# Не покрыто -> нужны более широкие интервалы
self.alpha_t = self.alpha_t + self.gamma * (self.alpha_t - 1)
# Ограничение допустимого диапазона
self.alpha_t = np.clip(self.alpha_t, 0.001, 0.5)
return covered
def predict(self, X, calibration_scores):
"""Генерация предсказания с адаптивным интервалом."""
y_pred = self.model.predict(X)
# Вычисление ширины интервала на основе текущего alpha
q_level = 1 - self.alpha_t
q_hat = np.quantile(calibration_scores, min(q_level, 1.0))
return {
'prediction': y_pred,
'lower': y_pred - q_hat,
'upper': y_pred + q_hat,
'interval_width': 2 * q_hat,
'current_alpha': self.alpha_t,
'recent_coverage': np.mean(self.history[-100:]) if self.history else None
}

Проектирование торговой стратегии

Генерация сигналов с неопределённостью

Основная идея: торгуем только когда интервал предсказания узкий (высокая уверенность) И направление ясно.

class ConformalTradingStrategy:
"""
Торговая стратегия с использованием калиброванных интервалов предсказания.
Ключевые принципы:
1. Торгуем только когда интервал узкий (высокая уверенность)
2. Направление должно быть ясным (интервал не пересекает ноль или далеко от него)
3. Размер позиции обратно пропорционален неопределённости
"""
def __init__(self, predictor, width_threshold=0.02, min_edge=0.005):
"""
Параметры:
----------
predictor : Конформный предсказатель с методом predict()
width_threshold : Максимальная ширина интервала для сделки (напр., 2% для доходностей)
min_edge : Минимальное ожидаемое преимущество для торговли (напр., 0.5% ожидаемая доходность)
"""
self.predictor = predictor
self.width_threshold = width_threshold
self.min_edge = min_edge
def generate_signal(self, X):
"""
Генерация торгового сигнала на основе интервала предсказания.
Возвращает:
-----------
dict с: prediction, interval_width, confidence, trade, direction, size
"""
pred = self.predictor.predict(X)
# Обработка скалярных и массивных входов
if hasattr(pred['interval_width'], '__len__'):
interval_width = pred['interval_width'][0]
lower = pred['lower'][0]
upper = pred['upper'][0]
midpoint = pred.get('midpoint', (lower + upper) / 2)
if hasattr(midpoint, '__len__'):
midpoint = midpoint[0]
else:
interval_width = pred['interval_width']
lower = pred['lower']
upper = pred['upper']
midpoint = pred.get('midpoint', (lower + upper) / 2)
signal = {
'prediction': midpoint,
'interval_width': interval_width,
'lower': lower,
'upper': upper,
'confidence': 1 / (1 + interval_width * 10), # Преобразование в шкалу 0-1
'trade': False,
'direction': 0,
'size': 0.0
}
# Условие 1: Интервал должен быть достаточно узким
if interval_width >= self.width_threshold:
signal['skip_reason'] = 'interval_too_wide'
return signal
# Условие 2: Направление должно быть ясным с достаточным преимуществом
if lower > self.min_edge:
# Весь интервал положительный с достаточной величиной
signal['direction'] = 1 # Лонг
signal['trade'] = True
signal['edge'] = lower # Худший случай ожидаемой доходности
elif upper < -self.min_edge:
# Весь интервал отрицательный с достаточной величиной
signal['direction'] = -1 # Шорт
signal['trade'] = True
signal['edge'] = -upper # Худший случай ожидаемой доходности
else:
signal['skip_reason'] = 'unclear_direction'
return signal
# Размер позиции обратно пропорционален ширине интервала
# Уже интервал -> выше уверенность -> больше позиция
signal['size'] = self._compute_size(interval_width, signal['edge'])
return signal
def _compute_size(self, interval_width, edge):
"""
Вычисление размера позиции на основе неопределённости и преимущества.
Использует упрощённый подход: size = edge / interval_width
Ограничен 1.0 (100% капитала)
"""
if interval_width <= 0:
return 0.0
# Размер пропорционален отношению преимущества к неопределённости
raw_size = edge / interval_width
# Применение ограничений
size = min(raw_size, 1.0)
size = max(size, 0.0)
return size

Определение размера позиции с калиброванной уверенностью

def kelly_with_conformal(prediction, lower, upper, risk_free_rate=0):
"""
Критерий Келли, адаптированный для интервалов конформного предсказания.
Ключевая идея: Ширина интервала предоставляет калиброванную оценку
неопределённости, которую можно использовать для корректировки доли Келли.
Параметры:
----------
prediction : Точечное предсказание (ожидаемая доходность)
lower : Нижняя граница интервала предсказания
upper : Верхняя граница интервала предсказания
risk_free_rate : Безрисковая ставка для расчёта избыточной доходности
Возвращает:
-----------
kelly_fraction : Рекомендуемый размер позиции как доля капитала
"""
interval_width = upper - lower
expected_excess = prediction - risk_free_rate
# Граничный случай: нет ожидаемого преимущества
if expected_excess <= 0:
return 0.0
# Граничный случай: вырожденный интервал
if interval_width <= 0:
return 0.0
# Ширина интервала служит прокси для волатильности
# Доля Келли = ожидаемая_доходность / дисперсия
# Используем interval_width как прокси для стандартного отклонения
implied_variance = (interval_width / 2) ** 2 # Полуширина как прокси std
kelly_fraction = expected_excess / implied_variance
# Применяем половину Келли для безопасности (распространённая практика)
kelly_fraction = kelly_fraction / 2
# Ограничение разумными уровнями
kelly_fraction = min(kelly_fraction, 2.0) # Макс 200% (с плечом)
kelly_fraction = max(kelly_fraction, -2.0) # Макс -200% (шорт)
return kelly_fraction
class ConfidenceBasedSizing:
"""
Определение размера позиции на основе уверенности интервала предсказания.
Отображает ширину интервала на размер позиции различными способами.
"""
def __init__(self, method='inverse', max_size=1.0, min_size=0.0):
self.method = method
self.max_size = max_size
self.min_size = min_size
def compute_size(self, interval_width, baseline_width=None):
"""
Вычисление размера позиции на основе ширины интервала.
Параметры:
----------
interval_width : Текущая ширина интервала предсказания
baseline_width : Эталонная ширина для нормализации
"""
if baseline_width is None:
baseline_width = interval_width
if self.method == 'inverse':
# Размер = базовая / текущая (уже = больше)
size = baseline_width / max(interval_width, 1e-6)
elif self.method == 'linear':
# Линейное уменьшение: size = 1 - width/baseline
size = 1 - interval_width / max(baseline_width, 1e-6)
elif self.method == 'exponential':
# Экспоненциальное затухание на основе ширины
size = np.exp(-interval_width / baseline_width)
elif self.method == 'threshold':
# Бинарный: полный размер если ниже порога, ноль иначе
size = self.max_size if interval_width < baseline_width else 0
else:
raise ValueError(f"Неизвестный метод: {self.method}")
# Ограничение границами
return np.clip(size, self.min_size, self.max_size)

Реализация

Ноутбуки

#НоутбукОписание
101_conformal_theory.ipynbТеория: взаимозаменяемость, гарантии покрытия, баллы неконформности
202_split_conformal.ipynbРеализация и анализ раздельного конформного предсказания
303_conformalized_quantile.ipynbКонформизированная квантильная регрессия для адаптивных интервалов
404_adaptive_conformal.ipynbАдаптивный конформный вывод для временных рядов
505_financial_application.ipynbПрименение к прогнозированию доходностей на реальных рыночных данных
606_interval_analysis.ipynbАнализ паттернов ширины интервалов и рыночных режимов
707_trading_rules.ipynbТорговые правила на основе интервалов предсказания
808_position_sizing.ipynbОпределение размера позиции по Келли с калиброванной неопределённостью
909_backtesting.ipynbПолный бэктест стратегии конформного предсказания
1010_comparison.ipynbСравнение со стандартным ML без оценки неопределённости

Примеры кода

Смотрите директорию rust_examples/ для готовых к продакшену реализаций на Rust:

  • Клиент API Bybit для криптовалютных данных в реальном времени
  • Модульные алгоритмы конформного предсказания (Split CP, CQR, ACI)
  • Фреймворк торговой стратегии с сигналами на основе интервалов
  • Движок бэктестинга с правильной обработкой временных рядов

Бэктестинг и оценка

Ключевые метрики

Метрики покрытия:

  • Эмпирическое покрытие: Доля истинных значений внутри интервалов предсказания
  • Условное покрытие: Покрытие, стратифицированное по ширине интервала, режиму волатильности и т.д.
  • Стабильность покрытия: Насколько согласованно покрытие во времени?

Качество интервалов:

  • Средняя ширина: Средняя ширина интервала предсказания
  • Вариабельность ширины: Стандартное отклонение ширины интервалов
  • Резкость (Sharpness): Обратная средней ширине (уже = резче)
  • Балл Винклера: Комбинированная мера покрытия и резкости

Торговая результативность:

  • Коэффициент Шарпа: Доходность с поправкой на риск
  • Процент выигрышей: Доля прибыльных сделок
  • Средняя сделка: Средняя доходность на сделку
  • Селективность торговли: Доля периодов с торговым сигналом
def evaluate_conformal_strategy(results_df):
"""
Комплексная оценка стратегии конформного предсказания.
Параметры:
----------
results_df : DataFrame с колонками:
- prediction, lower, upper, actual, direction, size, pnl
"""
metrics = {}
# Метрики покрытия
covered = (results_df['actual'] >= results_df['lower']) & \
(results_df['actual'] <= results_df['upper'])
metrics['coverage'] = covered.mean()
# Метрики интервалов
widths = results_df['upper'] - results_df['lower']
metrics['avg_width'] = widths.mean()
metrics['width_std'] = widths.std()
metrics['sharpness'] = 1 / widths.mean()
# Торговые метрики (только для фактических сделок)
trades = results_df[results_df['direction'] != 0]
if len(trades) > 0:
metrics['n_trades'] = len(trades)
metrics['trade_frequency'] = len(trades) / len(results_df)
metrics['avg_pnl'] = trades['pnl'].mean()
metrics['sharpe'] = trades['pnl'].mean() / trades['pnl'].std() * np.sqrt(252)
metrics['win_rate'] = (trades['pnl'] > 0).mean()
metrics['total_return'] = trades['pnl'].sum()
# Условное покрытие для сделок
trades_covered = covered[results_df['direction'] != 0]
metrics['coverage_on_trades'] = trades_covered.mean()
return metrics

Сравнение с традиционными подходами

Проблема стандартного ML

Традиционные ML-модели для торговли дают точечные прогнозы без надёжных оценок неопределённости:

  • Чрезмерная уверенность: Нейронные сети часто выдают высокоуверенные предсказания, даже когда ошибаются
  • Некалиброванные вероятности: Предсказанные вероятности не соответствуют реальным частотам
  • Предположения о распределении: Многие методы предполагают гауссовы ошибки, что редко выполняется на финансовых рынках
  • Отсутствие гарантий покрытия: Нет теоретической гарантии, что интервалы предсказания содержат истинные значения

Конформное предсказание vs. другие методы оценки неопределённости

АспектТрадиционный MLКонформное предсказание
Оценка неопределённостиЭвристическая или отсутствуетГарантированное покрытие
Предположения о распределенииЧасто гауссовоСвободное от распределения
КалибровкаТребует отдельной валидацииВстроенная калибровка
Размер позицииСубъективныйПринципиальный, основанный на неопределённости
Управление рискамиСпециальноеГарантии покрытия
АдаптивностьСтатическаяВозможна онлайн-адаптация

vs. Байесовские нейронные сети

  • BNN: Требует спецификации априорного распределения, вычислительно дорого
  • CP: Свободен от распределения, гарантия на конечной выборке

vs. Монте-Карло Dropout

  • MC Dropout: Приблизительный, без гарантии покрытия
  • CP: Точная гарантия покрытия

vs. Ансамблевые методы

  • Ансамбли: Неопределённость из разногласий, некалиброванная
  • CP: Калиброванные интервалы с доказуемым покрытием

vs. Квантильная регрессия

  • QR: Асимптотически валидная, некалиброванная на конечных выборках
  • CQR: Конформизированная QR с гарантиями на конечных выборках

Полное конформное предсказание

Оригинальный метод — вычислительно дорогой, но оптимальный:

Алгоритм:
1. Для каждой возможной метки y:
a. Добавить (x_new, y) в калибровочный набор
b. Вычислить все баллы неконформности
c. Вычислить p-значение: доля баллов >= балла (x_new, y)
2. Вернуть все y с p-значением > alpha
Сложность: O(n) переобучений модели на предсказание

Это контрастирует с раздельным конформным предсказанием (используемым на практике), которое требует только O(1) на предсказание после начальной настройки.


Дополнительные функции баллов неконформности

Балл MAPIE (адаптивный)

def mapie_score(y_true, y_pred, residuals_std):
"""Локально-взвешенный балл на основе MAD остатков"""
return np.abs(y_true - y_pred) / residuals_std

Эта адаптивная функция баллов особенно полезна для финансовых данных, где дисперсия остатков варьируется в различных рыночных условиях.


Конвейер конформного предсказания

┌─────────────────────────────────────────────────────────────────┐
│ КОНВЕЙЕР КОНФОРМНОГО ПРЕДСКАЗАНИЯ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ СЛОЙ ДАННЫХ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Рыночные данные (OHLCV, объём, стакан заявок) │ │
│ │ - Доходности (несколько таймфреймов) │ │
│ │ - Профиль объёма и моментум │ │
│ │ - Технические индикаторы (RSI, MACD, Боллинджер) │ │
│ │ - Меры волатильности (ATR, реализованная вол.) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ИНЖИНИРИНГ ПРИЗНАКОВ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Признаки временных рядов, лаговые значения, скользящая │ │
│ │ статистика, кросс-активные корреляции, индикаторы режима │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ОБУЧЕНИЕ БАЗОВОЙ МОДЕЛИ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Предсказатель: нейронная сеть / градиентный бустинг │ │
│ │ - LSTM, трансформер или ансамблевые методы │ │
│ │ - Предсказывает E[Y|X] или квантили │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ КОНФОРМНАЯ КАЛИБРОВКА │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Вычисление баллов неконформности │ │
│ │ - Баллы на отложенном калибровочном наборе │ │
│ │ - Адаптивные баллы для гетероскедастических данных │ │
│ │ Оценка квантиля │ │
│ │ - Нахождение (1-alpha) квантиля калибровочных баллов │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ↓ │
│ ПРЕДСКАЗАНИЕ И ТОРГОВОЕ РЕШЕНИЕ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Точечное предсказание + калиброванный интервал │ │
│ │ Размер позиции на основе ширины интервала и уверенности │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Инжиниринг признаков для конформного предсказания

features = {
# Ценовые признаки
'returns_1m': log_return(close, 1),
'returns_5m': log_return(close, 5),
'returns_15m': log_return(close, 15),
'returns_1h': log_return(close, 60),
# Признаки волатильности
'volatility_1h': rolling_std(returns, 60),
'atr_14': average_true_range(high, low, close, 14),
'realized_vol': realized_volatility(returns, 20),
# Индикаторы моментума
'rsi_14': rsi(close, 14),
'macd': macd(close, 12, 26, 9),
'momentum_10': momentum(close, 10),
# Признаки объёма
'volume_ratio': volume / volume_ma_20,
'obv': on_balance_volume(close, volume),
# Индикаторы тренда
'sma_cross': sma(close, 10) - sma(close, 30),
'ema_trend': ema(close, 20) - ema(close, 50),
}

Конфигурация

model:
base_predictor: "gradient_boosting" # или "neural_network"
n_estimators: 100
max_depth: 6
learning_rate: 0.1
conformal:
method: "split" # "split", "cv" или "jackknife"
alpha: 0.1 # Целевой уровень непокрытия (10%)
calibration_size: 0.2
adaptive: true
window_size: 100 # Для адаптивного конформного
trading:
max_position: 1.0
risk_budget: 0.02 # 2% риска на сделку
min_confidence: 0.6
rebalance_frequency: "1H"
data:
train_split: 0.6
calibration_split: 0.2
test_split: 0.2
lookback_window: 60
prediction_horizon: 5 # 5 периодов вперёд

Продакшн-соображения

Конвейер инференса:
├── Сбор данных (Exchange WebSocket/REST)
│ └── OHLCV обновления в реальном времени
├── Вычисление признаков
│ └── Скользящая статистика, индикаторы
├── Предсказание модели
│ └── Точечное предсказание базовой модели
├── Конформный интервал
│ └── Применение калиброванного квантиля
├── Адаптивное обновление
│ └── Отслеживание покрытия, корректировка alpha
└── Генерация сигналов
└── Размер позиции с учётом неопределённости
Бюджет задержки:
├── Сбор данных: ~10мс
├── Вычисление признаков: ~5мс
├── Инференс модели: ~10мс
├── Конформная калибровка: ~1мс
├── Генерация сигналов: ~1мс
└── Итого: ~30мс (без исполнения)
Расписание рекалибровки:
├── Полная рекалибровка: ежедневно (конец дня)
├── Адаптивное обновление alpha: на каждое предсказание
├── Переобучение модели: еженедельно/ежемесячно
└── Ревизия признаков: ежеквартально

Ресурсы и литература

Академические статьи

  • Vovk, Gammerman, Shafer (2005): “Algorithmic Learning in a Random World” — Основополагающий учебник по конформному предсказанию
  • Romano, Patterson, Candès (2019): “Conformalized Quantile Regression” — CQR для адаптивных интервалов
  • Gibbs & Candès (2021): “Adaptive Conformal Inference Under Distribution Shift” — ACI для невзаимозаменяемых данных
  • Barber et al. (2022): “Conformal Prediction Beyond Exchangeability” — Расширения для зависимых данных
  • Tibshirani et al. (2019): “Conformal Prediction Under Covariate Shift” — https://arxiv.org/abs/1904.06019
  • Angelopoulos & Bates (2021): “Conformal Prediction: A Gentle Introduction” — https://arxiv.org/abs/2107.07511

Программные библиотеки

  • MAPIE: Комплексная библиотека конформного предсказания для Python
  • Crepes: Конформные регрессоры и предиктивные системы
  • ConformalPrediction.jl: Реализация на Julia

Туториалы и курсы


Уровень сложности

Средний (3/5)

Предварительные требования

  • Статистический вывод и проверка гипотез
  • Интервалы предсказания vs. доверительные интервалы
  • Основы квантильной регрессии
  • Основы анализа временных рядов
  • Управление рисками и определение размера позиции

Результаты обучения

После завершения этой главы вы сможете:

  1. Реализовать конформное предсказание для прогнозирования доходностей
  2. Строить интервалы предсказания с гарантированным покрытием
  3. Проектировать торговые стратегии, использующие оценку неопределённости
  4. Определять размер позиции на основе калиброванной уверенности
  5. Оценивать стратегии с помощью метрик покрытия и результативности
  6. Адаптировать методы конформного предсказания для нестационарных финансовых временных рядов