Deflated Sharpe Ratio: сколько "победителей" бэктеста переживают множественное тестирование?
Статья из серии "Бэктесты без иллюзий".
📄 Эта статья выросла в исследовательскую работу. Каждое число ниже получено одним детерминированным скриптом, который строит контролируемую истину — поиски на чистом шуме, поиски с заложенным edge и реальную коррелированную сетку параметров, — а затем прогоняет через них Deflated Sharpe Ratio, multiple-testing haircut Harvey-Liu и Reality Check Уайта / SPA Хансена, напрямую измеряя false-discovery rate и power каждого метода. Читайте статью онлайн (интерактивная версия + PDF) на deflated-sharpe.marketmaker.cc, код и данные — на github.com/suenot/deflated-sharpe-search.
Вы запускаете перебор параметров. Шестнадцать быстрых длин, сорок медленных, 640 комбинаций moving-average crossover. Сетка досчитывается, и одна ячейка светится: годовой Sharpe 3.9, p-value одиночного теста . Двенадцать нулей значимости. Вы что-то нашли.
Или вы не нашли ничего, и это поиск нашел это за вас.
Поиск параметров — это не тест. Это машина для нахождения самого везучего из N попыток, и чем больше попыток вы ей даете, тем более везучим выглядит ее победитель — независимо от того, есть ли под этим реальный edge. Лучший-из-N Sharpe раздут отбором точно так же, как самый высокий из тысячи случайных людей высок: не потому, что высокий рост реален, а потому, что вы искали. Статистики одиночного теста, напечатанные рядом с победителем, — его p-value, его t-статистика, его "значимо ли это?" — были спроектированы для одной заранее зарегистрированной гипотезы. Скормите им выжившего из поиска, и они солгут, уверенно, каждый раз.
Эта статья измеряет, насколько именно они лгут, а затем измеряет три инструмента, которые это исправляют. Вся суть — в контролируемой истине: мы генерируем доходности, для которых знаем правильный ответ, — иногда чистый шум с нулевым edge, иногда заложенный edge известной силы, — так что "правильно ли сработал метод?" становится фактом, а не оценочным суждением. Вот заголовочный результат сразу. На поисках с известным нулем, где честный ответ всегда "открытий нет", вот как часто каждый тест кричит "волк!":
| Тест | False-discovery rate на поисках с известным нулем | Вердикт |
|---|---|---|
| Наивный тест: "лучший Sharpe значим?" | 1.000 | фиксирует открытие каждый раз без исключения |
| Deflated Sharpe Ratio (DSR ≥ 0.95) | 0.001 | под контролем |
| Harvey-Liu haircut — Bonferroni | 0.057 | ~под контролем |
| Harvey-Liu haircut — Holm | 0.057 | ~под контролем |
| Harvey-Liu haircut — BHY | 0.007 | под контролем |
| Reality Check Уайта (bootstrap) | 0.022 | под контролем |
1,000 стратегий на поиск, по 1,000 наблюдений на каждую, 2,000 независимых нулевых поисков, истинный Sharpe = 0 везде. Синтетические iid нормальные доходности, seed 0, α = 0.05, 252 периода в году. False-discovery rate наивного теста не просто высок — он равен ровно единице.
Читайте первую строку, пока не зацепит. Тест, который должен срабатывать 5% времени на чистом шуме, срабатывает 100% времени — потому что вы показываете ему не чистый шум, а максимум из тысячи выборок чистого шума, а максимум тысячи людей, подбрасывающих монету, всегда выглядит гением. Каждая следующая строка — это метод, который знает об этом и это исправляет. В этом вся статья: почему первая строка равна 1.000, почему остальные — нет, и единственное место (последний раздел), где даже хорошим методам нужна вторая поправка, чтобы остаться честными.
Акт 1 — Ловушка: поиск фабрикует Sharpe из ничего

