Твой бэктест врёт: walk-forward harness на Python
Суть идеи
Автор рассказывает историю, которую каждый квант проживал хотя бы раз: бэктест показывает +40% за два года, потом находятся три бага — не в логике стратегии, а в том, как считается результат — и доходность схлопывается до нуля. Это и есть центральный тезис: бэктест врёт не потому что стратегия плохая, а потому что «линейка» кривая.
На основе этого опыта собран walk-forward validation harness на Python. Идея классическая: делишь историю на последовательные окна, на каждом in-sample подбираешь параметры, на следующем out-of-sample проверяешь — и так катишься вперёд. Никакого заглядывания в будущее, никакого единого «оптимального» набора параметров, подогнанного под всю историю целиком.
Механизм, по которому это должно работать: если сигнал несёт реальную предсказательную силу, он должен выживать при смене окна обучения. Если он выживает только на конкретном историческом отрезке — это переподгонка, а не стратегия. Walk-forward — минимальный фильтр, отсекающий самые грубые случаи data-snooping.
Применимость к крипте
Переносится напрямую и без потерь. Наш bt_engine уже заточен под rolling-z и walk-forward, так что харнесс концептуально совпадает с тем, что мы уже делаем. Конкретная польза — в деталях реализации: как именно нарезать окна (expanding vs. rolling in-sample), как агрегировать OOS-результаты по всем фолдам, как считать итоговый Sharpe только по OOS-периодам.
Для наших рядов — ATM IV BTC/ETH, GEX, funding, STH-MVRV, skew — логика та же: параметры rolling-z (длина окна, порог входа) подбираются на in-sample, фиксируются, прогоняются на следующем OOS-блоке. Особенно актуально для VRP-стратегий, где «оптимальный» порог продажи волатильности гуляет в зависимости от режима рынка.
Тестируемо ли
Да, и именно на нашем движке. Все нужные ряды есть: дневные и часовые OHLCV BTC/ETH, ATM IV, funding, on-chain метрики. Харнесс не требует специфических данных — он про архитектуру теста, а не про конкретный сигнал. Единственное, чего может не хватать — достаточной длины истории для большого числа независимых OOS-фолдов: крипто-данные с 2017 года дают ~7 лет, что при квартальных окнах — около 28 фолдов. Это приемлемо, но не роскошно.
Deflated Sharpe Ratio, который уже есть в нашем движке, логично встраивается поверх walk-forward: считаешь DSR по агрегированному OOS-эквити, а не по in-sample кривой.
Сомнения
Статья — методологическая, не эмпирическая, поэтому классических претензий к переподгонке конкретной стратегии здесь нет. Но есть риск другого рода: walk-forward сам по себе не панацея. Если перебираешь достаточно параметров на каждом in-sample окне, data-snooping никуда не девается — просто становится менее очевидным. Кроме того, при коротких OOS-окнах (скажем, месяц) результаты отдельных фолдов высокодисперсны, и агрегированный Sharpe может выглядеть прилично за счёт нескольких удачных периодов, а не стабильного сигнала.
Ещё один момент: режимная хрупкость. Параметры, оптимальные в трендовом 2020–2021, будут мусором в боковике 2022–2023. Walk-forward это частично ловит, но не гарантирует.
Следующий шаг
Взять VRP-сигнал (ATM IV минус реализованная волатильность BTC, дневной ряд с 2019), прогнать walk-forward с expanding in-sample окном (минимум 180 дней) и OOS-блоками по 60 дней, перебрать 3–4 порога входа на каждом фолде, посчитать DSR только по склеенному OOS-эквити — и сравнить с наивным бэктестом на полной истории с теми же параметрами.
Результаты тестов
Дописано 21 июля 2026 — прогон «Следующего шага» на нашем движке в день выхода заметки. Сама статья выше не менялась.
Сигнал — VRP BTC (Deribit DVOL 30д ATM IV минус 30-дневная реализованная волатильность), стратегия из наших прошлых прогонов: высокий z(VRP) → лонг BTC, вход t+1, издержки 6 б.п. плюс funding перпа (в среднем +8.4%/год на удержании). Одна поправка к спеке: «дневного ряда с 2019» для крипто-IV не существует — DVOL стартовал в марте 2021. Харнесс собран ровно по статье: expanding in-sample от 180 дней, OOS-блоки по 60, на каждом фолде перебор четырёх порогов входа (z > 0 / 0.5 / 1.0 / 1.5, expanding-z, меню зафиксировано до прогона), выбор по IS-Sharpe, DSR — только по склеенному OOS-эквити. Вышло 28 фолдов (декабрь 2021 → июль 2026) — забавно, ровно столько, сколько статья обещала от «семи лет с 2017-го».
| Вариант | Sharpe (вся история) | DSR | В рынке | Sharpe на OOS-периоде |
|---|---|---|---|---|
| z > 0 | +0.25 | 0.56 | 38% | +0.19 |
| z > 0.5 — выбор наивного бэктеста | +0.60 | 0.83 | 16% | +0.56 |
| z > 1.0 | +0.24 | 0.55 | 5% | +0.20 |
| z > 1.5 | +0.59 | 0.90 | 1% | +0.67 |
| Walk-forward склейка — честный форвард того же меню | — | 0.26 | 5% | −0.12 |
| Buy & hold BTC | — | — | 100% | +0.40 |
Главная цифра — хэйркат −0.88. В момент каждого из 28 выборов бэктест по всей доступной истории показывал в среднем +0.76. Форвардная торговля этими выборами дала −0.12 (−9.3% за 4.6 года склейки). Наивные +0.60 — та цифра, которую показывают инвестору, — не пережили первого же честного измерителя. Тезис заголовка воспроизведён дословно.
Как именно врёт: выбор залипает на редком пороге. С 7-го фолда IS-выбор захватил z > 1.5 — порог, который за пять лет был в рынке 17 дней (восемь в 2021-м, семь в 2022-м, два в январе 2023-го — и всё). Эти полтора десятка удачных дней дали +19.8% и IS-Sharpe 1.04 — и харнесс держался за него 20 фолдов подряд: с декабря 2022 по март 2026, если не считать тех двух январских дней (единственный плюсовый фолд серии), стратегия просидела в кэше — 0 дней в рынке в 18 фолдах из 20. Механику стоит запомнить: у редкосрабатывающего варианта expanding-Sharpe затухает всего лишь как 1/√n — флэтовые дни его почти не штрафуют, новые данные ничего не опровергают, и удача 2021 года рулит выбором до 2026-го. Rolling-окно в IS забывало бы быстрее — но это ещё одна ручка, которую придётся крутить и переподгонять.
Стоимость переключателя — −0.68. Самое неприятное: на том же OOS-периоде все четыре статичных порога дали плюс (от +0.19 до +0.67) — сам VRP-сигнал скорее жив. Ротация «лучшего по IS» дала −0.12 — хуже каждого из кандидатов, между которыми выбирала; performance chasing внутри честного харнесса стоил −0.68 Sharpe против «просто держи z > 0.5». Walk-forward — измеритель, а не улучшайзер: от снупинга он не спасает, он выставляет ему счёт.
Сомнение №1 из статьи (перебор параметров никуда не девается) — подтверждено, с гарниром. Расширяем меню до 40 вариантов (5 оценщиков z × 8 порогов): наивный best-of-40 хорошеет до +1.06, и DSR 0.95 его почти пропускает — фон из десятков полуфлэтовых вариантов недодисперсен, и поправка «на N испытаний» сама обманывается, когда испытания — флэт. WF на широком меню даёт +0.43 против −0.12 на узком: не «больше перебора → лучше OOS», а лотерея пикера — std фолдовых Sharpe здесь 1.58. Оба честных числа статистически неотличимы от нуля (DSR 0.45 и 0.26).
Сомнение №2 (агрегат тянут удачные фолды) — да. Из 28 фолдов торговали шесть, в плюсе три. Убираем один лучший (декабрь 2021: 4 дня в рынке, фолдовый Sharpe 3.44) — склейка проседает с −0.12 до −0.19; без топ-3 — −0.29.
Вывод. Статья права в главном и даже скромничает. Walk-forward обязателен — но как линейка, а не как стратегия: здесь он превратил витринные +0.60 в честные −0.12. При этом сам харнесс — тоже код с ручками (метрика выбора, expanding против rolling в IS, ширина меню), и на разреженных сигналах его выбор залипает на прошлой удаче ровно тем способом, от которого должен был защищать. DSR по склеенному OOS-эквити — правильное место для DSR, но фон испытаний должен быть живым: сорок флэтов ничего не дефлируют.
Проверка: research_wf_harness.py (реюз bt_engine и загрузчиков прошлых Tier-3) + адверсариальная верификация: независимая реимплементация с нуля (numpy-цепочка, свой DSR через erf и бисекцию) сошлась до четвёртого знака; future-shock — подглядывание в завтрашний z переворачивает знак (+0.60 → −0.40: лукахед заводит лонг прямо в день vol-спайка, который и вздувает VRP) — пайплайн к внесённому лукахеду чувствителен, значит сам чист; лишний день лага к исполнению деградирует умеренно (+0.60 → +0.46); повторный прогон детерминирован побайтово.
Результаты тестов · часть 2: чинится ли сам харнесс
Дописано 25 июля 2026 — продолжение прогона выше. Сама статья не менялась.
В первой части walk-forward превратил витринные +0.60 в честные −0.12, и виноват оказался не сигнал, а правило выбора: оно залипло на пороге, который за пять лет торговал 17 дней. Раз диагноз известен, логично спросить — лечится ли. Причин залипания ровно две, и лечится каждая отдельно: expanding-окно никогда не забывает старую удачу (лечится rolling-окном в in-sample), а редкий кандидат нечем опровергнуть, потому что флэтовые дни не портят его Sharpe (лечится порогом допуска — кандидат обязан быть в рынке хотя бы 30 дней в in-sample). Фолды, меню и данные те же, меняется только правило выбора.
| Правило выбора | OOS-Sharpe | DSR | Смен | Дней в рынке |
|---|---|---|---|---|
| Как в статье (expanding, без допуска) | −0.12 | 0.26 | 2 | 78 |
| Expanding + допуск 30 дней в рынке | +0.56 | 0.79 | 0 | 220 |
| Rolling IS 365 дней | +0.80 | 0.91 | 8 | 128 |
| Rolling IS 365 + допуск | +0.33 | 0.62 | 3 | 329 |
| Rolling IS 730 + допуск | +0.57 | 0.80 | 2 | 223 |
| Статичный z > 0.5, без всякого выбора | +0.56 | — | 0 | 220 |
Первое, что стоит заметить: строка с допуском совпала со статикой до второго знака. Это не совпадение — порог допуска выбросил редкого кандидата из меню, и выбирать стало не из чего: правило 28 фолдов подряд берёт один и тот же вариант. Починка сработала, но её результат — «перестать выбирать». Ноль смен позиции, ровно та же кривая, что у человека, который вообще не строил харнесс.
Второе — и вот тут ловушка, в которую легко провалиться. Пять правил выше я отбирал, уже видя их OOS-результат. Это тот же самый data-snooping, только этажом выше: не «переберём пороги стратегии», а «переберём способы бороться с перебором». Честная проверка — выбрать правило по первой половине фолдов и замерить на второй, которой при выборе не видели:
| Правило | Фолды 1–14 | Фолды 15–28 (не видели при выборе) |
|---|---|---|
| Как в статье | −0.17 | флэт (ни одной сделки) |
| Expanding + допуск | +0.48 | +0.77 |
| Rolling IS 365 дней | +0.79 | +0.84 |
| Rolling IS 365 + допуск | +0.36 | +0.29 |
| Rolling IS 730 + допуск | +0.48 | +0.81 |
| Статичный z > 0.5 | +0.48 | +0.77 |
Rolling-365 лидирует в обеих половинах — то есть выбор правила пережил собственный форвард-тест, это не мета-снупинг. Но перевес над «просто держи z > 0.5» на скрытой половине — +0.07 Sharpe при восьми переключениях, и называть это эджем было бы ровно тем, от чего предостерегает статья. Честная формулировка: короткая память в in-sample убирает залипание, а всё, что она возвращает, — это примерно статичный вариант.
Отдельно про DSR, раз статья предлагает считать его по склейке. Место выбрано верно, но у формулы Bailey — López de Prado есть незаметная деталь: разброс Sharpe между испытаниями (sd_SR) берётся из наблюдаемых результатов меню, хотя по смыслу нужен разброс под нулевой гипотезой. Наблюдаемый — плохая замена, причём врёт в обе стороны. В первой части это видно на широком меню: сорок полуфлэтовых вариантов дают заниженный разброс, порог падает, и DSR 0.95 пропускает пустышку. Мы прогнали ту же диагностику на своём турнире из 42 сигналов, и там перекос обратный: меню разнородное, с настоящими сигналами и антисигналами, наблюдаемый разброс шире нулевого в 1.25 раза, порог завышен, DSR занижены на 0.10–0.14 — то есть наш собственный измеритель несколько лет был строже, чем следует.
Чинится это заменой оценки на прямую: позиции стратегии и её издержки остаются как есть, а доходности циклически сдвигаются — получается распределение Sharpe под нулём, где разреженность и оборот учтены сами собой. Если сдвиг общий для всех испытаний, кросс-секция сохраняет их взаимную корреляцию, и порог берётся прямо как средний максимум по этому распределению — без допущения о независимости N испытаний, которого в реальном меню никогда нет (у нас средняя парная корреляция +0.23, эффективных испытаний около четырёх из 42). Кстати, наивная поправка «поделим N на корреляцию» здесь была бы грубой ошибкой в мягкую сторону: аналитическая формула на четырёх испытаниях дала бы порог 0.53 годовых вместо честных 1.20.
Вывод части 2. Харнесс чинится, но не так, как хочется: обе починки работают тем, что отнимают у него свободу выбирать, и возвращают примерно ту же кривую, что у статичного варианта. Walk-forward остаётся линейкой — он показывает, сколько стоит ваш перебор, а не добавляет доходности. И у самой линейки есть ручки, которые тоже надо валидировать форвардом: правило выбора, длина памяти, порог допуска, оценка фона DSR. Хорошая новость в том, что каждая из этих ручек проверяется тем же приёмом, что и стратегия, — разделением на «до» и «после».
Проверка: research_wf_harness.py (обобщённое правило выбора; дефолты воспроизводят прогон части 1 без изменений) и research_dsr_audit.py (ротационный нуль, 289 общих сдвигов × 42 стратегии, прогнан на BTC и ETH — обе картины совпадают). Мета-проверка правил — раздельная выборка по фолдам, второй половины при выборе не видели.
Результаты тестов · часть 3: харнесс на собственном арсенале
Дописано 25 июля 2026 — третий заход. Сама статья не менялась.
Части 1 и 2 гоняли харнесс на одном сигнале и четырёх порогах. Теперь тот же аппарат — поверх нашего рабочего меню: 42 живые стратегии из арсенала бэктест-движка (CME-позиционирование, потоки спот-ETF, on-chain, funding, ансамбли), BTC, 22 фолда по 60 дней, out-of-sample с декабря 2022 по июль 2026. Правило то же самое: на каждом фолде выбираем лучшую стратегию по трейлинг-Sharpe и держим её следующий блок. Плюс к этому мы добавили то, чего не хватало в первых двух частях — нулевую гипотезу для самого переключателя.
Идея нуля простая. Позиции всех стратегий и их издержки остаются как есть, а ряд доходностей циклически сдвигается: связь «сигнал → будущая доходность» рвётся, всё остальное сохраняется. И дальше на каждом из 288 сдвигов гоняется весь пикер целиком, со всеми его 22 выборами из 42 кандидатов. Получается прямой ответ на вопрос «а сколько вообще набирает переключатель на шуме?» — со всей множественностью выбора внутри, без формул и допущений.
Ответ оказался неожиданным: не ноль, а +0.48. Циклический сдвиг сохраняет лонг-бету меню (стратегии в среднем сидят в лонге BTC), поэтому пикер по шуму на растущем рынке всё равно зарабатывает. Любой, кто сравнивает свой переключатель с нулём, сравнивает не с тем.
| Что | Наблюдённый Sharpe | Нуль E[SR|0] | p95 нуля | Перцентиль |
|---|---|---|---|---|
| Ротация, expanding-окно | +0.85 | +0.47 | 1.15 | 82% |
| Ротация, rolling 180 | +0.94 | +0.45 | 1.16 | 88% |
| Ротация, rolling 365 | +0.60 | +0.50 | 1.19 | 60% |
| Ротация, rolling 730 | +0.97 | +0.48 | 1.21 | 87% |
| B&H BTC | +0.99 | +0.81 | 1.13 | 81% |
| Лучший статик задним числом | +1.63 | +1.27 | 1.66 | 94% |
| EW всего меню (контроль) | +0.63 | +0.64 | 1.20 | 49% |
| Допуск + равные веса | +1.44 | +0.70 | 1.16 | 100% |
Строка контроля важнее всех остальных. Равные веса по всему меню — стратегия, в которой вообще нет никакого выбора, — дали 0.63 при нуле 0.64, то есть ровно медиану собственного нуля. Именно так и должно выглядеть «селекции нет, эджа нет»; это проверка, что нуль не подкручен и меряет то, что заявлено. На фоне этой калибровки остальные строки читаются однозначно: ни одно правило ротации из нуля не вышло (60–88 перцентиль), не вышел и просто BTC (81%), и даже лучший статик, выбранный задним числом по этому же периоду (94% при p95 = 95%) — что независимо рифмуется с нашим отдельным аудитом фона DSR, где планку 0.95 не прошёл никто.
Цена переключателя — не комиссии. Механика оказалась копеечной: 15 базисных пунктов за три с половиной года, четырнадцать смен позиции, вклад в Sharpe −0.001. Меню сильно перекрывается по лонг-экспозиции, поэтому «переехать» из стратегии в стратегию почти ничего не стоит. Вся разница — минус 1.04 Sharpe против лучшего статика — это чистое сожаление о выборе, а не издержки. Экономить на комиссиях здесь бессмысленно: платит не брокер, платит ранжирование.
Правило выбора не переносится между задачами. В части 2 победителем мета-проверки вышло rolling-365 — и оно же здесь худшее из шести (0.60). А правило, выбранное по первой половине фолдов этого прогона (rolling-180, великолепные 2.15), на второй половине даёт −0.21. Вывод, который стоит записать крупно: длина памяти пикера — это не настройка, которую можно один раз подобрать и переиспользовать. Она сама по себе испытание, и валидировать её надо заново на каждом новом меню.
Что всё-таки работает. Единственное наблюдение во всём исследовании, вышедшее за собственный нуль, — предпоследняя строка таблицы: не выбирать лучшего, а отсеять неработающих и оставшимся дать равные веса. Причинный фильтр допуска (стратегия обязана быть активной в трейлинг-окне) плюс равномерное взвешивание дают 1.44 при нуле 0.70 — выше всех 288 нулевых прогонов. Разложение по шагам: 0.63 у всего меню → 1.17 при статичном фильтре активности → 1.44 при динамическом допуске. Формула получается короткая: допуск полезен, argmax вреден. Отбор нужен, чтобы выбросить мусор, а не чтобы короновать чемпиона.
Оговорка по-честному: конфигурация допуска здесь одна (окно 365 дней, минимум 30 дней активности), выбрана по аналогии с правилами ротации, а не подобрана — но если начать перебирать её параметры, множественность вернётся, и проверять придётся тем же нулём. Мы это и сделаем прежде, чем что-то на этом строить.
Вывод части 3. Проверять надо не только стратегию, но и того, кто её выбирает — и мерить его против нуля, который сохраняет бету рынка, иначе половина «эджа» окажется просто лонгом BTC. На нашем меню переключатель по трейлинг-результату не окупился ни в одной из шести настроек, зато окупился отказ от выбора в пользу дисциплины допуска. Что, если задуматься, и есть главная мысль исходной статьи, только с обратной стороны: харнесс нужен не для того, чтобы найти лучшую стратегию, а чтобы честно узнать, чего стоят ваши попытки её найти.
Проверка: research_wf_rotation.py. Встроенная — независимая numpy-реплика пикера повторяет выборы и Sharpe всех шести правил бит-в-бит, реконструкция дневного P&L сходится до нуля, повторный прогон детерминирован. Адверсариальная — реимплементация с нуля по словесной спеке отдельным агентом: расхождений нет ни в одной цифре, утечки на границах фолдов нет, стоимость переключения точна или консервативна. Диагностика границы: лишний день лага даёт +0.65, а заглядывание на день вперёд +0.88 — пайплайн к утечке чувствителен, значит сам чист.
Результаты тестов · часть 4: опровержение части 3
Дописано 26 июля 2026. Эта часть отменяет главный вывод предыдущей — оставляем обе, потому что в том, как именно мы ошиблись, пользы больше, чем в самой ошибке.
В части 3 мы объявили находку: из всего нашего арсенала за пределы ротационного нуля вышло одно правило — не выбирать чемпиона, а отсеять неактивных и оставшимся дать равные веса. «Допуск полезен, argmax вреден». Дальше мы честно попытались её убить: прогнали на втором активе, просвипали тридцать конфигураций, ввели family-wise поправку максимумом по сетке, дважды переписали код независимыми реализациями. Находка выстояла всё.
А потом мы задали вопрос, которого не задавали раньше: откуда вообще берётся размер пула?
Механизм. Правило взвешивает членов пула поровну, то есть вес каждого равен 1/n. Пул рос: 5 стратегий в конце 2022-го, 13 к 2024-му, 38 к 2026-му. А раз позиция портфеля — это среднее по пулу, валовая экспозиция правила падала обратно размеру: с 8.4× в начале до 1.1× в конце. Мы думали, что тестируем отбор. Мы тестировали монотонно убывающий график плеча на выборке, которая начинается на дне цикла — в декабре 2022-го, сразу после краха FTX.
Разложение на три компоненты (тот же период, та же метрика) не оставляет от находки ничего:
| Что считаем | Sharpe | Перцентиль своего нуля |
|---|---|---|
| Равные веса по всем 42 (ни отбора, ни плеча) | +0.63 | 47% |
| Только отбор, масштаб зафиксирован на 1/42 | +0.56 | — |
| Только плечо 42/n, состав — все 42, отбора ноль | +1.63 | 100% |
| Наша «находка» (отбор + плечо) | +1.45 | 100% |
| Гладкая линейная рампа плеча, ноль информации | +1.37 | 99% |
| Та же рампа, развёрнутая вверх | +0.15 | 23% |
Читается это так. Компонента отбора даёт минус: 0.56 против 0.63 у простого равного веса. Компонента плеча даёт всё: 1.63 без единого бита отбора — то есть больше, чем сама находка. А главное — предпоследняя строка: гладкая рампа, не содержащая никакой информации вообще, проходит нуль на 99%. Ротационный нуль не имеет мощности против монотонного профиля экспозиции: сдвиг доходностей сохраняет путь позиций, поэтому убывающее плечо на растущем рынке выигрывает механически, а не потому что что-то предсказало.
И вот где это становится настоящим лукахедом. Мы объясняли рост пула «созреванием стратегий»: сигнал накапливает активность и пересекает барьер допуска. Красивая история, и она неверна. Мы посмотрели, когда наши ряды впервые появились в базе:
| Ряд | История начинается | Впервые записан в базу |
|---|---|---|
| CME-позиционирование | 2018-04-13 | 2026-07-25 |
| Bitfinex-позиции | 2021-02-22 | 2026-06-24 |
| Потоки спот-ETF | 2024-01-19 | 2026-07-25 |
| On-chain и макро | 2025-06-24 | 2026-06-24 |
В 2023 году у нас не было ни одного коллектора. То, что «в 2023-м пул состоял из пяти CME-стратегий», — не факт истории, а следствие того, что CFTC отдаёт восемь лет отчётов бесплатно и мы скачали их накануне прогона. Размер пула по годам — это календарь нашего бэкфилла, составленный в июле 2026-го задним числом. Забэкфиль мы все ряды до 2018-го (технически возможно для многих), пул был бы полным с первого дня, плечо — плоским, а Sharpe — теми самыми 0.63, что и у контрольной группы.
Почему это пережило все проверки. Каждая из них смотрела не туда. Ротационный нуль сохраняет путь позиций — значит сохраняет и рампу. Свип менял окно и порог, но все тридцать конфигураций делили одну и ту же рампу. Кросс-чек на ETH использует те же ряды с теми же датами бэкфилла — та же рампа, поэтому он «подтвердил». Family-wise поправка защищает от перебора конфигураций, а не от структуры экспозиции. Две независимые реализации сошлись до пятнадцатого знака — и обе считали одно и то же неправильное.
Последнее стоит проговорить отдельно, потому что это соблазн, в который легко попасть: воспроизводимость — не валидность. Мы прогнали находку через два независимых кода, два актива, тридцать конфигураций и три вида нуля, получили согласие везде — и всё это время согласие было согласием о цифре, а не о том, что она означает.
Что уцелело. Вывод части 3 про ротацию стоит: переключатель по трейлинг-результату не окупается, все шесть правил внутри своего нуля, а цена переключения — сожаление о выборе, а не комиссии. Уцелел и контроль: равные веса по всему меню сидят на медиане нуля. Не уцелела ровно вторая половина формулы. «Argmax вреден» — да. «Допуск полезен» — нет: его вклад отрицателен, а всё, что мы приняли за пользу допуска, было плечом, нарисованным нашей же историей закупок данных.
Практический вывод мы уже применили к себе: правило не пошло в наш форвард-трекер, хотя было для этого готово и подключено. Живая линия провисела несколько часов и снята.
Что забирать с собой. Если в бэктесте размер позиции меняется во времени — вы тестируете не только сигнал, но и ставку на тайминг плеча, и она может тихо съесть весь результат. Дальше два вопроса, которых нет ни в одном стандартном чек-листе. Первый: откуда взялся график экспозиции — из логики стратегии или из того, какие данные у вас оказались доступны? Второй: пройдёт ли ваш тест значимости, если подать в него бессмысленную рампу вместо сигнала? У нас — прошла, на 99 перцентиле. Тест, который штампует пустышку, не защищает ни от чего, и узнать это можно только одним способом: подсунуть ему пустышку самому.
Проверка: разложение и провенанс — research_wf_rotation.py, research_wf_sweep.py, запрос к таблице рядов. Опровержение найдено адверсариальной проверкой в пять независимых линз с последующей попыткой опровергнуть каждую находку; ключевые числа (0.56 / 1.63 / 1.45 / рампы 1.37 и 0.15) пересчитаны заново независимой реализацией и совпали. Даты первой записи рядов — прямой запрос min(dt), min(updated_at) по таблице tbl_series.