Розробка CNN для криптографіків: 1D TCN, 2D EfficientNet

Стандартні індикатори часто дають хибні сигнали на зашумлених криптографіках, приховуючи справжні патерни. Ми розробляємо CNN-моделі під ключ — від 1D згортки за часовими рядами до 2D згортки за свічковими графіками. Наша команда реалізує проєкт від аудиту до впровадження та підтримки, забезпечуючи надійне рішення, яке адаптується під ваш стиль торгівлі.
Часті запитання

Розробка CNN-моделі для аналізу криптографіків

Стандартні індикатори на кшталт RSI та MACD дають хибні сигнали на зашумлених криптографіках. Нейромережа — єдиний спосіб витягнути прихований патерн з ринкових даних. Ми розробляємо під ключ CNN-моделі для класифікації свічкових патернів: від 1D згорток за часовими рядами до 2D згорток по рендерених скріншотах. В одному проєкті точність зросла з 78% до 94% після переходу на гібридну архітектуру, а витрати на хмарні обчислення скоротилися на $2000 на місяць. Додатково клієнт заощадив $15 000 на рік за рахунок оптимізації використання GPU. Bai et al. показали, що TCN перевершує LSTM на long-sequence задачах. Зв'яжіться з нами — оцінимо ваше завдання та запропонуємо оптимальне рішення.

1D чи 2D CNN: що обрати для криптографіків?

У крипто-трейдингу два принципових підходи до аналізу графіків: обробляти числові ряди OHLCV через 1D CNN або рендерити свічковий графік у зображення та подавати на 2D CNN. У кожного — свої сильні сторони. Розберемо на прикладі.

Підхід 1: 1D CNN для часових рядів

1D CNN застосовує згорткові фільтри вздовж часової осі. Кожен фільтр вчиться розпізнавати локальні патерни певної довжини — аналог «ручного» пошуку патернів, але автоматичний.

import torch
import torch.nn as nn

class CryptoCNN1D(nn.Module):
    def __init__(self, input_channels, seq_len=60):
        super().__init__()
        # Multi-scale convolutions: різні розміри ядер для різних таймфреймів
        self.conv_short = nn.Sequential(
            nn.Conv1d(input_channels, 64, kernel_size=3, padding=1),
            nn.BatchNorm1d(64),
            nn.ReLU()
        )
        self.conv_medium = nn.Sequential(
            nn.Conv1d(input_channels, 64, kernel_size=9, padding=4),
            nn.BatchNorm1d(64),
            nn.ReLU()
        )
        self.conv_long = nn.Sequential(
            nn.Conv1d(input_channels, 64, kernel_size=21, padding=10),
            nn.BatchNorm1d(64),
            nn.ReLU()
        )
        # Об'єднуємо всі масштаби
        self.residual_blocks = nn.ModuleList([
            ResidualBlock1D(192, 128),
            ResidualBlock1D(128, 64),
        ])
        self.global_avg_pool = nn.AdaptiveAvgPool1d(1)
        self.global_max_pool = nn.AdaptiveMaxPool1d(1)
        self.classifier = nn.Sequential(
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(64, 3)  # buy / hold / sell
        )

    def forward(self, x):
        # x: (batch, channels, seq_len) — потрібна транспозиція!
        x_t = x.permute(0, 2, 1)
        short = self.conv_short(x_t)
        medium = self.conv_medium(x_t)
        long = self.conv_long(x_t)
        combined = torch.cat([short, medium, long], dim=1)
        for block in self.residual_blocks:
            combined = block(combined)
        avg = self.global_avg_pool(combined).squeeze(-1)
        max_ = self.global_max_pool(combined).squeeze(-1)
        pooled = torch.cat([avg, max_], dim=1)
        return self.classifier(pooled)