Начнем с самой чистой возможной ловушки. Сгенерируем стратегий, доходности которых — независимый стандартный нормальный шум: без сноса, без мастерства, истинный Sharpe у всех ровно ноль. У каждой наблюдений. Теперь сделаем то, что делает любой поиск параметров: оставим лучшую.
Лучший-из-1000 Sharpe на одно наблюдение в среднем равен 0.1027, что при аннуализации дает 1.63 (вывод: ). Это не скромное число. Годовой Sharpe 1.63 — результат, под который стратегию профинансируют, о котором напишут, под который выделят капитал. А получен он из генератора случайных чисел со сносом, выкрученным в ноль.
Теперь передадим победителя наивному тесту значимости — тому самому, который бесплатно печатает любая библиотека для бэктестов. Переведем его Sharpe в t-статистику (), возьмем одностороннее p-value, назовем это открытием, если :
Медианное p-value одиночного теста для этих шумовых победителей — 0.000686 — три нуля "значимости" у стратегии без edge. А по 2,000 независимым нулевым поискам наивный тест объявляет открытие в каждом из них: false-discovery rate 1.000. Не "раздутый". Не "немного завышенный". Тест, который по построению прав максимум в 5% случаев на одной нулевой гипотезе, ошибается в 100% случаев на победителе поиска.
Механизм не так уж тонок, если его назвать. Наивный тест спрашивает: "мог ли этот Sharpe возникнуть случайно при нулевой гипотезе?" — честный вопрос для стратегии, которую вы выбрали до того, как посмотрели на данные. Но вы выбрали именно эту, потому что у нее был самый высокий Sharpe из тысячи. Вы обусловились на максимуме, а распределение выборки максимума совершенно не похоже на распределение выборки одного значения. Это та же болезнь, которую наша таксономия look-ahead bias диагностировала с другого конца — там утечка в один бар фабриковала Sharpe 15 из шума; здесь поиск фабрикует Sharpe 1.63 из шума вообще без утечки, чисто отбором. Разный механизм, идентичный симптом: отлично выглядящий Sharpe, который ничего не значит.
Число 1.63 — важное, так что держите его в уме. Это потолок шума для этого поиска: Sharpe, который вы должны ожидать от самой везучей из 1,000 стратегий с нулевым edge. Любой честный тест победителя поиска обязан сравнивать его не с нулем, а с этим числом — с тем, что дает чистая удача, когда вы смотрите тысячу раз.
Акт 2 — Инструментарий: три способа оценить цену поиска

Три исследовательские программы, пришедшие к этому независимо друг от друга, приходят к одному и тому же решению: перестать сравнивать победителя с нулем и начать сравнивать его с тем, что поиск такого размера производит по чистой удаче. Различаются они в том, как именно строят это сравнение.
PSR и Deflated Sharpe Ratio (Bailey & López de Prado, 2012 / 2014)
Probabilistic Sharpe Ratio задает более острый вопрос, чем "положителен ли Sharpe?". Он спрашивает: с учетом длины выборки и формы распределения доходностей (skew, толстые хвосты), какова вероятность, что истинный Sharpe превышает бенчмарк ?
Здесь — стандартная нормальная CDF, — skew, а — эксцесс (kurtosis) в не-избыточной конвенции (для нормального распределения ; подставьте сюда избыточный эксцесс без добавления 3, и дефляция получится неверной). При PSR — это просто тест значимости для конечной выборки. Магия — в правильном выборе .
Deflated Sharpe Ratio — это PSR, вычисленный при бенчмарке, который не ноль, а ожидаемый максимальный Sharpe всего поиска:
где — дисперсия по всем N Sharpe испытаний (разброс, который произвел сам поиск), — постоянная Эйлера-Маскерони, а два обратных нормальных члена — приближение теории экстремальных значений (Extreme-Value Theory) к ожидаемому максимуму стандартных нормальных выборок. В коде это почти слишком коротко, чтобы впечатлять:
def expected_max_sharpe(sr_variance, N, mean_sr=0.0):
"""E[max of N independent SR estimates ~ N(mean_sr, sr_variance)]
(Bailey & LdP 2014)."""
g = EULER_MASCHERONI # 0.5772156649
a = norm.ppf(1.0 - 1.0 / N) # Z^{-1}(1 - 1/N)
b = norm.ppf(1.0 - 1.0 / (N * E)) # Z^{-1}(1 - 1/(N e))
return float(mean_sr + np.sqrt(sr_variance) * ((1.0 - g) * a + g * b))
Тогда DSR — это просто PSR с этой дефлированной планкой:
def deflated_sharpe(sr_max, sr_estimates, T, skew=0.0, kurt=3.0, N=None):
"""DSR = PSR(sr_max, SR0). Returns (dsr, sr0)."""
v = float(np.asarray(sr_estimates).var(ddof=1)) # dispersion of the search
m = float(np.asarray(sr_estimates).mean())
if N is None:
N = len(sr_estimates)
sr0 = expected_max_sharpe(v, N, mean_sr=m)
return psr(sr_max, sr0, T, skew, kurt), sr0
DSR — это вероятность. Мы объявляем открытие, когда : истинный Sharpe победителя превосходит ожидаемый лучший-по-удаче с уверенностью 95%. Обратите внимание на несущее предположение, встроенное в : испытаний рассматриваются как независимые. Весь Акт 5 — о том, что происходит, когда это не так.
Haircut Harvey-Liu (2015)
Harvey и Liu атакуют ту же проблему через поправки p-value для multiple testing — классический аппарат для "я прогнал M тестов, не дайте мне обмануть самого себя". Упорядочим p-value одиночных тестов и раздуем их:
Bonferroni — тупой инструмент (контролирует вероятность любого ложноположительного результата, умножая каждое p-value на ); Holm — его равномерно более мощный "ступенчатый" родственник. Третий, Benjamini-Yekutieli (BHY), контролирует false-discovery rate — ожидаемую долю неверных среди ваших отклонений гипотезы — и, что критично, делает это при произвольной зависимости между тестами, используя гармонический нормализатор в числителе:
Это — цена, которую BHY берет за то, что не предполагает независимость ваших 1,000 испытаний: он раздувает порог FDR множителем, растущим как . Сам "haircut" — это итоговая метрика: перевести скорректированное p-value обратно в Sharpe и сообщить, сколько от исходного Sharpe пришлось состричь. Haircut в 100% означает, что победитель целиком объясняется multiple testing; 15% — что он в основном уцелел.
Reality Check Уайта и SPA Хансена (2000 / 2005)
Третий инструмент вообще не делает никаких предположений о распределении. Reality Check Уайта берет фактические доходности каждого правила, формирует статистику max-по-правилам и напрямую bootstrap-ит ее нулевое распределение:
где — средняя результативность правила относительно бенчмарка. Он ресемплирует доходности stationary bootstrap (Politis-Romano — блоки случайной длины, благодаря чему сериальная корреляция переживает ресемплинг), рецентрирует каждую выборку так, чтобы нулевая гипотеза выполнялась по построению, пересчитывает максимум на каждой выборке и сообщает p-value как долю bootstrap-максимумов, превысивших наблюдаемый. SPA Хансена улучшает RC двумя способами: студентизацией (делит среднее каждого правила на его собственную стандартную ошибку, так что одно дикое высоковариативное правило не может захватить максимум) и согласованным, зависящим от выборки рецентрированием нуля. Наша реализация добавляет студентизацию, но не полный шаг согласованного рецентрирования — так что везде, где в этой статье приводится p-value SPA-типа, читайте это как студентизированный Reality Check, а не полный Hansen SPA. Там, где DSR спрашивает "особенный ли победитель внутри этого поиска?", Reality Check спрашивает "обыгрывает ли лучшее правило кэш после честного учета того, сколько правил я перепробовал?" — и он обрабатывает коррелированные правила естественно, через bootstrap, вообще не считая испытания. Держите это различие в уме — на нем строится последний раздел.
Акт 3 — Калибровка — это все доказательство

