baykovpro

← Quant

Плато вместо пика: ловушка коллинеарных параметров

24 июля 2026 · 8 мин · бэктест, переподгонка, методология, робастность

Суть идеи

Классический совет квант-сообщества звучит так: не бери лучший параметр — бери стабильный. Если при изменении lookback с 10 до 30 дней Sharpe держится на одном уровне, система «робастна». Статья атакует именно эту логику.

Проблема — коллинеарность параметров. Если два параметра, которые вы свипаете, фактически двигают одно и то же (например, fast MA и slow MA оба масштабируют длину сигнала, а их разность — единственное, что реально влияет на логику), то плато в 2D-сетке не означает, что вы покрыли пространство решений. Вы ходите вдоль одной линии в многомерном пространстве и принимаете это за исследование всего пространства.

Механизм ловушки: метрика производительности — функция от эффективного параметра (скажем, разности двух MA), а не от каждого по отдельности. Свип по сетке (fast, slow) при фиксированном соотношении даёт плоскую поверхность — не потому что система устойчива, а потому что вы никогда не меняли то, что реально важно. Вывод автора: перед свипом нужно явно проверять, не являются ли параметры линейными комбинациями друг друга, и переходить к ортогональной параметризации.

Применимость к крипте

В нашем движке эта ловушка встречается постоянно. Типичный пример: свип по (window_short, window_long) для rolling-z сигнала на ATM IV или GEX. Если логика входа зависит только от z-score, который определяется разностью окон, плато по сетке ничего не доказывает. Аналогично — свип по (strike_delta, expiry) в стратегиях на skew/RR: если payoff определяется только соотношением, а не абсолютными значениями, коллинеарность гарантирована.

Для VRP-стратегий (продажа реализованной волатильности против IV) параметры типа «окно расчёта RV» и «окно сглаживания IV» часто коллинеарны через общий горизонт усреднения. Свип по обоим при фиксированном соотношении даст красивое плато — и ноль информации о реальной робастности.

Тестируемо ли

Методология полностью переносима на наш движок. Конкретные шаги: (1) перед любым 2D/3D свипом вычислить матрицу корреляций между параметрами и метриками чувствительности; (2) если корреляция параметров > 0.8 — перейти к ортогональной параметризации (например, вместо (fast, slow) свипать (fast, ratio=slow/fast)); (3) проверить, изменилась ли форма поверхности производительности.

Данные для этого есть — любой ряд из bt_engine подходит. Дополнительных внешних данных не нужно, это чисто методологический слой поверх существующих свипов.

Сомнения

Статья (судя по аннотации) не даёт строгого теста на коллинеарность — скорее концептуальное предупреждение. Неясно, насколько часто эта проблема возникает в реальных системах против надуманных примеров. Кроме того, ортогональная параметризация сама по себе не гарантирует отсутствия переподгонки — она лишь делает свип информативным. Плато в ортогональном пространстве всё равно может быть артефактом in-sample периода.

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

Взять текущий свип параметров rolling-z на ATM IV BTC (окна от 10 до 60 дней), вычислить попарные корреляции Пирсона между параметрами и Sharpe по сетке, переключиться на параметризацию (base_window, ratio) и сравнить форму поверхности до и после — если плато исчезает, коллинеарность была реальной проблемой.

Результаты тестов

Дописано 25 июля 2026 — прогон «Следующего шага» на нашем движке. Сама статья выше не менялась.

Взяли ровно то, что предложено: свип rolling-z на ATM IV BTC по окнам 10–60 дней. ATM IV — Deribit DVOL (30-дневный индекс, история с марта 2021), цена — перп BTCUSDT с funding-драгом (+8.4%/год на удержании), вход t+1, издержки 6 б.п. Сетка — 325 пар окон (шаг 2, длинное окно строго больше короткого), 1890 дней (~5.2 года). До первого прогона зафиксировали: порог z = 0.5, направление сигнала (штиль → лонг), «плато» = Sharpe в пределах 0.25 от максимума сетки, статичный контроль (20, 40).

Диагностика из статьи не может обнаружить коллинеарность. Шаг (1) предлагает считать корреляцию между параметрами и браковать сетку при corr > 0.8. На полной прямоугольной сетке corr(ws, wl) = 0.00 тождественно, на треугольной (wl > ws) = +0.50. Это свойство формы сетки, а не модели: число одно и то же при любых данных и любой стратегии. Коррелируют не параметры — вырождается метрика, и мерить надо её.

Собрали корректный тест и откалибровали его на синтетике. Два измерителя: (а) коллапс поверхности Sharpe на одну координату — доля объяснённой дисперсии R², с шум-порогом по перестановкам; (б) null-direction: усреднённая матрица ⟨∇S ∇Sᵀ⟩ по сетке, собственный вектор наименьшего собственного значения — это направление, вдоль которого метрика не меняется. Отношение λmin/λmax → 0 означает «поверхность фактически одномерна», угол 45° — «важна только разность окон».

