# PLAN: Feature Engineering Overhaul

> **Дата:** 2026-06-04
> **Цель:** Исправить фундаментальную проблему OOS деградации модели через расширение и улучшение признаков

---

## 1. Проблема

Текущая модель использует **15 технических индикаторов** → ~226 признаков. После anti-overfitting ретрейна (hidden=64, dropout=0.4, walk-forward=4):

| Метрика | IS (2023-24) | OOS (2024-25) | Δ |
|---------|:---:|:---:|:---:|
| **Total PnL** | +492K | **-1,163K** | **-1,656K** 🔴 |
| **Positive tickers** | 8/12 | **1/12** | -7 |
| **Avg WR** | 45.9% | **39.6%** | -6.3% |

Research показывает, что оптимальное количество признаков для финансового ML — **30-80 фич** с multi-window, interaction, temporal и cross-asset компонентами. Наш слабый сигнал (AUC~0.57) теряется в шуме OOS из-за недостаточной информативности признаков.

---

## 2. Ключевые изменения

| Компонент | Текущий | Новый | Файл |
|-----------|---------|-------|------|
| **Feature set** | 15 indicators | **~40 indicators** (multi-window, interaction, temporal) | `ai/features.py` |
| **Scaler** | `StandardScaler` | **`RobustScaler`** (устойчив к выбросам) | `ai/trainer_v2.py` |
| **Feature selection** | Нет | **LASSO** (сократить с ~500 до ~100) | `ai/features.py` (новый модуль) |
| **Input size модели** | 226 | **~500** (до LASSO), **~100** (после) | адаптируется автоматически |
| **CONTEXT_WINDOW** | 24 | **24** (оставить) | — |

---

## 3. Новые категории признаков

### 3.1 Momentum (расширить: 6→10)

| Признак | Формула | Диапазон | Экономический смысл |
|---------|---------|:--------:|---------------------|
| `rsi_14` | (существующий) | [0, 100] | Сила/слабость тренда |
| `rsi_centered` | RSI − 50 | [-50, +50] | Симметричная перекупленность |
| `macd_norm` | MACD / Close | ~[-0.05, 0.05] | Scale-free momentum |
| `macd_hist_sign` | sign(hist) | {-1, 0, +1} | Направление ускорения |
| `stoch_k` | (существующий) | [0, 100] | Ценовая позиция в range |
| `stoch_kd_diff` | %K − %D | [-100, +100] | Crossover signal |
| `adx_14` | (существующий) | [0, 100] | Сила тренда |
| `adx_directional_ratio` | (DM+−DM−)/(DM++DM−) | [-1, +1] | Направление тренда |
| `momentum_5` | (существующий) | unbounded | Скорость изменения |
| `williams_r` | Williams %R | [-100, 0] | Перекупленность (иная перспектива) |

### 3.2 Volatility (расширить: 1→4)

| Признак | Формула | Эффективность | Смысл |
|---------|--------|:-------------:|-------|
| `atr_14` | (существующий) | 1× | Базовый ATR |
| `parkinson_vol` | HL range estimator | **~5×** | Бестрендовая волатильность |
| `garman_klass_vol` | OHLC estimator | **~8×** | Самая эффективная |
| `bb_width_norm` | (Upper−Lower)/Mid | — | Ширина полос Боллинджера |
| `vol_percentile_252` | percentile_rank(atr, 252) | — | Режим волатильности (низкая/высокая) |

### 3.3 Trend/Moving Average (новые: 0→6)

| Признак | Формула | Диапазон | Смысл |
|---------|---------|:--------:|-------|
| `dist_to_sma_5` | (Close / SMA_5) − 1 | ~[-0.05, 0.05] | Краткосрочный тренд |
| `dist_to_sma_24` | (Close / SMA_24) − 1 | ~[-0.10, 0.10] | Среднесрочный тренд |
| `dist_to_sma_50` | (Close / SMA_50) − 1 | ~[-0.15, 0.15] | Долгосрочный тренд |
| `zscore_24` | (Close − SMA_24) / Std_24 | ~[-3, +3] | Стандартизованная позиция |
| `dist_to_high_24` | (Close / max(High,24)) − 1 | zawsze ≤ 0 | Отступ от хая |
| `dist_to_low_24` | (Close / min(Low,24)) − 1 | zawsze ≥ 0 | Отступ от лоя |

### 3.4 Interaction (новые: 0→5)

**Важно:** Research показывает, что divergence между двумя коррелированными сигналами часто несёт больше информации, чем сами сигналы.

| Признак | Формула | Смысл |
|---------|---------|-------|
| `trend_over_vol` | dist_to_sma_20 / hist_vol_20d | Сильный тренд в спокойном рынке = надёжнее |
| `momentum_regime` | dist_to_sma_5 − dist_to_sma_50 | Бычий/медвежий режим |
| `vol_adj_return_1d` | return_lag_1d / hist_vol_20d | Bar-level Sharpe ratio |
| `trend_volume_confirm` | dist_to_sma_20 × volume_ratio_lag_1d | Объём подтверждает тренд |
| `rsi_trend_divergence` | (RSI−50) × dist_to_sma_20 | RSI-тренд дивергенция (уже есть) |

### 3.5 Temporal (улучшить: 3→6)