Метод, который вообще ничего не фиксирует, тоже получит false-discovery rate, равный нулю, — и будет бесполезен. Поэтому единственный содержательный тест этих инструментов — двусторонний: на данных с известным нулем они должны удерживать долю ложных открытий на уровне или ниже, а на данных с известным edge (следующий раздел) они все равно должны срабатывать. Этот раздел — первая половина.
Прогоним 2,000 независимых поисков, каждый по 1,000 стратегиям с нулевым edge, и посчитаем, как часто каждый метод объявляет открытие. Это число, деленное на 2,000, и есть false-discovery rate — а поскольку истина в том, что edge нет, каждое открытие ложно:
| Тест | False-discovery rate (α = 0.05) |
|---|---|
| Наивная значимость | 1.000 |
| Deflated Sharpe Ratio | 0.001 |
| Harvey-Liu — Bonferroni | 0.057 |
| Harvey-Liu — Holm | 0.057 |
| Harvey-Liu — BHY | 0.007 |
| Reality Check Уайта | 0.022 |
Каждый принципиальный метод оказывается на уровне 5%-й линии или рядом с ней — два FWER-haircut'а чуть выше нее, DSR/BHY/RC — ниже, — тогда как наивный тест сидит на 100. (Bonferroni и Holm печатают здесь одинаковые 0.057, и не случайно: для единственной лучшей стратегии первый шаг Holm — это , идентичный Bonferroni по построению, так что это одно подтверждение, а не два.) Но самое глубокое число во всем исследовании — не в этой таблице, а в дефлированном бенчмарке, который порождает столбец DSR. Усредненный по нулевым поискам, выходит на уровне 0.1030 на одно наблюдение, что при аннуализации дает 1.63 (вывод: ) — те же 1.63, которые показывает средний шумовой победитель (1.63). Это не совпадение; это работает вся идея целиком:
Дефлированная планка стоит точно на потолке шума. DSR не требует от победителя поиска обыграть ноль. Он требует, чтобы победитель обыграл лучший результат, который чистая удача производит из поиска такого размера — здесь это 1.63 в годовом выражении. Победитель, который лишь совпадает с потолком шума, получает DSR ≈ 0.5 (подбрасывание монеты), поэтому средний нулевой DSR равен 0.495, а не какой-то малой величине. Чтобы стать открытием, победитель должен пройти 1.63 и еще сверху — достаточно, чтобы протолкнуть PSR за 0.95.
Это переосмысляет всю задачу. Наивный тест измеряет расстояние от нуля; любой поиск тривиально проходит эту планку, поэтому он бесполезен. DSR измеряет расстояние от потолка шума, и пройти эту планку по-настоящему трудно — как и должно быть. Haircut Harvey-Liu и Reality Check добиваются того же контроля разными путями (-раздутие для BHY, bootstrap-распределение максимума для RC) и попадают в один и тот же диапазон: от 0.001 до 0.057, на уровне или рядом с ним. Значение 0.057 у Bonferroni/Holm чуть-чуть выше 5%-й линии, но совсем немного: при 2,000 Monte-Carlo поисках стандартная ошибка оценки FDR около 0.05 составляет примерно 0.005, так что 0.057 отстоит от примерно на 1.4 стандартных ошибки — это шум Monte-Carlo, а не сломанная гарантия. "Контроль FWER" в любом случае — асимптотическое обещание, а не побитово точное при .
Акт 4 — Power: сохраняет ли метод реальные edge?

