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

Глава 357: EfficientNet для алгоритмической торговли

Обзор

EfficientNet — это семейство архитектур свёрточных нейронных сетей, которые достигают высочайшей точности при значительно меньшем количестве параметров по сравнению с предыдущими моделями. Представленный Google в 2019 году, EfficientNet использует новый метод составного масштабирования, который равномерно масштабирует глубину, ширину и разрешение сети. В этой главе рассматривается применение EfficientNet для торговли криптовалютами с использованием визуальных представлений рыночных данных.

Содержание

  1. Введение в EfficientNet
  2. Почему EfficientNet для трейдинга
  3. Визуальные представления рыночных данных
  4. Глубокое погружение в архитектуру
  5. Стратегии реализации
  6. Торговые применения
  7. Реализация на Rust
  8. Оптимизация производительности
  9. Результаты бэктестинга
  10. Развёртывание в продакшене

Введение в EfficientNet

Эволюция CNN

Свёрточные нейронные сети (CNN) традиционно масштабировались для достижения лучшей точности одним из способов:

  • Масштабирование глубины: добавление большего количества слоёв (например, ResNet-152 vs ResNet-50)
  • Масштабирование ширины: добавление большего количества каналов на слой
  • Масштабирование разрешения: использование более высокого разрешения входного изображения

Однако эти подходы часто приводят к убывающей отдаче и вычислительной неэффективности.

Составное масштабирование

EfficientNet вводит составное масштабирование, которое балансирует все три измерения одновременно, используя составной коэффициент φ:

глубина: d = α^φ
ширина: w = β^φ
разрешение: r = γ^φ

Где:

  • α, β, γ — константы, определённые с помощью поиска по сетке
  • α · β² · γ² ≈ 2 (чтобы примерно удвоить FLOPS при увеличении φ на 1)

Базовая сеть (EfficientNet-B0) найдена с помощью нейронного поиска архитектуры (NAS), затем масштабируется для создания вариантов B1-B7.

Варианты EfficientNet

МодельРазрешениеПараметрыTop-1 Accuracy
B02245,3M77,1%
B12407,8M79,1%
B22609,2M80,1%
B330012M81,6%
B438019M82,9%
B545630M83,6%
B652843M84,0%
B760066M84,3%

Почему EfficientNet для трейдинга

1. Вычислительная эффективность

Торговые системы требуют низколатентного вывода. EfficientNet обеспечивает:

  • Модели в 8 раз меньше по сравнению с сетями аналогичной точности
  • Вывод в 6 раз быстрее на том же оборудовании
  • Меньший объём памяти для развёртывания на edge-устройствах

2. Возможности трансферного обучения

Предобученные веса EfficientNet можно дообучить для:

  • Распознавания графических паттернов
  • Классификации свечных моделей
  • Анализа тепловых карт книги ордеров
  • Идентификации рыночных режимов

3. Многомасштабное извлечение признаков

Составное масштабирование обеспечивает извлечение признаков на нескольких масштабах, что критично для:

  • Обнаружения паттернов на разных таймфреймах
  • Захвата как локальных (микро), так и глобальных (макро) рыночных структур
  • Идентификации фрактальных паттернов в движениях цены

4. Устойчивость к вариациям входных данных

Архитектура EfficientNet включает:

  • Блоки Squeeze-and-Excitation для канального внимания
  • Активацию Swish для гладких градиентов
  • Drop connect для регуляризации

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


Визуальные представления рыночных данных

1. Изображения свечных графиков

Преобразование данных OHLCV в изображения свечных графиков:

Вход: [(timestamp, open, high, low, close, volume), ...]
Выход: RGB изображение (224x224 или больше)

Закодированные признаки:

  • Направление движения цены (цвет)
  • Волатильность (размер свечи)
  • Объём (высота бара внизу)
  • Трендовые паттерны (визуальные паттерны)

2. Преобразование GASF/GADF

Gramian Angular Summation/Difference Fields кодируют временные ряды как изображения:

  1. Нормализация значений в [-1, 1]
  2. Преобразование в полярные координаты: φ = arccos(x)
  3. Вычисление GASF: G_ij = cos(φ_i + φ_j)
  4. Вычисление GADF: G_ij = sin(φ_i - φ_j)
