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

Глава 167: InfoNCE в трейдинге

1. Введение

InfoNCE (Information Noise-Contrastive Estimation) — это контрастивная функция потерь, впервые предложенная ван ден Оордом и соавторами в их основополагающей статье 2018 года Representation Learning with Contrastive Predictive Coding. Основная идея элегантно проста: обучать представления, заставляя модель отличать истинный (положительный) сигнал от набора отвлекающих (отрицательных) примеров. В контексте финансовых рынков этот принцип оказывается удивительно мощным.

Традиционные подходы к прогнозированию рынка с учителем требуют явных меток — будущую доходность, флаги направления, теги режимов — все они зашумлены, запаздывают и по своей природе субъективны. InfoNCE обходит эту проблему. Вместо предсказания целевого значения он обучает пространство вложений, в котором похожие рыночные условия группируются вместе, а различные — отталкиваются друг от друга. Модели никогда не нужно знать «правильный ответ»; ей достаточно понимать, какие состояния похожи друг на друга.

Почему это важно для трейдинга?

  • Рыночные режимы размыты. Чёткой границы между трендовым рынком и рынком возврата к среднему не существует. Контрастивное обучение обнаруживает эти границы из данных, а не навязывает их.
  • Метки дороги. Размечать каждую 5-минутную свечу как «бычью» или «медвежью» — упрощение. InfoNCE обучает структуру без меток.
  • Transfer learning становится естественным. Имея хороший энкодер, его можно дообучить для множества задач — генерации сигналов, управления рисками, построения портфелей — все они разделяют один и тот же базовый энкодер представлений.
  • Устойчивость к шуму. Контрастивная функция потерь по своей природе более устойчива к зашумлённым входным данным, поскольку оперирует относительными сравнениями, а не абсолютными целями.

В этой главе мы построим полную систему обучения представлений на основе InfoNCE для данных криптовалютного рынка с использованием Rust. Мы загрузим реальные OHLCV-данные с биржи Bybit, построим контрастивные пары, обучим энкодер и исследуем полученное пространство вложений.

2. Математическое обоснование

2.1 Функция потерь InfoNCE

Имея представление запроса q, один положительный ключ k+ и N-1 отрицательных ключей k-, функция потерь InfoNCE определяется как:

L = -log( exp(sim(q, k+) / τ) / Σᵢ₌₁ᴺ exp(sim(q, kᵢ) / τ) )

где:

  • sim(a, b) — функция сходства (обычно косинусное сходство)
  • τ (тау) — гиперпараметр температуры
  • Сумма в знаменателе охватывает положительный ключ и все отрицательные ключи

По сути, это softmax кросс-энтропийная функция потерь, где «правильный класс» — это положительная пара. Модель обучается назначать высокое сходство положительной паре и низкое — всем отрицательным парам.

2.2 Косинусное сходство

В качестве функции сходства мы используем косинусное сходство:

sim(a, b) = (a · b) / (‖a‖ · ‖b‖)

Косинусное сходство варьируется от -1 (противоположные направления) до +1 (одинаковое направление) и инвариантно к величине векторов. Это желательно, поскольку нас интересует направление представлений рыночного состояния, а не их масштаб.

2.3 Температурное масштабирование

Параметр температуры τ управляет «остротой» распределения:

  • Низкая τ (напр., 0.05): Модель становится очень избирательной — сильно штрафует даже небольшие отклонения от положительной пары. Это приводит к более плотным кластерам, но может затруднить обучение.
  • Высокая τ (напр., 1.0): Распределение становится более равномерным, и модель терпимее к различиям. Обучение проходит плавнее, но представления могут быть менее дискриминативными.

На практике τ ∈ [0.07, 0.5] работает хорошо. Для финансовых данных мы считаем τ = 0.1 хорошей отправной точкой, потому что рыночные состояния имеют тонкие различия, требующие достаточно резкой температуры.

2.4 Связь с взаимной информацией

Замечательное свойство InfoNCE состоит в том, что его минимизация максимизирует нижнюю границу взаимной информации между запросом и положительным ключом:

I(q; k+) ≥ log(N) - L_InfoNCE

По мере роста числа отрицательных примеров N эта граница становится более точной. Это означает, что энкодер обучает представления, сохраняющие максимум информации о взаимосвязи между парными рыночными состояниями.

3. Торговое применение

3.1 Построение контрастивных пар

Ключевое проектное решение при применении InfoNCE к трейдингу — как строить положительные и отрицательные пары. Мы определяем:

Положительные пары: Два рыночных окна, принадлежащих к похожему режиму. Конкретно:

  • Временны́е соседи: Окна, близкие по времени (в пределах нескольких свечей друг от друга). Предположение: рыночные условия меняются медленно относительно размера окна.
  • Схожая доходность: Окна с похожей реализованной доходностью на горизонте прогнозирования.
  • Совпадение волатильности: Окна с похожей реализованной волатильностью.

Отрицательные пары: Окна из разных временных периодов или режимов. На практике мы берём случайные окна из набора данных — при достаточном количестве данных случайные выборки почти наверняка принадлежат к разным режимам.

В нашей реализации мы используем временну́ю близость как основной сигнал для положительных пар: если два окна находятся в пределах настраиваемого расстояния друг от друга, они считаются положительными. Все остальные окна в батче служат отрицательными примерами.

3.2 Инженерия признаков для энкодера

Каждое рыночное окно представлено вектором признаков, извлечённых из OHLCV-данных:

ПризнакОписание
Нормализованная доходность(close - open) / open для каждой свечи
Диапазон high-low(high - low) / open — прокси для волатильности
Коэффициент объёмаОбъём относительно скользящего среднего
Коэффициент телаabs(close - open) / (high - low) — доля тела свечи
Верхняя тень(high - max(open, close)) / (high - low)
Нижняя тень(min(open, close) - low) / (high - low)

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

3.3 Архитектура энкодера

Мы используем простой полносвязный энкодер:

Вход (window_size × features) → Выпрямление → Dense(128, ReLU) → Dense(64, ReLU) → Dense(32) → L2-нормализация

Финальная L2-нормализация гарантирует, что все представления лежат на единичной гиперсфере, что является стандартной практикой при использовании косинусного сходства. 32-мерное выходное пространство достаточно компактно для интерпретации и достаточно выразительно для захвата рыночной структуры.

3.4 Использование в задачах

После обучения энкодер может применяться для:

  1. Определение режимов: Кластеризация вложений (напр., K-means) для обнаружения рыночных режимов.
  2. Поиск по сходству: По текущему рыночному состоянию найти наиболее похожие исторические состояния и изучить, что произошло далее.
  3. Извлечение признаков: Использовать вложения как входные признаки для последующей торговой модели (напр., предсказатель доходности или модель рисков).
  4. Обнаружение аномалий: Отмечать рыночные состояния, вложения которых далеки от любого центра кластера.

4. Описание реализации

4.1 Основные структуры данных

Определяем основные типы в Rust:

pub struct OhlcvCandle {
pub timestamp: u64,
pub open: f64,
pub high: f64,
pub low: f64,
pub close: f64,
pub volume: f64,
}
pub struct InfoNCEConfig {
pub temperature: f64,
pub embedding_dim: usize,
pub window_size: usize,
pub positive_range: usize,
pub num_negatives: usize,
pub learning_rate: f64,
}

4.2 Вычисление функции потерь InfoNCE

Вычисление потерь следует формуле напрямую:

pub fn infonce_loss(
query: &Array1<f64>,
positive: &Array1<f64>,
negatives: &[Array1<f64>],
temperature: f64,
) -> f64 {
let pos_sim = cosine_similarity(query, positive) / temperature;
let neg_sims: Vec<f64> = negatives
.iter()
.map(|n| cosine_similarity(query, n) / temperature)
.collect();
let max_sim = pos_sim.max(neg_sims.iter().cloned().fold(f64::NEG_INFINITY, f64::max));
let pos_exp = (pos_sim - max_sim).exp();
let neg_sum: f64 = neg_sims.iter().map(|&s| (s - max_sim).exp()).sum();
-(pos_exp / (pos_exp + neg_sum)).ln()
}

Обратите внимание на приём log-sum-exp (вычитание max_sim перед возведением в степень) для числовой стабильности.

4.3 Загрузка данных с Bybit

Мы загружаем OHLCV-данные через Bybit V5 API:

pub async fn fetch_bybit_klines(
symbol: &str,
interval: &str,
limit: usize,
) -> Result<Vec<OhlcvCandle>> {
let url = format!(
"https://api.bybit.com/v5/market/kline?category=linear&symbol={}&interval={}&limit={}",
symbol, interval, limit
);
let response: BybitResponse = reqwest::get(&url).await?.json().await?;
// Парсинг и возврат свечей...
}

4.4 Генерация контрастивных пар

Окна извлекаются из серии OHLCV. Для каждого якорного окна выбирается ближайшее окно как положительное и случайные отдалённые окна как отрицательные:

pub fn generate_contrastive_pairs(
candles: &[OhlcvCandle],
config: &InfoNCEConfig,
) -> Vec<ContrastiveSample> {
// Для каждой допустимой якорной позиции:
// 1. Извлечь окно признаков в позиции i
// 2. Выбрать положительный пример из [i-range, i+range]
// 3. Выбрать num_negatives из отдалённых позиций
// ...
}

4.5 Цикл обучения

Цикл обучения проходит по контрастивным примерам, вычисляет функцию потерь и обновляет энкодер методом градиентного спуска. Поскольку мы реализуем простую полносвязную сеть с нуля на ndarray, вычисление градиентов использует конечные разности для простоты (в продакшн-системе использовалось бы автоматическое дифференцирование).

5. Интеграция с криптоданными Bybit

Bybit V5 API предоставляет бесплатный доступ без авторизации к историческим данным свечей (kline). Используемый эндпоинт:

GET https://api.bybit.com/v5/market/kline

Параметры:

  • category: "linear" для USDT бессрочных фьючерсов
  • symbol: напр., "BTCUSDT"
  • interval: "1" (1 мин), "5" (5 мин), "15", "60", "240", "D", "W"
  • limit: Количество свечей (макс. 200)

Структура ответа:

{
"retCode": 0,
"result": {
"list": [
["timestamp", "open", "high", "low", "close", "volume", "turnover"],
...
]
}
}

Свечи возвращаются в обратном хронологическом порядке (сначала самые новые), поэтому мы разворачиваем их перед обработкой. Данные поступают в реальном времени и не требуют API-ключа, что делает их идеальными для образовательных и исследовательских целей.

Лимиты запросов: Публичный эндпоинт допускает приблизительно 10 запросов в секунду, что более чем достаточно для наших задач.

Аспекты интеграции

При интеграции данных Bybit в режиме реального времени в конвейер InfoNCE:

  1. Нормализация данных: Сырые значения OHLCV различаются на порядки между активами. Наша инженерия признаков (раздел 3.2) решает это, используя отношения вместо абсолютных значений.
  2. Пропущенные данные: Если API возвращает меньше свечей, чем запрошено, мы соответственно корректируем расчёты окон.
  3. Выравнивание временных меток: Временные метки Bybit — в миллисекундах. Мы конвертируем в секунды для единообразия.
  4. Кэширование: Для обучения рекомендуется кэшировать загруженные данные, чтобы не превышать лимиты запросов и обеспечить воспроизводимость.

6. Ключевые выводы

  1. InfoNCE предоставляет безлейбловую функцию обучения для финансовых рынков. Обучая модель отличать похожие рыночные состояния от различных, мы получаем богатые представления без необходимости явных целей прогнозирования.

  2. Параметр температуры критически важен. Слишком низкий — и модель переобучается на тривиальных различиях; слишком высокий — и она не обучает значимую структуру. Начните с τ = 0.1 для финансовых данных и подбирайте далее.

  3. Проектирование контрастивных пар — важнейшее инженерное решение. Временна́я близость — разумная отправная точка, но включение схожести доходности, совпадения волатильности или меток режимов (при их наличии) может значительно улучшить качество представлений.

  4. Rust обеспечивает гарантии производительности и безопасности, ценные для продакшн-торговых систем. Система типов отлавливает ошибки на этапе компиляции, а отсутствие сборщика мусора гарантирует предсказуемую задержку.

  5. Обученные представления универсальны. Один обученный энкодер может поддерживать определение режимов, поиск по сходству, извлечение признаков и обнаружение аномалий — что делает его фундаментальным компонентом современной торговой системы.

  6. Увеличение числа отрицательных примеров улучшает границу взаимной информации. Используйте столько отрицательных примеров, сколько позволяет оборудование. Размеры батчей 256-1024 типичны в литературе по контрастивному обучению.

  7. Комбинируйте с другими функциями потерь. InfoNCE хорошо работает как функция потерь предобучения. После предобучения дообучите энкодер с небольшим количеством размеченных данных для конкретной торговой задачи, чтобы получить лучшее из обоих подходов.


Ссылки

  • van den Oord, A., Li, Y., & Vinyals, O. (2018). Representation Learning with Contrastive Predictive Coding. arXiv:1807.03748.
  • Chen, T., Kornblith, S., Norouzi, M., & Hinton, G. (2020). A Simple Framework for Contrastive Learning of Visual Representations. ICML 2020.
  • He, K., Fan, H., Wu, Y., Xie, S., & Girshick, R. (2020). Momentum Contrast for Unsupervised Visual Representation Learning. CVPR 2020.