Контроль ложных открытий — только половина теста: параноидальный метод, который отвергает все подряд, получает идеальные 0.000 и абсолютно бесполезен. Вторая половина: когда настоящий edge действительно есть, находит ли его DSR?
Заложим его. В поле из 1,000 стратегий сделаем так, чтобы 25 из них несли настоящий edge известной силы, а остальные остаются шумом, затем запустим поиск и проверим, фиксирует ли DSR победителя. Проведем заложенный edge от слабого к сильному, и detection power вычерчивает чистую S-кривую (false-positive rate все время держится на ~0):
| Заложенный истинный Sharpe (годовой) | Detection power DSR | False-positive rate DSR |
|---|---|---|
| 0.79 | 0.005 | 0.000 |
| 1.27 | 0.090 | 0.000 |
| 1.90 | 0.651 | 0.000 |
| 2.54 | 0.998 | 0.000 |
| 3.17 | 1.000 | 0.000 |
Посмотрите, где кривая поворачивает. Ниже потолка шума — истинный годовой Sharpe 0.79, заметно ниже 1.63 — DSR срабатывает в 0.5% случаев, правильно отказываясь это признавать: edge такой слабости действительно неотличим от удачи, которую генерирует поиск из 1,000 испытаний, и делать вид иначе означало бы нечестность, а не мощность. Прямо у потолка кривая круто взлетает (0.09 при 1.27, 0.65 при 1.90). При годовом Sharpe 2.54 power равен 0.998; при 3.17 — идеальные 1.000. Сильные edge сохраняются практически всегда, ложноположительные срабатывания остаются прижатыми к нулю, а точка пересечения на уровне 50%-й power приходится на годовой Sharpe около 1.73 (получено интерполяцией между строками 1.27 и 1.90) — чуть выше потолка шума 1.63, ровно там, где честная планка и должна стоять: в точке, где edge начинает опережать то, что выдумывает поиск из 1,000 испытаний.
Вот свойство, которое вам на самом деле нужно, выраженное в виде S-кривой: edge ниже потолка шума правильно отбраковываются как удача; edge, уверенно превышающие его, сохраняются с power, стремящимся к единице. Наивный тест, для контраста, "обнаруживает" заложенный edge в 67% случаев даже при истинном Sharpe 0.79 — но это число бессмысленно, потому что мы уже видели: он обнаруживает несуществующий edge в 100% случаев. Тест, который срабатывает на все подряд, не имеет power — у него нет различительной способности. DSR жертвует небольшой чувствительностью к пограничным edge (строки 0.79 и 1.27) ради того, что действительно важно: его открытия реальны.
Акт 5 — Ловушка практика: коррелированные сетки

