baykovpro

← Quant

Твой бэктест врёт: walk-forward harness на Python

21 июля 2026 · 21 мин · бэктест, walk-forward, data-snooping, методология

Суть идеи

Автор рассказывает историю, которую каждый квант проживал хотя бы раз: бэктест показывает +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.

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