Глава 83: Прототипные сети для финансов
Обзор
Прототипные сети (Prototypical Networks) - это подход мета-обучения, разработанный для задач классификации с малым количеством примеров (few-shot). На финансовых рынках они отлично справляются с классификацией рыночных режимов, обнаружением торговых паттернов и адаптацией к новым рыночным условиям при минимальном количестве размеченных данных. Это особенно ценно на крипторынках, где режимы могут быстро меняться, а исторические паттерны имеют ограниченное количество примеров.
Содержание
- Введение
- Теоретические основы
- Компоненты архитектуры
- Применение на финансовых рынках
- Few-Shot классификация рыночных режимов
- Стратегия реализации
- Интеграция с Bybit
- Управление рисками
- Метрики производительности
- Ссылки
Введение
Традиционные подходы машинного обучения для трейдинга требуют большого количества размеченных данных для каждого рыночного режима или паттерна. Однако финансовые рынки представляют уникальные вызовы:
- Редкость режимов: Некоторые рыночные условия (обвалы, шорт-сквизы) происходят редко
- Дрейф концепций: Рынки эволюционируют, делая исторические данные менее релевантными
- Быстрая адаптация: Необходимость распознавать новые паттерны с небольшим количеством примеров
Почему прототипные сети для трейдинга?
┌─────────────────────────────────────────────────────────────────────────┐│ Проблема Few-Shot в трейдинге │├─────────────────────────────────────────────────────────────────────────┤│ ││ Традиционное ML: Прототипные сети: ││ ──────────────── ──────────────── ││ Нужны 1000+ примеров Нужно только 5-20 примеров ││ каждого паттерна на паттерн (support set) ││ ││ Проблема: Редкие события Решение: Учимся вычислять ││ типа флэш-крэшей имеют "прототипы" из малого числа ││ мало исторических примеров примеров и классифицировать ││ ││ ┌────────────┐ ┌────────────┐ ││ │ Бычий рынок│ 1000 примеров │ Бычий рынок│ 10 примеров ││ │ Медвежий │ 1000 примеров │ Медвежий │ 10 примеров ││ │ Обвал │ 12 примеров ❌ │ Обвал │ 5 примеров ✓ ││ │ Сквиз │ 8 примеров ❌ │ Сквиз │ 5 примеров ✓ ││ └────────────┘ └────────────┘ ││ │└─────────────────────────────────────────────────────────────────────────┘Ключевые преимущества
| Аспект | Традиционное ML | Прототипные сети |
|---|---|---|
| Требования к данным | Высокие (1000+ на класс) | Низкие (5-20 на класс) |
| Адаптация к новым паттернам | Требует переобучения | Достаточно нескольких примеров |
| Обработка редких событий | Плохо | Отлично |
| Вычислительные затраты | Высокие при переобучении | Низкие при адаптации |
| Интерпретируемость | Низкая (чёрный ящик) | Высокая (расстояния до прототипов) |
Теоретические основы
Фреймворк прототипных сетей
Прототипная сеть изучает метрическое пространство, где классификация выполняется путём вычисления расстояний до прототипов классов (центроидов).
Математическая формулировка
Функция эмбеддинга: $f_\phi: \mathbb{R}^D \rightarrow \mathbb{R}^M$
Отображает входные данные в M-мерное пространство эмбеддингов через нейронную сеть с параметрами $\phi$.
Вычисление прототипа: Для support set $S_k$ примеров класса $k$:
$$c_k = \frac{1}{|S_k|} \sum_{(x_i, y_i) \in S_k} f_\phi(x_i)$$
где $c_k$ - прототип (центроид) класса $k$.
Классификация: Для query точки $x$ вычисляем распределение вероятностей по классам:
$$p(y = k | x) = \frac{\exp(-d(f_\phi(x), c_k))}{\sum_{k’} \exp(-d(f_\phi(x), c_{k’}))}$$
где $d$ - функция расстояния (обычно квадрат евклидова расстояния).
Обучение через эпизоды
┌────────────────────────────────────────────────────────────────────────┐│ Процесс эпизодического обучения │├────────────────────────────────────────────────────────────────────────┤│ ││ Эпизод = Одна итерация обучения, симулирующая few-shot сценарий ││ ││ Шаг 1: Выбираем N классов (напр., 5 рыночных режимов) ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ Бычий │ Медвежий │ Боковик │ Обвал │ Восстановление │ ││ └─────────────────────────────────────────────────────────────┘ ││ ││ Шаг 2: Для каждого класса выбираем K support + Q query примеров ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ Бычий: [s1, s2, s3, s4, s5] | [q1, q2, q3] │ ││ │ Медвежий: [s1, s2, s3, s4, s5] | [q1, q2, q3] │ ││ │ ... │ ││ └─────────────────────────────────────────────────────────────┘ ││ Support Set (5-shot) Query Set ││ ││ Шаг 3: Вычисляем прототипы из support set ││ Шаг 4: Классифицируем query примеры по расстояниям до прототипов ││ Шаг 5: Вычисляем loss и делаем обратное распространение ││ │└────────────────────────────────────────────────────────────────────────┘N-way K-shot классификация
- N-way: Количество классов для различения
- K-shot: Количество примеров на класс в support set
Для трейдинга: обычно 3-5 way (режимов) с 5-10 shot (примеров на режим)
Функции расстояния
Квадрат евклидова расстояния (по умолчанию): $$d(x, y) = |x - y|^2 = \sum_i (x_i - y_i)^2$$
Косинусное расстояние (альтернатива): $$d(x, y) = 1 - \frac{x \cdot y}{|x| |y|}$$
Расстояние Махаланобиса (учитывает ковариацию): $$d(x, y) = \sqrt{(x-y)^T \Sigma^{-1} (x-y)}$$
Компоненты архитектуры
Архитектура сети эмбеддинга
┌────────────────────────────────────────────────────────────────────────┐│ Сеть эмбеддинга для трейдинга │├────────────────────────────────────────────────────────────────────────┤│ ││ Вход: Рыночные признаки [цена, объём, волатильность, ...] ││ Форма: (batch_size, sequence_length, feature_dim) ││ ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ Блок временных свёрток │ ││ │ ───────────────────────── │ ││ │ Conv1D(in=features, out=64, kernel=3) → BatchNorm → ReLU │ ││ │ Conv1D(in=64, out=128, kernel=3) → BatchNorm → ReLU │ ││ │ Conv1D(in=128, out=128, kernel=3) → BatchNorm → ReLU │ ││ │ MaxPool1D(kernel=2) │ ││ └─────────────────────────────────────────────────────────────┘ ││ ↓ ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ Блок LSTM/Transformer │ ││ │ ───────────────────── │ ││ │ LSTM(hidden=256, layers=2, bidirectional=True) │ ││ │ ИЛИ │ ││ │ TransformerEncoder(d_model=256, nhead=8, layers=2) │ ││ └─────────────────────────────────────────────────────────────┘ ││ ↓ ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ Голова проекции │ ││ │ ─────────────── │ ││ │ Linear(in=256, out=128) → ReLU │ ││ │ Linear(in=128, out=embedding_dim) │ ││ │ L2 нормализация (опционально) │ ││ └─────────────────────────────────────────────────────────────┘ ││ ↓ ││ Выход: Вектор эмбеддинга формы (batch_size, embedding_dim) ││ │└────────────────────────────────────────────────────────────────────────┘Инженерия признаков для трейдинга
┌────────────────────────────────────────────────────────────────────────┐│ Входные признаки для рыночного режима │├────────────────────────────────────────────────────────────────────────┤│ ││ Ценовые признаки: ││ • Доходности (1м, 5м, 15м, 1ч, 4ч, 24ч) ││ • Логарифмические доходности ││ • Диапазон high-low ││ • Позиция close в диапазоне ││ ││ Объёмные признаки: ││ • Объём (нормализованный) ││ • Изменение объёма ││ • Соотношение Buy/Sell объёма ││ • Профиль объёма ││ ││ Признаки волатильности: ││ • Скользящая волатильность (несколько окон) ││ • ATR (Average True Range) ││ • Ширина полос Боллинджера ││ • Волатильность Паркинсона ││ ││ Признаки структуры рынка: ││ • RSI, MACD, Стохастик ││ • Соотношения скользящих средних ││ • Уровни поддержки/сопротивления ││ • Дисбаланс ордербука ││ ││ Крипто-специфичные признаки: ││ • Ставка финансирования (funding rate) ││ • Открытый интерес (OI) ││ • Соотношение Long/Short ││ • Уровни ликвидаций ││ │└────────────────────────────────────────────────────────────────────────┘Модуль вычисления прототипов
/// Вычисление прототипов из эмбеддингов support setpub struct PrototypeComputer { /// Тип функции расстояния distance_type: DistanceType, /// Опциональное уточнение прототипов refine_prototypes: bool,}
impl PrototypeComputer { /// Вычислить прототипы классов из support эмбеддингов pub fn compute_prototypes( &self, support_embeddings: &Array2<f32>, // (n_support, embed_dim) support_labels: &Array1<usize>, // (n_support,) n_classes: usize, ) -> Array2<f32> { // (n_classes, embed_dim) let embed_dim = support_embeddings.ncols(); let mut prototypes = Array2::zeros((n_classes, embed_dim)); let mut counts = vec![0usize; n_classes];
// Суммируем эмбеддинги по классам for (i, &label) in support_labels.iter().enumerate() { prototypes.row_mut(label).add_assign(&support_embeddings.row(i)); counts[label] += 1; }
// Усредняем для получения прототипов for (class_idx, count) in counts.iter().enumerate() { if *count > 0 { prototypes.row_mut(class_idx).mapv_inplace(|x| x / *count as f32); } }
prototypes }
/// Классифицировать query точки по расстояниям до прототипов pub fn classify( &self, query_embeddings: &Array2<f32>, // (n_query, embed_dim) prototypes: &Array2<f32>, // (n_classes, embed_dim) ) -> (Array1<usize>, Array2<f32>) { // (предсказания, вероятности) let n_query = query_embeddings.nrows(); let n_classes = prototypes.nrows();
// Вычисляем расстояния до всех прототипов let mut distances = Array2::zeros((n_query, n_classes)); for i in 0..n_query { for j in 0..n_classes { distances[[i, j]] = self.compute_distance( &query_embeddings.row(i), &prototypes.row(j), ); } }
// Преобразуем в вероятности через softmax от отрицательных расстояний let neg_distances = -&distances; let probabilities = softmax(&neg_distances);
// Получаем предсказания (argmax) let predictions = probabilities .outer_iter() .map(|row| row.iter() .enumerate() .max_by(|a, b| a.1.partial_cmp(b.1).unwrap()) .unwrap().0) .collect();
(Array1::from_vec(predictions), probabilities) }}Применение на финансовых рынках
Классификация рыночных режимов
┌────────────────────────────────────────────────────────────────────────┐│ Классы рыночных режимов │├────────────────────────────────────────────────────────────────────────┤│ ││ Класс 0: СИЛЬНЫЙ_ВОСХОДЯЩИЙ_ТРЕНД ││ ┌───────────────────────────────────────────────────────────┐ ││ │ Характеристики: │ ││ │ • Устойчивые положительные доходности (>2% в день в ср.) │ ││ │ • Растущие максимумы, растущие минимумы │ ││ │ • Объём подтверждает движения │ ││ │ • Положительная ставка финансирования │ ││ └───────────────────────────────────────────────────────────┘ ││ ││ Класс 1: СЛАБЫЙ_ВОСХОДЯЩИЙ_ТРЕНД ││ ┌───────────────────────────────────────────────────────────┐ ││ │ Характеристики: │ ││ │ • Умеренные положительные доходности (0.5-2% в день) │ ││ │ • Волатильное движение с восходящим уклоном │ ││ │ • Смешанные сигналы по объёму │ ││ └───────────────────────────────────────────────────────────┘ ││ ││ Класс 2: БОКОВИК / КОНСОЛИДАЦИЯ ││ ┌───────────────────────────────────────────────────────────┐ ││ │ Характеристики: │ ││ │ • Доходности около нуля │ ││ │ • Цена отскакивает между поддержкой/сопротивлением │ ││ │ • Снижающаяся волатильность │ ││ │ • Низкий объём │ ││ └───────────────────────────────────────────────────────────┘ ││ ││ Класс 3: СЛАБЫЙ_НИСХОДЯЩИЙ_ТРЕНД ││ ┌───────────────────────────────────────────────────────────┐ ││ │ Характеристики: │ ││ │ • Умеренные отрицательные доходности (-0.5 до -2%) │ ││ │ • Формируется паттерн снижающихся максимумов │ ││ │ • Отрицательная ставка финансирования │ ││ └───────────────────────────────────────────────────────────┘ ││ ││ Класс 4: СИЛЬНЫЙ_НИСХОДЯЩИЙ_ТРЕНД / ОБВАЛ ││ ┌───────────────────────────────────────────────────────────┐ ││ │ Характеристики: │ ││ │ • Резкие отрицательные доходности (<-2% в день) │ ││ │ • Всплеск волатильности │ ││ │ • Высокий объём на падениях │ ││ │ • Каскады ликвидаций │ ││ └───────────────────────────────────────────────────────────┘ ││ │└────────────────────────────────────────────────────────────────────────┘Торговая стратегия на основе режимов
┌────────────────────────────────────────────────────────────────────────┐│ Торговые сигналы по режимам │├────────────────────────────────────────────────────────────────────────┤│ ││ Пайплайн определения режима: ││ ──────────────────────────── ││ 1. Собрать последние рыночные данные (напр., за 24 часа) ││ 2. Извлечь признаки для текущего окна ││ 3. Получить эмбеддинг через обученную сеть ││ 4. Вычислить расстояния до прототипов режимов ││ 5. Классифицировать текущий режим с уверенностью ││ 6. Сгенерировать торговый сигнал на основе режима ││ ││ Маппинг Режим → Сигнал: ││ ┌─────────────────┬──────────────────────────────────────────┐ ││ │ Режим │ Действие │ ││ ├─────────────────┼──────────────────────────────────────────┤ ││ │ СИЛЬНЫЙ_ВВЕРХ │ Лонг с трейлинг-стопом, докупать на │ ││ │ │ просадках │ ││ │ СЛАБЫЙ_ВВЕРХ │ Лёгкий лонг, жёсткие стопы │ ││ │ БОКОВИК │ Mean reversion, торговля в диапазоне │ ││ │ СЛАБЫЙ_ВНИЗ │ Лёгкий шорт или оставаться вне рынка │ ││ │ СИЛЬНЫЙ_ВНИЗ │ Шорт с защитой, хеджировать лонги │ ││ └─────────────────┴──────────────────────────────────────────┘ ││ ││ Размер позиции по уверенности: ││ ────────────────────────────── ││ размер_позиции = базовый_размер × уверенность_классификации ││ ││ Если уверенность < 0.6: Уменьшить позицию или не торговать ││ Если уверенность > 0.8: Полный размер позиции ││ │└────────────────────────────────────────────────────────────────────────┘Few-Shot классификация рыночных режимов
Генерация эпизодов для обучения
# Псевдокод генерации эпизодаdef generate_episode(dataset, n_way=5, k_shot=5, n_query=10): """ Генерация одного обучающего эпизода для прототипной сети.
Args: dataset: Исторические рыночные данные с метками режимов n_way: Количество классов режимов в эпизоде k_shot: Количество support примеров на класс n_query: Количество query примеров на класс
Returns: support_set: тензор (n_way * k_shot, features) support_labels: тензор (n_way * k_shot,) query_set: тензор (n_way * n_query, features) query_labels: тензор (n_way * n_query,) """ # Выбираем n_way классов из доступных классов режимов available_classes = dataset.get_regime_classes() sampled_classes = random.sample(available_classes, n_way)
support_set = [] support_labels = [] query_set = [] query_labels = []
for class_idx, regime_class in enumerate(sampled_classes): # Получаем все примеры для этого режима class_samples = dataset.get_samples_for_regime(regime_class)
# Выбираем k_shot + n_query примеров sampled_indices = random.sample( range(len(class_samples)), k_shot + n_query )
# Разделяем на support и query support_indices = sampled_indices[:k_shot] query_indices = sampled_indices[k_shot:]
support_set.extend([class_samples[i] for i in support_indices]) support_labels.extend([class_idx] * k_shot)
query_set.extend([class_samples[i] for i in query_indices]) query_labels.extend([class_idx] * n_query)
return ( torch.stack(support_set), torch.tensor(support_labels), torch.stack(query_set), torch.tensor(query_labels) )Стратегии разметки режимов
┌────────────────────────────────────────────────────────────────────────┐│ Автоматическая разметка режимов │├────────────────────────────────────────────────────────────────────────┤│ ││ Метод 1: Квантили по доходностям ││ ─────────────────────────────── ││ Разметка по кумулятивной доходности за окно: ││ • Топ 20%: СИЛЬНЫЙ_ВОСХОДЯЩИЙ ││ • 20-40%: СЛАБЫЙ_ВОСХОДЯЩИЙ ││ • 40-60%: БОКОВИК ││ • 60-80%: СЛАБЫЙ_НИСХОДЯЩИЙ ││ • Нижние 20%: СИЛЬНЫЙ_НИСХОДЯЩИЙ ││ ││ Метод 2: Доходность с поправкой на волатильность ││ ─────────────────────────────────────────────── ││ risk_adjusted_return = return / volatility ││ Разметка по порогам с поправкой на риск ││ ││ Метод 3: Скрытая марковская модель (HMM) ││ ──────────────────────────────────────── ││ Обучаем HMM для обнаружения латентных режимов ││ Используем состояния HMM как метки ││ ││ Метод 4: На основе кластеризации ││ ───────────────────────────────── ││ Извлекаем признаки → K-means → Кластеры как режимы ││ ││ Метод 5: Ручная экспертная разметка (Золотой стандарт) ││ ─────────────────────────────────────────────────── ││ Эксперты размечают ключевые периоды рынка ││ Используется для валидации и примеров редких событий ││ │└────────────────────────────────────────────────────────────────────────┘Обработка дисбаланса классов
Финансовые рынки естественно имеют несбалансированное распределение режимов:
- Бычий/Медвежий рынки: Часто
- Обвалы: Редко, но критически важны
Стратегии для несбалансированного Few-Shot обучения:
1. Взвешенное вычисление прототипов - Даём больше веса примерам редких классов - prototype_k = weighted_mean(support_k, weights)
2. Генерация синтетических примеров - Генерируем синтетические примеры обвалов/сквизов - Используем аугментацию данных для редких режимов
3. Стратегия семплирования эпизодов - Чаще семплируем эпизоды с редкими классами - Обеспечиваем равное появление всех классов
4. Масштабирование расстояний - Масштабируем расстояния обратно пропорционально частоте класса - Редкие классы имеют меньшие расстояния (легче классифицировать)Стратегия реализации
Архитектура модулей
83_prototypical_networks_finance/├── Cargo.toml├── README.md├── README.ru.md├── readme.simple.md├── readme.simple.ru.md├── src/│ ├── lib.rs # Корень библиотеки│ ├── network/│ │ ├── mod.rs # Модуль сети│ │ ├── embedding.rs # Сеть эмбеддинга│ │ ├── prototype.rs # Вычисление прототипов│ │ └── distance.rs # Функции расстояния│ ├── training/│ │ ├── mod.rs # Модуль обучения│ │ ├── episode.rs # Генерация эпизодов│ │ ├── trainer.rs # Цикл обучения│ │ └── scheduler.rs # Планирование learning rate│ ├── data/│ │ ├── mod.rs # Модуль данных│ │ ├── bybit.rs # Клиент API Bybit│ │ ├── features.rs # Инженерия признаков│ │ ├── regime.rs # Разметка режимов│ │ └── types.rs # Типы данных│ ├── strategy/│ │ ├── mod.rs # Модуль стратегии│ │ ├── classifier.rs # Классификатор режимов│ │ ├── signals.rs # Генерация сигналов│ │ └── execution.rs # Исполнение ордеров│ └── utils/│ ├── mod.rs # Утилиты│ └── metrics.rs # Метрики производительности├── examples/│ ├── basic_prototypical.rs # Базовый пример│ ├── regime_trading.rs # Торговля по режимам│ └── backtest.rs # Бэктестинг├── python/│ ├── prototypical_network.py # Реализация на PyTorch│ ├── train.py # Скрипт обучения│ └── notebooks/│ └── example.ipynb # Jupyter notebook пример└── tests/ └── integration.rs # Интеграционные тестыКлючевые принципы проектирования
- Модульность: Каждый компонент (эмбеддинг, прототип, расстояние) независим
- Типобезопасность: Использование системы типов Rust для целостности финансовых данных
- Производительность: Эффективные batch-операции для инференса в реальном времени
- Гибкость: Поддержка разных функций расстояния и архитектур эмбеддинга
- Тестируемость: Полное покрытие unit и интеграционными тестами
Основные типы в Rust
/// Перечисление рыночных режимов#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]pub enum MarketRegime { StrongUptrend, // Сильный восходящий тренд WeakUptrend, // Слабый восходящий тренд Sideways, // Боковик WeakDowntrend, // Слабый нисходящий тренд StrongDowntrend, // Сильный нисходящий тренд}
impl MarketRegime { /// Получить торговый уклон для этого режима pub fn trading_bias(&self) -> TradingBias { match self { Self::StrongUptrend => TradingBias::StrongLong, Self::WeakUptrend => TradingBias::WeakLong, Self::Sideways => TradingBias::Neutral, Self::WeakDowntrend => TradingBias::WeakShort, Self::StrongDowntrend => TradingBias::StrongShort, } }}
/// Типы функций расстояния#[derive(Debug, Clone, Copy)]pub enum DistanceType { Euclidean, // Евклидово SquaredEuclidean, // Квадрат евклидова Cosine, // Косинусное Mahalanobis, // Махаланобиса}
/// Конфигурация прототипной сети#[derive(Debug, Clone)]pub struct PrototypicalConfig { /// Размерность эмбеддинга pub embedding_dim: usize, /// Количество классов (режимов) pub n_classes: usize, /// Количество shot для support set pub k_shot: usize, /// Количество query примеров pub n_query: usize, /// Тип функции расстояния pub distance_type: DistanceType, /// Температура для softmax pub temperature: f32, /// Размерность входных признаков pub input_dim: usize, /// Длина последовательности для временных признаков pub sequence_length: usize,}
impl Default for PrototypicalConfig { fn default() -> Self { Self { embedding_dim: 128, n_classes: 5, k_shot: 5, n_query: 15, distance_type: DistanceType::SquaredEuclidean, temperature: 1.0, input_dim: 32, sequence_length: 48, // напр., 48 часов почасовых данных } }}Интеграция с Bybit
Пайплайн сбора данных
┌────────────────────────────────────────────────────────────────────────┐│ Пайплайн данных Bybit │├────────────────────────────────────────────────────────────────────────┤│ ││ 1. Сбор исторических данных (Обучение) ││ ────────────────────────────────────── ││ GET /v5/market/kline → Свечи для нескольких таймфреймов ││ GET /v5/market/tickers → Текущее состояние рынка ││ GET /v5/market/funding/history → Исторические funding rates ││ GET /v5/market/open-interest → История открытого интереса ││ ││ 2. Данные реального времени (Инференс) ││ ────────────────────────────────────── ││ WebSocket подписка: ││ • kline.{interval}.{symbol} → Свечи в реальном времени ││ • ticker.{symbol} → Обновления цен ││ • liquidation.{symbol} → События ликвидаций ││ ││ 3. Вычисление признаков ││ ────────────────────── ││ Сырые данные → Экстрактор признаков → Нормализованные признаки ││ ││ 4. Классификация режима ││ ─────────────────────── ││ Признаки → Сеть эмбеддинга → Расстояния до прототипов → Режим ││ ││ 5. Торговый сигнал ││ ────────────────── ││ Режим + Уверенность → Размер позиции → Отправка ордера ││ │└────────────────────────────────────────────────────────────────────────┘Интеграция клиента Bybit
use crate::data::{BybitClient, Kline, FundingRate};
/// Получение и обработка данных для прототипной сетиpub async fn collect_training_data( client: &BybitClient, symbols: &[&str], start_time: u64, end_time: u64,) -> Result<TrainingDataset, BybitError> { let mut all_features = Vec::new(); let mut all_labels = Vec::new();
for symbol in symbols { // Получаем свечи let klines = client.get_klines( symbol, "1h", 1000 // Максимальный лимит ).await?;
// Получаем ставки финансирования let funding = client.get_funding_rate(symbol).await?;
// Извлекаем признаки для каждого окна for window in klines.windows(48) { // 48-часовые окна let features = extract_features(window, &funding)?; let label = compute_regime_label(window)?;
all_features.push(features); all_labels.push(label); } }
Ok(TrainingDataset::new(all_features, all_labels))}Управление рисками
Контроль рисков по режимам
┌────────────────────────────────────────────────────────────────────────┐│ Управление рисками по режимам │├────────────────────────────────────────────────────────────────────────┤│ ││ СИЛЬНЫЙ_ВОСХОДЯЩИЙ: ││ • Макс. позиция: 100% от аллокации ││ • Стоп-лосс: 5% трейлинг ││ • Тейк-профит: Дать прибыли расти ││ • Плечо: До 3x ││ ││ СЛАБЫЙ_ВОСХОДЯЩИЙ: ││ • Макс. позиция: 60% от аллокации ││ • Стоп-лосс: 3% фиксированный ││ • Тейк-профит: Цель 5-8% ││ • Плечо: До 2x ││ ││ БОКОВИК: ││ • Макс. позиция: 40% от аллокации ││ • Стоп-лосс: 2% фиксированный ││ • Тейк-профит: Границы диапазона ││ • Плечо: Только 1x ││ ││ СЛАБЫЙ_НИСХОДЯЩИЙ: ││ • Макс. позиция: 30% шорт или 20% хедж ││ • Стоп-лосс: 3% фиксированный ││ • Тейк-профит: Цель 5-8% ││ • Плечо: До 2x ││ ││ СИЛЬНЫЙ_НИСХОДЯЩИЙ: ││ • Макс. позиция: 50% шорт ││ • Стоп-лосс: 5% трейлинг ││ • Тейк-профит: Уровни паники ││ • Плечо: До 3x (с осторожностью) ││ │└────────────────────────────────────────────────────────────────────────┘Пороги уверенности классификации
/// Параметры риска на основе уверенности классификацииpub struct RiskParameters { pub position_size_multiplier: f32, pub max_leverage: f32, pub stop_loss_pct: f32, pub take_profit_pct: Option<f32>,}
impl RiskParameters { pub fn from_confidence(confidence: f32, regime: MarketRegime) -> Self { let base = Self::base_for_regime(regime);
// Масштабируем размер позиции по уверенности let size_mult = if confidence < 0.6 { 0.25 // Очень неуверенно - минимальная позиция } else if confidence < 0.75 { 0.5 // Умеренно уверенно } else if confidence < 0.9 { 0.75 // Уверенно } else { 1.0 // Очень уверенно - полная позиция };
Self { position_size_multiplier: base.position_size_multiplier * size_mult, max_leverage: base.max_leverage, stop_loss_pct: base.stop_loss_pct, take_profit_pct: base.take_profit_pct, } }}Автоматические выключатели
- Падение уверенности: Если уверенность классификации падает ниже 0.5, закрыть позиции
- Частая смена режимов: Если режим меняется > 3 раз за 4 часа, снизить экспозицию
- Всплеск расстояния: Если мин. расстояние до всех прототипов превышает порог - неизвестный режим
- Лимит просадки: Если просадка стратегии > 10%, приостановить торговлю
Метрики производительности
Метрики оценки модели
| Метрика | Описание | Цель |
|---|---|---|
| Accuracy | Общая точность классификации | > 70% |
| F1-Score (macro) | Сбалансированная точность по режимам | > 0.65 |
| F1-Score (crash) | Обнаружение обвалов специфически | > 0.80 |
| AUC-ROC | Способность различения | > 0.85 |
| Ошибка калибровки | Надёжность уверенности | < 0.10 |
Метрики торговой производительности
| Метрика | Описание | Цель |
|---|---|---|
| Коэффициент Шарпа | Доходность с поправкой на риск | > 2.0 |
| Коэффициент Сортино | С поправкой на нисходящий риск | > 2.5 |
| Макс. просадка | Наибольшая просадка от пика | < 15% |
| Доля выигрышей | Прибыльные сделки | > 55% |
| Profit Factor | Валовая прибыль / Валовой убыток | > 1.5 |
| Задержка определения режима | Время на обнаружение смены режима | < 4 часа |
Бюджет задержки
┌─────────────────────────────────────────────────┐│ Требования к задержке │├─────────────────────────────────────────────────┤│ Вычисление признаков: < 10мс ││ Forward pass эмбеддинга: < 20мс ││ Расстояние до прототипов: < 5мс ││ Классификация: < 5мс │├─────────────────────────────────────────────────┤│ Общий инференс: < 40мс │└─────────────────────────────────────────────────┘Ссылки
-
Prototypical Networks for Few-shot Learning
- Snell, J., Swersky, K., & Zemel, R. (2017)
- URL: https://arxiv.org/abs/1703.05175
-
Matching Networks for One Shot Learning
- Vinyals, O., et al. (2016)
- URL: https://arxiv.org/abs/1606.04080
-
Meta-Learning for Semi-Supervised Few-Shot Classification
- Ren, M., et al. (2018)
- URL: https://arxiv.org/abs/1803.00676
-
Meta-Learning: A Survey
- Hospedales, T., et al. (2020)
- URL: https://arxiv.org/abs/2004.05439
-
Few-Shot Learning for Financial Time Series
- Современные применения мета-обучения в трейдинге
-
Market Regime Detection
- Nystrup, P., et al. (2020). “Learning Hidden Markov Models with Persistent States”
Следующие шаги
- Простое объяснение - Версия для начинающих
- English Version - Английская версия
- Примеры кода - Рабочий код на Rust
- Python реализация - Референсная реализация на PyTorch
Глава 83 из Machine Learning for Trading