До сих пор все использовало независимые стратегии — самую чистую из возможных постановок, ту самую, где предположение DSR о независимости выполняется точно. Реальные сетки параметров устроены не так, и именно здесь наивно применяемый инструмент становится новым способом ошибиться.
Возьмем честный поиск moving-average crossover: 16 быстрых длин 40 медленных длин испытаний, по 755 наблюдений в каждом. Такая сетка пропитана корреляцией — fast=45/slow=120 и fast=45/slow=125 — почти одна и та же стратегия, так что их потоки доходностей движутся вместе. Измеренная средняя попарная корреляция по 640 испытаниям: около 0.61. Это не 640 независимых ставок. Даже отдаленно нет.
Случай A — случайное блуждание (без edge): каждый метод его убивает, и правильно
Прогоним сетку на чистом случайном блуждании. Победитель выглядит соблазнительно: параметры fast=45/slow=120, лучший годовой Sharpe 0.81, p-value одиночного теста 0.081. Каждый метод видит его насквозь:
| Метод | Результат | Вердикт |
|---|---|---|
| DSR (сырое K = 640) | 0.431 | отвергнуто (< 0.95) |
| Reality Check p | 0.570 | отвергнуто |
| SPA-type p (студентизированный RC) | 0.569 | отвергнуто |
| Harvey-Liu haircut | 100% | отвергнуто |
Начнем с признака, для которого вообще не нужна дефляция: даже нескорректированная значимость этого победителя для конечной выборки, -vs-zero, составляет всего 0.918 — уже не дотягивает до 0.95, прежде чем мы поправим хотя бы на одно из 640 испытаний. Дефляция затем окончательно его хоронит: планка равна на одно наблюдение, в годовом выражении ~0.91 (вывод: ) — выше победительских 0.81. Лучшая стратегия даже не дотягивает до потолка шума, DSR ≈ 0.43 (хуже подбрасывания монеты), а Reality Check, SPA-типовой тест и 100%-й haircut согласны: здесь ничего нет. Идеально. Это легкий случай, и он работает — и, как мы увидим, отклонение сохраняется при любом эффективном числе испытаний, которое мы пробуем.
Случай B — настоящий режимный edge: сырой DSR ошибается
Теперь прогоним ту же сетку на ряде со сменой режимов, который несет настоящий, эксплуатируемый edge. Победитель категоричен: параметры fast=3/slow=55, лучший годовой Sharpe 3.92 — это in-sample, отобранный Sharpe, сам по себе раздутый отбором со стороны поиска (не истинный и не out-of-sample edge), но лежащий в основе режимный эффект — настоящий — с p-value одиночного теста и недефлированной значимостью -vs-zero практически 1.000. Здесь есть настоящий edge, и победитель его нашел. Смотрите, как сырой DSR все равно его отвергает:
| Метод | Результат | Вердикт |
|---|---|---|
| DSR (сырое K = 640) | 0.748 | отвергнуто (< 0.95) ✗ передефлировано |
| Reality Check p | 0.0024 | подтверждено ✓ |
| SPA-type p (студентизированный RC) | 0.0038 | подтверждено ✓ |
| Harvey-Liu haircut | 15% | подтверждено ✓ |
Сырой DSR 0.748 — это ложное отклонение настоящего edge. Причина — предположение о независимости, теперь грубо нарушенное: DSR построил свою дефлированную планку, трактуя 640 коррелированных испытаний как 640 независимых выборок, что раздувает ожидаемый максимум до 0.221 на одно наблюдение — в годовом выражении ~3.51 (вывод: ). Против планки 3.51 победитель с 3.92 проходит лишь с небольшим запасом, и DSR оказывается на уровне 0.748 — не дотягивая до 0.95. Эту планку задирают вверх две вещи: сырой счет (640 взглядов вместо горстки эффективных) и настоящий разброс мастерства между испытаниями — некоторые пары параметров действительно лучше на режимном ряде, что расширяет и поднимает выше того, что дала бы чистая удача сама по себе. Оба фактора тянут в одну сторону, и планка оказывается слишком высокой, потому что поиск на самом деле никогда не был 640 независимыми взглядами; это была горстка независимых ставок, просэмплированных 640 раз.
Вместо этого скормим DSR эффективное число испытаний. Однострочник, использованный выше, — грубая оценка по средней попарной корреляции:
def effective_n_trials(returns_matrix):
"""N_eff = N / (1 + (N-1) * rho_bar), clipped to [1, N].
Correlated trials -> fewer independent bets."""
C = np.corrcoef(returns_matrix, rowvar=False)
rho_bar = max(np.nanmean(C[np.triu_indices(C.shape[0], k=1)]), 0.0)
N = returns_matrix.shape[1]
neff = N / (1.0 + (N - 1) * rho_bar)
return float(min(max(neff, 1.0), N))
При и это схлопывает сетку до эффективных испытаний (вывод: ), и DSR подскакивает до 1.000. Но не спешите праздновать это число, потому что это самое слабое свидетельство во всем разделе. При дефлированная планка схлопывается до годового — по сути, среднего по испытаниям, по сути, нуля. Дефляция здесь отключена: DSR при просто заново сообщает недефлированную значимость победителя для конечной выборки (-vs-zero ). Вердикт унаследован от сырой значимости, а не произведен поправкой на multiple testing. И зеркальная оговорка на стороне случайного блуждания: его отклонение при держится лишь потому, что этот победитель и без того был независимо пограничным (-vs-zero ). Заякорите весь аргумент на 1.6, и скептик будет прав, пожав плечами: вы отключили поправку и сообщили то, что было под ней.
Так что не заякоривайтесь на одном оценщике. Честный ход — и более сильный — вычислить пятью разными стандартными способами и читать вердикт по всей полосе. Вот пять оценщиков, примененных к одной и той же сигнальной сетке из 640 испытаний, каждый со своей подразумеваемой дефлированной планкой и производимым DSR:
| Оценщик эффективного числа испытаний | Дефлированная планка (годовая) | DSR | Вердикт | |
|---|---|---|---|---|
| Средняя корреляция | 1.6 | 0.25 | 1.000 | сохранить |
| Participation ratio | 2.4 | 0.43 | 1.000 | сохранить |
| PCA (95% дисперсии) | 16 | 1.85 | 1.000 | сохранить |
| Kaiser (собственные значения > 1) | 21 | 2.00 | 0.999 | сохранить |
| Cheverud-Nyholt | 370 | 3.31 | 0.845 | отвергнуть |
| сырой счет сетки (без поправки) | 640 | 3.51 | 0.748 | отвергнуть |
Оценщики: средняя корреляция — это приведенный выше однострочник ; participation ratio и счетчики PCA-95%/Kaiser считывают эффективную размерность с собственных значений корреляционной матрицы; Cheverud-Nyholt — оценщик на основе дисперсии собственных значений из генетической литературы, известный тем, что переоценивает при почти равномерной корреляции (near-equicorrelation).
Теперь суть доходит, и это не "любая поправка вас спасает". Посмотрите на защитимую середину — PCA-95% () и Kaiser (). Это не режим "дефляция отключена"; они накладывают настоящую годовую планку в диапазоне 1.85-2.00 — серьезный haircut, заметно выше шума, подлинный штраф за multiple testing для 16-21 эффективных взглядов. И edge 3.92 все равно ее проходит (DSR 1.000 и 0.999). Сигнал переживает DSR для любого ниже 144.8 (получено из точки пересечения); он проваливается только при у Cheverud-Nyholt — оценщика, который доказуемо переоценивает, когда испытания близки к равномерной корреляции, — и даже сырой, неисправленный счет 640 сталкивает DSR лишь до 0.748, а не до нуля. Победитель случайного блуждания, прогнанный через ровно те же пять оценщиков, отвергается на каждом из них (он не выживает ни при каком выше 1). Вот реальный результат: не одно везучее число, а вердикт, устойчивый по всей полосе стандартных оценщиков эффективного числа испытаний, — а это гораздо более сильное свидетельство, чем доверие к какому-то одному из них.
Одна техническая оговорка про самый грубый оценщик, потому что она объясняет, почему он оказывается на слабом краю: на самом деле — коэффициент снижения дисперсии для среднего коррелированных величин (сколько дает усреднение при корреляции ). Бенчмарк DSR — это величина экстремального значения — ожидаемый максимум испытаний, — так что использование сжатия дисперсии среднего в качестве числа испытаний — функциональное несоответствие: верное по направлению (коррелированность ⇒ меньше эффективных испытаний), но не та величина, от которой на самом деле зависит распределение максимума. Именно поэтому оценщики на основе собственных значений в середине полосы — более надежное чтение, и именно поэтому результатом является полоса, а не точка.
Урок: используйте оба инструмента и скармливайте DSR верный N

