Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

Свёрточные сети в финансовом анализе: от компьютерного зрения к прогнозированию рынков

Дата публикации: 23-10-2026 14:11:23

Свёрточные нейросети умеют находить закономерности в данных, но на финансовых рынках легко принять особенности волатильности за сигнал и получить модель, которая хорошо работает только на исторических котировках. Разберём, как применять CNN к временным рядам и данным ордербука, избегать утечки будущего и проверять качество прогнозов, чтобы понять, когда свёрточные архитектуры действительно полезны в финансовом анализе. Изучить метод

Основное содержимое страницы с новостью.

Свёрточные сети в финансовом анализе: от компьютерного зрения к прогнозированию рынков

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

Время на прочтение10 мин

Охват и читатели1.7K

Туториал

Привет, Хабр!

Меня зовут Андрей Бирюков. Я — независимый эксперт в области ИТ и ИБ, преподаю в учебных центрах и пишу статьи и книги. 

Мы привыкли связывать сверточные нейросети (CNN) с задачами, относящимися к компьютерному зрению, например, к поиску лиц, классификации картинок или беспилотным авто.

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

Умение «видеть» в хаосе котировок повторяющиеся структуры и извлекать эти полезные признаки в процессе обучения и есть суперсила сверточных сетей.

И сегодня мы поговорим об этом мощнейшем инструменте финансового анализа.

Псевдоизображения в финансах

Для начала давайте рассмотрим классическое определение CNN. Свёрточные нейронные сети представляют собой класс нейронных сетей, который специализируется на обработке данных с пространственной структурой, прежде всего изображений и видео.

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

094a2a71418065e169c1cefc2fffa093.png

В целом свёрточные нейросети были спроектированы под три индуктивных смещения.

  • Локальность — важные признаки формируются в окрестности точки, а не по всему входу сразу.

  • Трансляционная инвариантность — один и тот же паттерн может появиться в любом месте входа.

  • Иерархия масштабов — простые признаки комбинируются в сложные по мере углубления.

Но в финансах эти смещения будут работать частично. Давайте разберём несколько конкретных примеров использования CNN. И начнём с рассмотрения временного ряда как «псевдоизображения» (1 D‑CNN).

Перед нами стоит задача классифицировать 60-минутные окна BTC‑USD, разбив их на три класса:

  • «Рост > +0.5%».

  • «Падение < −0.5%».

  • «Боковик».

В качестве горизонта мы будем рассматривать следующие 30 минут.

Здесь самое важное — определить, что нам нужно подать на вход. Использование сырых цен — это очень плохой вариант. Дело в том, что они нестационарны, то есть абсолютный уровень и волатильность дрейфуют во времени, и CNN выучивает не форму паттерна, а конкретные значения цены в тренировочном окне, из‑за чего трансляционная инвариантность свёртки превращается из полезного свойства в источник ложных срабатываний.

Вместо этого мы используем лог‑доходности и нормализацию:

import numpy as np
import pandas as pd

def build_features(df, window=60):
    """
    df: DataFrame с колонками open, high, low, close, volume
    Возвращает массив окон признаков и метки.
    """

    # 1. Лог-доходности вместо цен (убираем нестационарность уровня)
    df['ret'] = np.log(df['close'] / df['close'].shift(1))
    df['hl_range'] = np.log(df['high'] / df['low'])
    df['vol_z'] = (df['volume'] - df['volume'].rolling(200).mean()) / df['volume'].rolling(200).std()

    # 2. Z-score по скользящему окну (адаптация к режиму волатильности)
    for col in ['ret', 'hl_range', 'vol_z']:
        roll = df[col].rolling(200)
        df[f'{col}_z'] = (df[col] - roll.mean()) / (roll.std() + 1e-8)

    features = df[['ret_z', 'hl_range_z', 'vol_z_z']].dropna().values

    # 3. Метки: forward return через 30 шагов
    fwd = np.log(df['close'].shift(-30) / df['close'])
    labels = np.where(fwd > 0.005, 2, np.where(fwd < -0.005, 0, 1))

    X, y = [], []

    for i in range(window, len(features) - 30):
        X.append(features[i - window:i].T)  # (channels, time)
        y.append(labels[i])
    return np.array(X), np.array(y)
Архитектура

При реализации CNN у нас имеются некоторые подводные камни, на которые хотелось бы обратить особое внимание.

Так, нормализация считается на скользящем окне, а не по всему датасету, потому что иначе у нас будет утечка будущего (look‑ahead bias), то есть ситуация, когда модель при обучении или оценке использует информацию, которая фактически недоступна в момент реального принятия решения.

