Настройка мониторинга дрифта торговой AI-модели

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Настройка мониторинга дрифта торговой AI-модели
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    854
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

Настройка мониторинга дрифта торговой AI-модели

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

Специфика дрифта в торговых системах

Structural break — резкое изменение рыночного режима (кризис, смена ДКП регулятора). Признаки становятся нерелевантными мгновенно.

Gradual concept drift — постепенное изменение паттернов: арбитражные возможности закрываются по мере того, как их начинают использовать другие участники рынка.

Seasonality shift — изменение сезонных паттернов (ликвидность меняется в праздники, квартальные экспирации опционов).

Alpha decay — естественное снижение предсказательной силы сигнала с течением времени.

Метрики мониторинга дрифта

import pandas as pd
import numpy as np
from scipy.stats import ks_2samp
from evidently.report import Report
from evidently.metric_preset import DataDriftPreset

class TradingModelDriftMonitor:
    def __init__(self, reference_window_days=60, current_window_days=5):
        self.ref_window = reference_window_days
        self.cur_window = current_window_days

    def compute_feature_drift(self, feature_df: pd.DataFrame) -> dict:
        ref_end = feature_df.index[-1] - pd.Timedelta(days=self.cur_window)
        ref_start = ref_end - pd.Timedelta(days=self.ref_window)

        reference = feature_df[ref_start:ref_end]
        current = feature_df.tail(self.cur_window * 390)  # ~390 bars/day

        drift_results = {}
        for col in feature_df.columns:
            ks_stat, p_value = ks_2samp(reference[col].dropna(), current[col].dropna())
            psi = self._compute_psi(reference[col], current[col])

            drift_results[col] = {
                'ks_stat': ks_stat,
                'ks_p_value': p_value,
                'psi': psi,
                'is_drifted': psi > 0.2 or p_value < 0.01
            }

        return drift_results

    def monitor_prediction_quality(self, predictions_df: pd.DataFrame) -> dict:
        """Мониторинг качества предсказаний по proxy-метрикам"""
        # IC (Information Coefficient) - корреляция предсказания с будущей доходностью
        ic = predictions_df['predicted_return'].corr(predictions_df['actual_return'])

        # Rolling IC за последние 20 дней vs исторический IC
        rolling_ic = predictions_df.rolling(20)['predicted_return'].corr(
            predictions_df['actual_return']
        ).iloc[-1]

        historical_ic = predictions_df['predicted_return'].corr(
            predictions_df['actual_return']
        )

        return {
            'current_ic': ic,
            'rolling_ic_20d': rolling_ic,
            'historical_ic': historical_ic,
            'ic_degradation': (historical_ic - rolling_ic) / abs(historical_ic),
            'is_critical': rolling_ic < historical_ic * 0.5  # IC упал на 50%+
        }

Мониторинг рыночных режимов

class MarketRegimeDetector:
    def __init__(self, lookback=252):
        self.lookback = lookback

    def detect_regime(self, prices: pd.Series) -> str:
        returns = prices.pct_change().dropna()
        recent = returns.tail(20)
        historical = returns.tail(self.lookback)

        # Волатильность
        recent_vol = recent.std() * np.sqrt(252)
        hist_vol = historical.std() * np.sqrt(252)

        # Тренд
        sma_short = prices.tail(10).mean()
        sma_long = prices.tail(50).mean()

        if recent_vol > hist_vol * 1.5:
            return "HIGH_VOLATILITY"  # Требует консервативных лимитов
        elif sma_short > sma_long * 1.02:
            return "UPTREND"
        elif sma_short < sma_long * 0.98:
            return "DOWNTREND"
        else:
            return "SIDEWAYS"

    def check_regime_change(self, current_regime: str, trained_regime: str) -> bool:
        """Нужно ли переобучение из-за смены режима?"""
        incompatible_pairs = [
            ("HIGH_VOLATILITY", "SIDEWAYS"),
            ("HIGH_VOLATILITY", "UPTREND"),
            ("UPTREND", "DOWNTREND"),
        ]
        return (current_regime, trained_regime) in incompatible_pairs

Алерты и эскалация

Уровень Условие Действие
Warning IC деградировал на 25% Slack уведомление, начать мониторинг чаще
Alert PSI > 0.2 на ключевых признаках PagerDuty, рассмотреть pause
Critical IC деградировал на 50% Автоматическая пауза торговли, экстренное переобучение
Emergency Структурный дрейф всех признаков Остановка торговли, ручная проверка

Мониторинг должен обновляться каждые 15-30 минут в trading hours, а не раз в день — скорость реакции критична.