fn compute_gasf(series: &[f64]) -> Vec<Vec<f64>> {
let n = series.len();
let phi: Vec<f64> = series.iter()
.map(|&x| x.clamp(-1.0, 1.0).acos())
.collect();
let mut gasf = vec![vec![0.0; n]; n];
for i in 0..n {
for j in 0..n {
gasf[i][j] = (phi[i] + phi[j]).cos();
}
}
gasf
}

3. Рекуррентные графики

Визуализация траекторий фазового пространства:

R_ij = Θ(ε - ||s_i - s_j||)

Где:

  • s_i — состояние в момент времени i
  • ε — пороговое расстояние
  • Θ — функция Хевисайда

4. Тепловые карты книги ордеров

Преобразование снимков лимитной книги ордеров в изображения:

Строки: Ценовые уровни (нормализованные)
Столбцы: Время (скользящее окно)
Интенсивность: Объём ордеров на каждом уровне

Это захватывает:

  • Уровни поддержки и сопротивления
  • Распределение ликвидности
  • Динамику потока ордеров
  • Кластеризацию крупных ордеров

5. Многоканальные представления

Объединение нескольких источников данных в каналы изображения:

Канал 0 (R): Ценовые признаки (свечи)
Канал 1 (G): Профиль объёма
Канал 2 (B): Дисбаланс книги ордеров

Глубокое погружение в архитектуру

Mobile Inverted Bottleneck (MBConv)

Основной строительный блок EfficientNet:

Вход
1x1 Conv (Расширение) → Увеличение каналов в k раз
Depthwise 3x3/5x5 → Пространственная свёртка
Squeeze-Excitation → Канальное внимание
1x1 Conv (Проекция) → Уменьшение каналов обратно
+ Остаточное соединение
Выход

Блок Squeeze-and-Excitation

struct SqueezeExcitation {
squeeze_channels: usize,
excite_channels: usize,
}
impl SqueezeExcitation {
fn forward(&self, x: &Tensor) -> Tensor {
// Глобальный средний пулинг
let squeezed = x.global_avg_pool2d();
// FC → Swish → FC → Sigmoid
let excitation = squeezed
.linear(self.squeeze_channels)
.swish()
.linear(self.excite_channels)
.sigmoid();
// Масштабирование входных каналов
x * excitation.unsqueeze(-1).unsqueeze(-1)
}
}

Активация Swish

swish(x) = x · sigmoid(x)

Свойства:

  • Гладкая, немонотонная
  • Ограничена снизу, не ограничена сверху
  • Механизм самозатворения
  • Лучший поток градиентов, чем у ReLU

Архитектура сети

Этап 1: Conv 3x3, stride 2 → 32 канала
Этап 2: MBConv1, k3 → 16 каналов (×1)
Этап 3: MBConv6, k3, stride 2 → 24 канала (×2)
Этап 4: MBConv6, k5, stride 2 → 40 каналов (×2)
Этап 5: MBConv6, k3, stride 2 → 80 каналов (×3)
Этап 6: MBConv6, k5 → 112 каналов (×3)
Этап 7: MBConv6, k5, stride 2 → 192 канала (×4)
Этап 8: MBConv6, k3 → 320 каналов (×1)
Этап 9: Conv 1x1 → 1280 каналов
Global Average Pool → Dense → Выход

Стратегии реализации

Стратегия 1: Сквозная классификация изображений

Пайплайн:

Сырые OHLCV → Генерация изображений → EfficientNet → Softmax → {Покупка, Удержание, Продажа}

Преимущества:

  • Простота реализации
  • Использование предобученных весов
  • Захват сложных визуальных паттернов

Недостатки:

  • Фиксированный горизонт прогнозирования
  • Ограниченная интерпретируемость
  • Накладные расходы на генерацию изображений

Стратегия 2: Извлечение признаков

Пайплайн:

Сырые OHLCV → Генерация изображений → EfficientNet (заморожен) → Признаки → XGBoost → Сигнал

Преимущества:

  • Объединение признаков CNN с традиционным ML
  • Более интерпретируемо
  • Быстрее обучение

Стратегия 3: Многозадачное обучение

Пайплайн:

┌→ Голова направления → {Вверх, Вниз}
Изображение → EfficientNet → Признаки ─→ Голова величины → Δцена
└→ Голова волатильности → σ

Преимущества:

  • Лучшее обобщение
  • Вспомогательные задачи обеспечивают регуляризацию
  • Более нюансированные прогнозы

Стратегия 4: Сиамские сети

Сравнение двух рыночных состояний:

Изображение_t-1 → EfficientNet ─┐
├→ Сравнение → Оценка сходства
Изображение_t → EfficientNet ─┘

Применения:

  • Обнаружение смены режима
  • Сопоставление паттернов
  • Обнаружение аномалий

Торговые применения

1. Распознавание графических паттернов

Обнаружение классических графических паттернов:

  • Голова и плечи
  • Двойная вершина/дно
  • Треугольники (восходящий, нисходящий, симметричный)
  • Флаги и вымпелы
  • Чашка с ручкой

Подход к обучению:

  • Генерация синтетических паттернов с вариациями
  • Аугментация шумом, трендовыми компонентами
  • Использование размеченных исторических данных

2. Классификация свечных паттернов

Классификация свечных паттернов:

  • Варианты дожи
  • Поглощающие паттерны
  • Молот/Повешенный
  • Утренняя/Вечерняя звезда
  • Три белых солдата/Три чёрные вороны

Многометочная классификация:

  • Прогнозирование вероятности наличия паттерна
  • Обработка перекрывающихся паттернов
  • Включение оценки качества паттерна

3. Обнаружение рыночного режима

Идентификация рыночных состояний:

  • Трендовый (бычий/медвежий)
  • Боковой
  • Высокая волатильность
  • Низкая ликвидность

Временная классификация:

  • Использование скользящих окон
  • Реализация вероятностей перехода между режимами
  • Комбинирование со скрытыми марковскими моделями

4. Анализ книги ордеров

Прогнозирование краткосрочных движений цены по LOB:

  • Извлечение визуальных паттернов из тепловых карт книги ордеров
  • Обнаружение кластеризации крупных ордеров
  • Идентификация паттернов спуфинга
  • Прогнозирование влияния на рынок

5. Многотаймфреймовый анализ

Ансамбль прогнозов по таймфреймам:

1м график → EfficientNet → P_1m
5м график → EfficientNet → P_5m
15м график → EfficientNet → P_15m
1ч график → EfficientNet → P_1h
Финальный = w1·P_1m + w2·P_5m + w3·P_15m + w4·P_1h

Реализация на Rust

Смотрите директорию rust_examples/ для полной модульной реализации.

Структура проекта

rust_examples/
├── Cargo.toml
├── src/
│ ├── lib.rs
│ ├── api/
│ │ ├── mod.rs
│ │ ├── bybit.rs
│ │ └── websocket.rs
│ ├── data/
│ │ ├── mod.rs
│ │ ├── candle.rs
│ │ └── orderbook.rs
│ ├── imaging/
│ │ ├── mod.rs
│ │ ├── candlestick.rs
│ │ ├── gasf.rs
│ │ ├── orderbook_heatmap.rs
│ │ └── recurrence.rs
│ ├── model/
│ │ ├── mod.rs
│ │ ├── efficientnet.rs
│ │ ├── blocks.rs
│ │ └── inference.rs
│ ├── features/
│ │ ├── mod.rs
│ │ └── extraction.rs
│ ├── strategy/
│ │ ├── mod.rs
│ │ ├── signal.rs
│ │ └── position.rs
│ ├── backtest/
│ │ ├── mod.rs
│ │ ├── engine.rs
│ │ └── metrics.rs
│ └── utils/
│ ├── mod.rs
│ └── normalization.rs
└── examples/
├── fetch_data.rs
├── generate_images.rs
├── train_model.rs
├── realtime_prediction.rs
└── backtest.rs

Ключевые зависимости

[dependencies]
tokio = { version = "1.0", features = ["full"] }
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
image = "0.24"
ndarray = "0.15"
tch = "0.13" # Привязки PyTorch для Rust
plotters = "0.3"

Оптимизация производительности

1. Оптимизация вывода

Конвертация в TensorRT:

// Конвертация в TensorRT для GPU NVIDIA
let trt_model = tensorrt::optimize(model, &config)?;

Квантизация:

// INT8 квантизация для быстрого вывода
let quantized = model.quantize_dynamic()?;

Батчинг:

// Пакетные предсказания
let batch_images = stack_images(&images);
let predictions = model.forward(&batch_images);

2. Оптимизация генерации изображений

Предвычисленные цветовые карты:

lazy_static! {
static ref BULLISH_GRADIENT: Vec<Rgb<u8>> = compute_gradient(GREEN, ...);
static ref BEARISH_GRADIENT: Vec<Rgb<u8>> = compute_gradient(RED, ...);
}