Также метки здесь считаются через shift(-30), то есть последние 30 строк должны быть отброшены, иначе тренируемся на будущем.

И в обязательном порядке должен использоваться Z‑score по волатильности, так как без него модель выучит «высокая волатильность = сигнал», а это режимный артефакт, а не паттерн.

import torch
import torch.nn as nn
 
class TemporalCNN(nn.Module):
    def init(self, n_channels=3, n_classes=3):
        super().__init__()
        self.net = nn.Sequential(
            nn.Conv1d(n_channels, 32, kernel_size=5, padding=2),
            nn.BatchNorm1d(32),
            nn.ReLU(),
            nn.MaxPool1d(2),
            nn.Conv1d(32, 64, kernel_size=3, padding=1),
            nn.BatchNorm1d(64),
            nn.ReLU(),
            nn.MaxPool1d(2),
            nn.Conv1d(64, 64, kernel_size=3, padding=1, dilation=2),  # dilated — расширяем рецептивное поле
            nn.ReLU(),
            nn.AdaptiveAvgPool1d(1),
        )
        self.head = nn.Linear(64, n_classes)

    def forward(self, x):
        return self.head(self.net(x).squeeze(-1))

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

Причём между концом обучения и началом теста не остаётся пересечений, так как этот зазор нужен, чтобы метки обучающих примеров (которые считаются по будущим значениям, например forward return через 30 шагов) не «подглядывали» в тестовый период, а двигающееся окно обучения эмулировало реальное переобучение модели по мере поступления новых данных.

def walk_forward_splits(n_samples, n_splits=5, embargo=30):
    """Purged walk-forward CV (López de Prado)."""

    fold_size = n_samples // (n_splits + 1)
    for k in range(n_splits):
        train_end = fold_size * (k + 1)
        test_start = train_end + embargo
        test_end = min(test_start + fold_size, n_samples)
        if test_end <= test_start:
            break
        yield np.arange(0, train_end), np.arange(test_start, test_end)
2 D‑представления ряда

Главный недостаток подхода 1 D‑CNN на финансовых рядах — это ограниченное рецептивное поле и слабая работа с дальними зависимостями, так как свёртка видит только локальную окрестность. Поэтому «эхо» событий спустя сотни шагов, долгую память и режимные сдвиги она улавливает плохо.

В качестве альтернативы мы рассмотрим популярные способы превратить 1 D‑ряд в «картинку».

67055dea31ac98e70df1b0c295a9c05d.png

Начнём с STFT, или спектрограммы.

  • Плюс такого подхода в том, что мы физически осмысленно можем ловить смену частот (ускорение/замедление трендов, кластеры волатильности).

  • Минус — необходимость вручную подбирать фиксированное разрешение по частоте и времени (принцип неопределённости). Соответственно, параметр nperseg подбираем под горизонт.

import scipy.signal as ss

def stft_image(series, nperseg=32, noverlap=24):
    f, t, Z = ss.stft(series, nperseg=nperseg, noverlap=noverlap)
    return np.abs(Z)  # (freq_bins, time_bins)

Multi‑asset correlation map хорошо ловит режимные сдвиги (risk‑on/risk‑off), что бывает реально полезно для портфельных задач и для BTC как рискового актива. При этом он не работает на одном активе, а данные нужно синхронизировать.

def corr_image(returns_df, window=60):
    """Матрица корреляций по окну — 'картинка' кросс-активных связей."""
    return returns_df.iloc[-window:].corr().values

Таким образом, выбор подхода зависит от задачи:

  • Для одного актива с коротким горизонтом используем 1 D‑CNN на нормализованных доходностях.

  • В случае сильной волатильности применяем STFT + CNN.

  • Для портфельных и кросс‑активных сигналов нужны correlation maps + CNN или GNN.

GAF — академически красиво, но дорого

Использование превращения 1 D‑ряда в «картинку» плохо тем, что оно чаще всего приносит сложность без добавления информации. Например, STFT навязывает фиксированное разрешение по времени и частоте.

В качестве альтернативы можно рассмотреть метод GAF (Gramian Angular Field), в котором мы будем кодировать одномерный временной ряд в двумерное изображение. Идея в том, что исходный ряд сначала нормализуется, затем переводится в полярные координаты (угол кодирует значение, радиус — время), после чего попарные отношения между точками ряда формируют матрицу‑«картинку».

d2d6c17c9076355f2289548a5da86155.png

Это самый недооценённый сценарий, так как вместо того чтобы предсказывать цену CNN‑ом, мы используем его как энкодер признаков, а решение принимает градиентный бустинг.