| Признак | Энкодинг | Период | Почему не raw |
|---------|----------|:------:|---------------|
| `hour` | (существующий) | 24 | Время сессии |
| `dow_sin` / `dow_cos` | sin/cos | 5 | Пн↔Пт должны быть соседями |
| `hour_sin` / `hour_cos` | sin/cos | 24 | 23:00↔00:00 должны быть соседями |
| `is_month_end` | binary | — | Эффект конца месяца |
| `is_quarter_end` | binary | — | Институциональная перебалансировка |

---

## 4. Feature Selection Pipeline

После расчёта ~500 raw признаков (OHLCV × 25 + returns × 25 + indicators × 3 + новые):

1. **Шаг 1: LASSO** (L1-регуляризация)
   - Цель: отобрать ~50-100 фич с ненулевыми коэффициентами
   - Alpha подбирается по TimeSeriesSplit CV
   - Имплементация: `sklearn.linear_model.LassoCV`

2. **Шаг 2: Удаление мультиколлинеарности**
   - VIF < 5 или correlation < 0.95
   - Не авто-удаление, а диагностика + ручной контроль

3. **Итоговый набор:** ~60-100 признаков

---

## 5. Scaler: StandardScaler → RobustScaler

| Scaler | Формула | Чувствительность к выбросам |
|--------|---------|:--------------------------:|
| `StandardScaler` | (x − mean) / std | **Высокая** — 1 выброс меняет mean/std |
| **`RobustScaler`** | **(x − median) / IQR** | **Низкая** — median/IQR устойчивы к выбросам |

Финансовые данные содержат много выбросов (flash crashes, gap openings, news spikes). RobustScaler даёт более стабильные фичи в таких условиях.

---

## 6. Пошаговый план реализации

| # | Шаг | Файлы | Ожидаемое время |
|---|-----|-------|:--------------:|
| 1 | Добавить momentum признаки (rsi_centered, macd_norm, macd_hist_sign, stoch_kd_diff, adx_directional_ratio, williams_r) | `ai/features.py` | 20 мин |
| 2 | Добавить volatility признаки (parkinson_vol, garman_klass_vol, bb_width_norm, vol_percentile_252) | `ai/features.py` | 15 мин |
| 3 | Добавить trend признаки (dist_to_sma_5/24/50, zscore_24, dist_to_high_24, dist_to_low_24) | `ai/features.py` | 15 мин |
| 4 | Добавить interaction признаки (trend_over_vol, momentum_regime, vol_adj_return_1d, trend_volume_confirm) | `ai/features.py` | 15 мин |
| 5 | Добавить temporal признаки (dow_sin/cos, hour_sin/cos, is_month_end, is_quarter_end) | `ai/features.py` | 10 мин |
| 6 | Реализовать LASSO feature selection + интеграция в build_dataset | `ai/features.py` + `ai/dataset_v2.py` | 30 мин |
| 7 | RobustScaler в TrainerConfig | `ai/trainer_v2.py` | 10 мин |
| 8 | Обновить константы размерности (LSTM_N_GLOBAL, TOTAL_FEATURES) | `ai/features.py`, `domain/constants.py` | 10 мин |
| 9 | Обновить `inference_v2.py` (синхронизировать feature extraction) | `ai/inference_v2.py` | 10 мин |
| 10 | Прогнать тесты и исправить сломанные | `pytest -v` | 20 мин |
| 11 | **Переобучить модель** | `python scripts/train_neural_model.py --start 2021-01-01 --end 2024-01-01 --hidden-size 64 --num-layers 1 --dropout 0.4 --weight-decay 1e-4 --no-auto-scale --epochs 200 --walk-forward 4` | ~35 мин |
| 12 | **IS batch backtest** | `python scripts/batch_backtest.py --start 2023-01-01 --end 2024-01-01` | ~10 мин |
| 13 | **OOS batch backtest** | `python scripts/batch_backtest.py --start 2024-01-01 --end 2025-01-01` | ~10 мин |
| 14 | Обновить отчёты | STATE, BACKTEST-RESULTS, CHANGELOG, PARAMETERS | ~10 мин |

**Общее время:** ~3.5 часа (включая обучение и бэктесты)

---

## 7. Риски и митигация

| Риск | Вероятность | Серьёзность | Митигация |
|------|:-----------:|:-----------:|-----------|
| **Слишком много фич → overfitting** | Medium | High | LASSO + dropout=0.5 |
| **Feature computation медленнее** | High | Low | Кэширование technicals уже есть |
| **Размер входного слоя растёт** | High | Low | hidden=64 сохраняем |
| **Тесты ломаются (размерности)** | High | Medium | Обновить assert-ы в тестах |
| **LASSO не улучшает OOS** | Medium | High | Откатить feature selection, пробовать Boruta |
| **Изменение scaler ломает модель** | Low | High | Retrain обязателен после смены scaler |

---

## 8. Критерии успеха

| Критерий | Текущее значение | Целевое значение |
|----------|:----------------:|:----------------:|
| **OOS Total PnL** | -1,163K | **> 0** (хотя бы безубыток) |
| **Positive OOS tickers** | 1/12 (8%) | **≥ 4/12 (33%)** |
| **OOS Avg WR** | 39.6% | **≥ 42%** |
| **OOS Avg PF** | 0.78 | **≥ 0.95** |
| **AUC** | 0.5679 | **≥ 0.58** |
| **Walk-forward avg AUC** | 0.5731 | **≥ 0.60** |
| **IS→OOS gap (PnL)** | -1,656K | **< -500K** |