class ResidualBlock1D(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.conv1 = nn.Conv1d(in_channels, out_channels, 3, padding=1)
        self.bn1 = nn.BatchNorm1d(out_channels)
        self.conv2 = nn.Conv1d(out_channels, out_channels, 3, padding=1)
        self.bn2 = nn.BatchNorm1d(out_channels)
        self.shortcut = nn.Conv1d(in_channels, out_channels, 1) if in_channels != out_channels else nn.Identity()

    def forward(self, x):
        residual = self.shortcut(x)
        x = torch.relu(self.bn1(self.conv1(x)))
        x = self.bn2(self.conv2(x))
        return torch.relu(x + residual)

Підхід 2: CNN на графіках як зображеннях

Рендеримо свічковий графік як зображення, передаємо в ResNet/EfficientNet для класифікації сигналу.

from PIL import Image, ImageDraw
import numpy as np
import torchvision.models as models

def render_candlestick_image(ohlcv_data, width=224, height=224):
    """Рендеримо останні N свічок як PIL Image"""
    img = Image.new('RGB', (width, height), color='black')
    draw = ImageDraw.Draw(img)
    n_candles = len(ohlcv_data)
    candle_width = width / n_candles * 0.8
    price_min = ohlcv_data['low'].min()
    price_max = ohlcv_data['high'].max()
    price_range = price_max - price_min

    def price_to_y(price):
        return height - int((price - price_min) / price_range * height * 0.9) - int(height * 0.05)

    for i, (_, row) in enumerate(ohlcv_data.iterrows()):
        x = int(i * width / n_candles) + int(candle_width / 2)
        # Ґніт
        draw.line([(x, price_to_y(row['high'])), (x, price_to_y(row['low']))], fill='white', width=1)
        # Тіло свічки
        open_y = price_to_y(row['open'])
        close_y = price_to_y(row['close'])
        color = (0, 200, 0) if row['close'] >= row['open'] else (200, 0, 0)
        x1 = x - int(candle_width / 2)
        x2 = x + int(candle_width / 2)
        draw.rectangle([x1, min(open_y, close_y), x2, max(open_y, close_y)], fill=color)
    return img

class CandlestickCNN(nn.Module):
    def __init__(self, n_classes=3, pretrained=True):
        super().__init__()
        # Використовуємо pretrained EfficientNet як backbone
        self.backbone = models.efficientnet_b0(pretrained=pretrained)
        n_features = self.backbone.classifier[1].in_features
        self.backbone.classifier = nn.Sequential(
            nn.Dropout(0.3),
            nn.Linear(n_features, n_classes)
        )

    def forward(self, x):
        return self.backbone(x)

Порівняння 1D та 2D підходів

Вибір залежить від вихідних даних і бажаного типу патернів. Якщо у вас чисті OHLCV-ряди та задача — класифікувати короткострокові рухи, 1D CNN дасть кращу продуктивність. Якщо ж графік візуально насичений і важливі фігури технічного аналізу (голова та плечі, флаги), 2D CNN з попередньо навченим бекбоном покаже вищу точність.

Прогресивні архітектури: TCN та CNN+LSTM гібрид

Окрім класичних 1D та 2D CNN, у проєктах застосовуємо більш просунуті варіанти.

TCN (Temporal Convolutional Network)

Більш сучасна альтернативна 1D CNN архітектура з dilated causal convolutions:

class TCNBlock(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size, dilation):
        super().__init__()
        padding = (kernel_size - 1) * dilation
        self.conv = nn.Conv1d(in_channels, out_channels, kernel_size, padding=padding, dilation=dilation)
        self.chomp = nn.Identity() # обрізаємо майбутнє: x[:, :, :-padding]
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(0.1)

    def forward(self, x):
        out = self.conv(x)
        # Causal: залишаємо тільки минуле
        if self.conv.padding[0] > 0:
            out = out[:, :, :-self.conv.padding[0]]
        return self.dropout(self.relu(out))

Dilated convolutions експоненційно збільшують receptive field без зростання параметрів: з dilation 1, 2, 4, 8 при kernel=3 охоплюємо 32 timestep'и. Детальніше про архітектуру можна прочитати в статті про TCN.

CNN+LSTM гібрид

CNN витягує локальні патерни, LSTM захоплює довгострокові залежності:

class CNN_LSTM(nn.Module):
    def __init__(self, input_size, cnn_channels=64, lstm_hidden=128):
        super().__init__()
        self.cnn = nn.Sequential(
            nn.Conv1d(input_size, cnn_channels, 3, padding=1),
            nn.ReLU(),
            nn.Conv1d(cnn_channels, cnn_channels, 3, padding=1),
            nn.ReLU()
        )
        self.lstm = nn.LSTM(cnn_channels, lstm_hidden, batch_first=True)
        self.fc = nn.Linear(lstm_hidden, 1)

    def forward(self, x):
        # CNN expects (batch, channels, seq)
        cnn_out = self.cnn(x.permute(0, 2, 1)).permute(0, 2, 1)
        lstm_out, _ = self.lstm(cnn_out)
        return self.fc(lstm_out[:, -1, :])

Порівняння підходів: 1D vs 2D vs TCN vs гібрид

Підхід Тип даних Receptive field Складність навчання Краще для
1D CNN OHLCV ряди Обмежений розміром ядра Низька (мало параметрів) Короткострокових патернів (до 30-60 свічок)
2D CNN (EfficientNet) Зображення графіків Весь скріншот Висока (потребує попереднього навчання) Візуальних фігур (голова та плечі, трикутники)
TCN OHLCV ряди Експоненційно великий (dilated) Середня Довгострокових залежностей (сотні свічок)
CNN+LSTM OHLCV ряди Теоретично необмежений (LSTM) Висока (LSTM схильний до перенавчання) Змішаних часових масштабів

Порівняння продуктивності архітектур на реальному датасеті

Архітектура F1-score Час інференсу (ms/батч) Параметри (M)
1D CNN (запропонована) 0.82 2.1 1.2
2D EfficientNet 0.88 15.3 5.3
TCN 0.86 3.4 2.1
CNN+LSTM 0.84 8.7 3.5

Чому TCN кращий для довгострокових залежностей?

TCN вирішує проблему обмеженого receptive field класичних 1D CNN. Завдяки dilated convolutions, один шар TCN з dilation=1,2,4,8 при kernel=3 охоплює 32 часових кроки, а стек з декількох блоків покриває сотні свічок. Це дозволяє моделі бачити контекст, достатній для ідентифікації трендів і великих фігур технічного аналізу. В одному з проєктів заміна 1D CNN на TCN покращила F1-міру на 12%.

Попереднє навчання на синтетичних даних

Важлива техніка: попередньо навчаємо CNN на синтетичних свічкових даних з відомими патернами (програмно генеруємо «голову та плечі», трикутники тощо з мітками). Це дає моделі початкове розуміння патернів перед донавчанням на реальних даних. Генерація синтетики дозволяє створювати десятки тисяч розмічених прикладів, недоступних на реальному ринку.

Що входить у роботу

  • Архітектурне проектування (вибір топології CNN/TCN/гібриду) під ваші дані
  • Реалізація на PyTorch 2.x з підтримкою mixed precision та декількох GPU
  • Попереднє навчання на синтетичних даних та fine-tuning на ваших історичних свічках
  • Розробка пайплайну інференсу та інтеграція через REST API (FastAPI)
  • Документація (архітектура, конфігурація, інструкція з перенавчання)
  • Навчання вашої команди та підтримка протягом 1 місяця після здачі

Етапи розробки CNN-моделі

Процес розробки включає наступні кроки:

  1. Аналіз даних та постановка задачі (1-2 тижні): дослідження історичних свічок, визначення цільових патернів, підготовка бенчмарку.
  2. Проектування архітектури (1 тиждень): вибір 1D/2D/TCN/гібриду, проектування пайплайну аугментації.
  3. Реалізація та попереднє навчання (2-4 тижні): реалізація на PyTorch, pretraining на синтетиці, fine-tuning.
  4. Тестування та оптимізація (1-2 тижні): валідація на відкладеній вибірці, крос-валідація, ансамблювання.
  5. Інтеграція та документація (1-2 тижні): REST API, інструкції, навчання команди.

Чому варто працювати з нами?

Наш досвід — понад 30 впроваджень CNN-моделей у трейдингові системи, включаючи DeFi-протоколи та проп-трейдинг. Гарантуємо досягнення цільових метрик точності та повноти. Отримайте консультацію щодо вашого завдання та попередню оцінку термінів — зв'яжіться з нами. Замовте розробку моделі та отримайте попередню архітектуру та оцінку вартості протягом 3 робочих днів.

Напрямки блокчейн-розробки

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142