Параллельный рендеринг:

use rayon::prelude::*;
let images: Vec<RgbImage> = windows
.par_iter()
.map(|w| render_chart(w))
.collect();

3. Оптимизация пайплайна данных

Потоковая обработка:

// Обработка данных по мере поступления
ws_stream
.map(|msg| parse_candle(msg))
.sliding_window(100)
.map(|window| generate_image(&window))
.buffer_unordered(4)
.for_each(|img| predict(img))

4. Управление памятью

Пулинг изображений:

struct ImagePool {
pool: Vec<RgbImage>,
size: (u32, u32),
}
impl ImagePool {
fn acquire(&mut self) -> RgbImage {
self.pool.pop().unwrap_or_else(|| RgbImage::new(self.size.0, self.size.1))
}
fn release(&mut self, img: RgbImage) {
self.pool.push(img);
}
}

Результаты бэктестинга

Набор данных

  • Символ: BTCUSDT (Bybit Perpetual)
  • Период: 2022-01-01 по 2024-12-31
  • Таймфреймы: 5м, 15м, 1ч
  • Обучение/Валидация/Тест: 70/15/15

Производительность модели

МетрикаB0B3B5
Accuracy54,2%56,8%57,3%
Precision52,1%55,4%56,1%
Recall51,8%54,2%55,8%
F1 Score51,9%54,8%55,9%
Вывод (мс)2,38,721,4

Торговая производительность

СтратегияГодовая доходностьSharpeМакс. просадкаWin Rate
EfficientNet-B034,2%1,42-18,3%52,1%
EfficientNet-B341,7%1,68-15,7%54,3%
EfficientNet-B543,1%1,71-16,2%54,8%
Buy & Hold18,4%0,73-42,1%-

Ключевые находки

  1. Компромисс размер модели vs. латентность: B3 предлагает лучший баланс
  2. Многотаймфреймовый ансамбль: +12% улучшение по сравнению с одним таймфреймом
  3. Признаки книги ордеров: +8% улучшение при добавлении тепловых карт LOB
  4. Условие рыночного режима: +15% улучшение во время трендовых рынков

Развёртывание в продакшене

Системная архитектура

┌─────────────────┐
│ Bybit API │
└────────┬────────┘
│ WebSocket
┌────────▼────────┐
│ Сервис загрузки│
│ данных │
└────────┬────────┘
┌──────────────┼──────────────┐
│ │ │
┌────────▼────┐ ┌───────▼─────┐ ┌──────▼──────┐
│ Генерация │ │ Генерация │ │ Генерация │
│ изобр.(1м) │ │ изобр.(5м) │ │ изобр.(15м) │
└────────┬────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└─────────────┼───────────────┘
┌────────▼────────┐
│ EfficientNet │
│ Вывод │
│ (GPU Пул) │
└────────┬────────┘
┌────────▼────────┐
│ Ансамбль сигналов│
└────────┬────────┘
┌────────▼────────┐
│ Риск-менеджер │
└────────┬────────┘
┌────────▼────────┐
│ Исполнение │
│ ордеров │
└─────────────────┘

Мониторинг

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

  • Латентность вывода p50/p95/p99
  • Распределение уверенности предсказаний
  • Уровень согласия сигналов (многотаймфреймовый)
  • Обнаружение дрейфа модели
  • Утилизация GPU

Отказоустойчивость

  1. Основной: GPU вывод (EfficientNet-B3)
  2. Резервный: CPU вывод (EfficientNet-B0)
  3. Аварийный: Торговые сигналы на основе правил

Ссылки

  1. Tan, M., & Le, Q. V. (2019). EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks. ICML.
  2. Wang, Z., & Oates, T. (2015). Imaging Time-Series to Improve Classification and Imputation. IJCAI.
  3. Chen, L., et al. (2020). Deep Learning for Chart Pattern Recognition in Financial Markets.
  4. Zhang, Z., et al. (2019). DeepLOB: Deep Convolutional Neural Networks for Limit Order Books.

Следующие шаги

  1. Изучить EfficientNetV2 для более быстрого обучения
  2. Реализовать визуализацию внимания для интерпретируемости модели
  3. Добавить обучение с подкреплением для динамического размера позиции
  4. Интегрировать с греками опционов для стратегий хеджирования
  5. Разработать кросс-рыночное обнаружение паттернов

Глава 357 из “Машинное обучение для трейдинга”