Семья сигналов R²(wl−ws) R²(wl/ws) шум-порог λmin/λmax, угол
СИНТ+ — по построению зависит только от разности 0.97 0.75 0.06 0.000, 45° — поймана
IV rolling-z — спека статьи 0.14 0.14 0.08 0.62, 48°
Price MA-кросс — архетип из статьи 0.03 0.12 0.06 0.51, 56°
VRP (окно RV × окно сглаживания IV) 0.15 0.30 0.06 0.19, 90°
СИНТ− — честно двумерная 0.06 0.08 0.06 0.32, 88° — не флагуется

Детектор ловит вырождение там, где оно заложено руками, и молчит там, где его нет. Ни одна живая семья не вырождена — включая канонический пример самой статьи, fast/slow MA (R² по разности 0.03, ниже шум-порога). Причина понятная: Sharpe зависит не только от логики сигнала, но и от частоты сделок, издержек и доли времени в рынке, а они меняются с абсолютной длиной окон, а не только с их разностью.

Ортогональная репараметризация — косметика, а не тест. Пересеяли сетку в координатах (base = ws, ratio = wl/ws) в той же коробке окон. Значения Sharpe в общих точках тождественны (проверено сравнением) — замена координат не меняет функцию, меняется только плотность выборки. Доля «плато» при этом поехала с 0% до 1% просто от пересева. Значит критерий «если плато исчезло — коллинеарность была реальной» неверен: плато меняется при неизменной системе.

Настоящая причина плато — разрешающая способность ряда. Блочный бутстрап (500 ресэмплов, средний блок 20 дней, ресэмплы общие для всех точек сетки — иначе разности не учитывают корреляцию вариантов): стандартная ошибка одного Sharpe 0.47, ошибка разности с максимумом сетки 0.54. 55% живой сетки статистически неотличимы от максимума (93% в варианте с корректной нормировкой z). За пять лет данных точки сетки просто не различаются — «плато» рисуется само, без всякой коллинеарности.

И плато не переживает смену периода. Корреляция формы поверхности между половинами истории — −0.12. Пересечение плато первой и второй половины к их объединению — 0.00, ни одной общей точки. Лучшая пара первой половины (38, 50) даёт во второй −0.53. Это ровно то «Сомнение», которое статья высказывает про себя в конце, — и оно оказывается важнее её основного тезиса.

Практический совет при этом работает — но не по той причине. Walk-forward: expanding in-sample от 180 дней, OOS-блоки по 60, 29 фолдов, выбор пары окон на каждом фолде только по in-sample, DSR по склейке OOS (N = 233).

Правило выбора OOS-Sharpe DSR IS в момент выбора
best-IS — берём лучшую точку −0.80 0.00 +1.11
плато — берём центр лучшей окрестности −0.28 0.01 +0.82
плато в ортогональных координатах −0.41 0.01 +0.68
статичный центр (20, 40), без выбора −0.51 0.00 −0.11
случайная пара (среднее по 25 сидам) −0.36

Разрыв «плато минус best-IS» = +0.52 и держится во второй спецификации нормировки (+0.48) — то есть «бери стабильный, а не лучший» реально смягчает переподгонку выбора. Но парный тест по дневным P&L даёт t = +0.77 (незначимо), а случайный выбор (−0.36 ± 0.25) плато не проигрывает. Сглаживание работает как регуляризация пикера, а не как источник дохода. Ортогональные координаты не помогли: −0.41 против −0.28.

Что забираем в движок. Корреляцию параметров не считаем — бесполезно. Перед любым свипом гоняем два измерителя из таблицы выше (они лежат в research_collinear_plateau.py и переиспользуемы) и — главное — считаем ошибку разности Sharpe бутстрапом. Если большая часть сетки статистически неотличима от максимума, спор о форме плато бессмысленен: данных не хватает, чтобы выбрать точку, и выбирать её не надо — надо усреднять или брать окрестность.

Оговорки. DVOL — 30-дневный индекс вариансного свопа, а не буквально ATM IV одной экспирации (своя реальная доска у нас короткая, с июня 2026). Сама стратегия убыточна (медиана сетки −0.18 против B&H +0.28) — изучалась геометрия поверхности, а не эдж. Пре-регистрированная нормировка z на SD уровня IV обнулила 28% сетки (при сближении окон |z| < 0.5 всегда); повтор с нормировкой на SD разности помечен в скрипте как пост-хок, выводы не изменились.

Верификация. Все числа переписаны с нуля независимым скриптом (verify_collinear.py, без импорта боевого движка) — 13 из 13 сверок совпали до четвёртого знака. Future-shock (торговля сигналом того же дня вместо t+1) даёт +0.84 → +0.48, то есть утечки будущего в лаге нет; повторный прогон бит-в-бит.

Источник: Aligrithm · оригинал на английском, разбор — авторский на русском.