Из случая B следуют две вещи, и обе — несущие:
- Сырой размер сетки — неверный N для DSR всякий раз, когда испытания коррелированы, — но и никакой единственный effective-N тоже не верен. Подстановка 640 в формулу, которая предполагает независимость, передефлирует: она фабрикует потолок шума, значительно превышающий тот, которого поиск на самом деле достиг, и хоронит под ним настоящие edge. DSR нужен эффективный счет испытаний — но решение не в том, чтобы довериться одному оценщику (тем более самому грубому, у которого поправка отключается около ). Решение — читать вердикт по всей полосе стандартных оценщиков (здесь от 1.6 до 370) и смотреть, устойчив ли он. Для этого edge он был устойчив: сохранялся везде, где дефляция была по-настоящему активна (настоящая годовая планка 1.85-2.00 при -), проваливаясь только при оценщике, который переоценивает. Вердикт, устойчивый по всей полосе, гораздо сильнее любого одного числа.
- Спаривайте DSR с Reality Check. Обратите внимание, что Reality Check и его SPA-типовой (студентизированный) родственник разобрались со случаем B правильно вообще без всякой хирургии над счетом испытаний (p = 0.0024 и 0.0038) — они обрабатывают зависимость естественным образом, через stationary bootstrap, потому что ресемплируют фактические коррелированные потоки доходностей вместо подсчета гипотетических независимых ставок. Это и есть решающий фактор во всей неразберихе с effective-N: RC не нужен . DSR и RC отвечают на разные вопросы: DSR спрашивает "особенный ли победитель внутри этого поиска?" (и ему нужно знать, сколько эффективных взглядов сделал поиск); RC/SPA-типовой тест спрашивает "обыгрывает ли лучшее правило кэш после data-snooping?" (и считывает зависимость прямо с данных). Вам нужны оба. Когда они расходятся — как здесь разошлись сырой DSR и RC, — это расхождение диагностично: обычно оно означает, что ваш неверен.
Это то же структурное предостережение, на которое постоянно натыкались наши исследования speed-ladder и IPC-tax со стороны инженерии — быстрый поиск, прогоняющий огромную коррелированную сетку, не покупает вам огромное число независимых ставок, а трактовка размера сетки как счета испытаний обманывает и ваш оптимизатор, и ваш тест значимости. Готовящаяся статья-компаньон про probability of backtest overfitting атакует тот же selection bias со стороны ресемплинга (CSCV) и естественно сочетается со всем, что здесь сказано: DSR оценивает цену победителя, PBO — цену самой процедуры.
Заметки честности
Три оговорки, сказанные прямо, потому что весь смысл контролируемого исследования — не переоценивать его.
- Доходности синтетические. iid нормальные для экспериментов по калибровке и power, процесс со сменой режимов для случая с настоящим edge — выбраны ради контролируемой истины, а не рыночного реализма. Реальные доходности имеют толстые хвосты, автокоррелированы и нестационарны, и члены skew/kurtosis в PSR существуют именно для того, чтобы справляться с первым из этого. Результат здесь — откалиброванный метод, а не стратегия: доказать, что тест контролирует ложные открытия, можно только прогнав его на данных, где мы знаем, что открывать нечего. А для этого нужно сфабриковать эту истину.
- Ни один оценщик effective-N не канонический — поэтому мы привели пять. Однострочник средней корреляции понятен рецензенту и верен по направлению (больше корреляции ⇒ меньше эффективных испытаний), но это коэффициент снижения дисперсии для среднего — функциональное несоответствие с бенчмарком максимума у DSR, — и около он полностью отключает дефляцию. Оценщики на собственных значениях (participation ratio, PCA-95%, Kaiser) подходят лучше, но все равно эвристичны, а Cheverud-Nyholt переоценивает при равномерной корреляции. Более полный, принципиальный подход — это кластеризация испытаний (DSR Appendix 3 у Bailey & López de Prado): группировать испытания по структуре корреляции и считать кластеры, а не схлопывать все в один скаляр. Мы приводим всю полосу именно потому, что выбор не решен окончательно — вердикт, устойчивый по всем пяти оценщикам, это честное утверждение; утверждение, зависящее от выбора одного оценщика, честным бы не было.
- Bootstrap — это студентизированный Reality Check, а не полный Hansen SPA, и число ресэмплов различается по экспериментам. Везде, где эта статья говорит "SPA-типовой", имеется в виду Reality Check Уайта с постатейной (per-rule) студентизацией; полное согласованное, зависящее от выборки рецентрирование Hansen не реализовано. False-discovery rate для калибровки использует 500 stationary-bootstrap ресэмплов на поиск по 400 поискам; два p-value RC/SPA-типа из кейс-стади используют по 5,000 ресэмплов каждый. Средняя длина блока 20 везде (Politis-Romano), , 252 периода в году для аннуализации. Измените это, и числа в третьем знаке после запятой сдвинутся; но сюжет — наивные 1.000 против принципиальных 0.001-0.057, S-кривая, достигающая 50% power чуть выше потолка шума, и ловушка коррелированной сетки, чей вердикт нужно читать по полосе effective-N, — не изменится.
Выводы
- Поиск параметров — это машина multiple testing, и наивный тест значимости к этому слеп. На 1,000 стратегий с нулевым edge лучший годовой Sharpe в среднем равен 1.63 при медианном p-value одиночного теста 0.000686 — и тест "значимо ли это?" объявляет открытие в 100% случаев (false-discovery rate 1.000). Отличный Sharpe из ничего, сертифицированный как значимый тестом, который никогда не задавал правильного вопроса.
- Deflated Sharpe Ratio сдвигает планку с нуля на потолок шума. DSR сравнивает победителя не с нулем, а с — ожидаемым лучшим-по-удаче результатом поиска такого размера, который для нулевого случая приходится на годовые 1.63, ровно там, где сидит средний шумовой победитель (вывод: ). Его нулевой false-discovery rate — 0.001; haircut Harvey-Liu (Bonferroni/Holm 0.057, BHY 0.007) и Reality Check Уайта (0.022) достигают того же контроля другими путями.
- Он сохраняет настоящие edge. Detection power DSR вычерчивает S-кривую, достигающую 50% power при годовом Sharpe ~1.73 — чуть выше потолка шума 1.63: 0.005 при истинном годовом Sharpe 0.79, 0.651 при 1.90, 0.998 при 2.54, 1.000 при 3.17, false positives ~0 на всем диапазоне. Edge ниже потолка правильно признаются неотличимыми от удачи; edge выше него сохраняются с power, приближающимся к единице.
- Коррелированные сетки ломают сырой DSR — и спасает не одно эффективное-N, а вся полоса. На 640-ячеечном MA crossover (средняя попарная корреляция ~0.61) DSR с сырым счетом ложно отверг настоящий (in-sample отобранный, годовой 3.92) edge (0.748 < 0.95), потому что 640 коррелированных испытаний — не 640 независимых ставок. Но решение — не в одном магическом : при самой грубой оценке () дефляция практически отключена (планка ~годовая 0.25), и DSR просто повторяет сырую значимость. Реальное свидетельство в том, что edge сохраняется по всей полосе стандартных оценщиков — DSR 1.000/1.000/1.000/0.999 при 1.6/2.4/16/21, включая настоящую годовую планку 1.85-2.00 в защитимом среднем диапазоне PCA-95%/Kaiser — выживает при любом и проваливается только при переоценивающем 370 у Cheverud-Nyholt. Случайное блуждание отвергается при каждом оценщике. Читайте полосу, а не точку.
- Спаривайте DSR с Reality Check, потому что они отвечают на разные вопросы. Reality Check и его SPA-типовой (студентизированный) родственник подтвердили настоящий edge (p = 0.0024 и 0.0038) без всякой хирургии над счетом испытаний — они обрабатывают зависимость естественным образом через stationary bootstrap, и это ровно тот решающий фактор, когда effective-N оспаривается. DSR спрашивает "особенный ли победитель внутри этого поиска?"; RC/SPA-типовой тест спрашивает "обыгрывает ли лучший кэш после data-snooping?" Расхождение между ними — сигнал, что ваш неверен. Запускайте оба.
Победитель поиска виновен, пока не доказано обратное. Наивное p-value — не доказательство невиновности, это собственные раздутые показания поиска, и они поручатся за чистый шум с двенадцатью нулями уверенности. Дефлируйте бенчмарк до того, что дает удача, честно посчитайте свои эффективные испытания и bootstrap-ните максимум для второго мнения. То, что проходит все три планки, возможно, реально. То, что проходит только наивную, — это самый высокий из тысячи людей, подбрасывающих монету.
Полный эксперимент — стенд калибровки на нуле, развертка power по заложенному edge, поиски на коррелированных сетках, и каждое число в этой статье, регенерируемое одним детерминированным скриптом, — в статье-компаньоне на deflated-sharpe.marketmaker.cc, код и данные — на github.com/suenot/deflated-sharpe-search.
Авторы
Инженер торговых систем
Разработка торговых ботов с 2017 года: межбиржевой арбитраж (подключал до 30 бирж), парный арбитраж на коинтеграции между спотом и фьючерсами, скальпинг, фронтраннинг, торговля по новостям, сентиментный анализ, трендовые алгоритмы, а также алгоритмы управления и балансировки портфелей. Делает выставление ордеров до 1 мс, warehouse для big data, бэктестинг-движки, AI-агентов и интерфейсы для ботов (в т.ч. open-source profitmaker.cc). Стек: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, архитектура.