import lightgbm as lgb
from sklearn.metrics import roc_auc_score
 
# Обучаем CNN на вспомогательной задаче (например, предсказание знака forward return)
cnn = TemporalCNN().cuda()
# ... обучение ...
 
# Извлекаем эмбеддинги
cnn.eval()
embeddings = []
with torch.no_grad():
    for batch in loader:
        emb = cnn.net(batch.cuda()).squeeze(-1).cpu().numpy()
        embeddings.append(emb)

X_emb = np.vstack(embeddings)  # (n, 64)

Дальше мы можем использовать стандартный пайплайн: LightGBM + walk‑forward + калибровка вероятностей.

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

На практике такая гибридная схема на BTC‑данных стабильно даёт Sharpe выше, чем end‑to‑end CNN, и, что важнее, устойчивее к смене режима.

Детектор аномалий / микроструктурных сигналов

А вот здесь CNN будет ближе всего к «честному» компьютерному зрению. Здесь наша задача заключается в том, чтобы найти на «карте» ордербука локальные структуры, такие как стенки, iceberg‑паттерны или спуфинг.

cac0fbfbc99769adfd7a1a0b2fdb771e.png

Для практической реализации нам потребуется следующий код: 

class OrderBookCNN(nn.Module):
    """Вход: (batch, 1, price_levels, time_steps) — 2D-снимок стакана."""

    def init(self):
        super().__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 16, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
            nn.Conv2d(16, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
            nn.AdaptiveAvgPool2d(1),
        )
        self.head = nn.Linear(32, 2)  # аномалия / норма

    def forward(self, x):
        return self.head(self.features(x).flatten(1))

Здесь аналогия с CV работает почти буквально, так как есть:

  • Локальность по уровням цены и по времени.

  • Трансляционная инвариантность по уровням (стенка на 5-м уровне = стенка на 15-м).

  • Иерархия «тик → паттерн → режим».

Итог: как строить пайплайн

Для построения пайплайна с использованием CNN в финансовом анализе необходимо начать с baseline без CNN, то есть использовать логистическую регрессию или LightGBM на инженерных признаках (доходности, волатильность, RSI, режимные индикаторы).

Затем добавьте 1 D‑CNN на нормализованных доходностях как отдельную модель и сравните с baseline на purge/embargo CV.

Если CNN выигрывает, то используйте её как энкодер признаков, а финальное решение отдайте бустингу. Ну а 2 D‑представления (STFT, correlation maps) добавляйте только в том случае, если у вас есть гипотеза, что именно мультимасштабная или кросс‑активная структура несёт сигнал. Иначе это будет усложнением без выигрыша.

Заключительный тезис заключается в том, что сила CNN в финансах — не в «предсказании курса биткоина», а в извлечении локальных мультимасштабных признаков, которые потом используются в более устойчивых моделях.

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

ffc0867f25279cd48822b5a11bd9701c.png

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

На бесплатных вебинарах от преподавателей Otus вы проследите путь от распознавания паттернов в данных до принятия торговых решений с помощью нейросетей — чтобы использовать машинное обучение для решения реальных задач финансового анализа.

  • 27 октября, 20:00. «Свёрточные сети: от распознавания изображений до прогнозирования курса биткоина». Записаться

  • 18 ноября, 20:00. «Нейросети в алгоритмической торговле — учим модель принимать торговые решения». Записаться

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Свёрточные сети в финансовом анализе: от компьютерного зрения к прогнозированию рынков09.0623-10-2026
2Ваш бэктест нейронки врёт на ±10 процентных пунктов08.9912-08-2026
3Тернарная нейронка на C#0913-09-2026
4Почему нейросеть ломает перспективу: FLUX 2 024 года обошёл Nano Banana 2.1 и GPT Image 2.5017.0521-10-2026
5Торговля по паттернам с точки зрения алгоритмов08.2101-08-2026
6Нейросеть-автопилот вместо 400 Playwright-тестов0707-07-2026
7Разработка метода прогнозирования стоимости бизнеса публичных компаний в рамках сравнительного подхода с использованием искусственного интеллекта04.3401-01-1970
8Делаем сайт из картинки в нейронке010.7728-05-2026
9Книга: «Анализ данных с LLM. Текст, таблицы, изображения и аудио»07.0323-06-2026
10Как я первый в Казахстане измерил ИИ видимость банков (и что из этого вышло)08.0812-08-2026

Классификация: Мнения. Схожих патентов: 0. Схожих новостей: 10. Тональность: 0. Информативность: 9.06. Источник: habr.com.