📉 1000 сделок в бэктесте — это 1000 независимых ставок? Чаще всего нет.
Спор о бэктесте обычно идёт про то, хороша ли кривая. Сначала надо спросить другое: сколько в ней НЕЗАВИСИМЫХ наблюдений. От этого числа зависит, насколько кривой вообще можно верить, — и оно почти всегда меньше числа строк в журнале.
🧮 «У меня тысяча сделок, выборка огромная»
Строка журнала — не ставка. Десять входов в одну сторону на одном движении — это одна идея, сыгранная десять раз. Лестница, которая докупает поверх стоящей позиции, — одна ставка, нарезанная на куски. В одной такой системе на фьючерс MXI я насчитал 84 % входов, открытых поверх уже стоящей позиции.
Сколько ставок на самом деле, считает поправка на кластеры:
N_eff = N / (1 + (m − 1)·ρ)
N — строк в журнале, m — средний размер «пачки» сделок на одной идее, ρ — корреляция результатов внутри пачки. Если пачек нет, а результаты цепляются друг за друга во времени, та же идея через автокорреляцию:
N_eff = N / (1 + 2·Σρₖ)
Пример: 1000 сделок, пачки по 10, ρ = 0,5. Знаменатель 5,5, N_eff ≈ 180. Значимость стоит на корне из N: t-статистика 4,0, посчитанная по строкам, превращается в 1,7 по ставкам. Было «точно не случайность», стало «может быть».
🔍 «Profit Factor 2,5 — я гений»
Слишком хороший результат на малом числе независимых ставок — сначала повод искать ошибку, потом хвалить систему. Три частые причины:
— заглядывание вперёд: решение принято по цене закрытия бара, а исполнено по открытию того же бара;
— псевдорепликация: одна идея посчитана как десять сделок, см. выше;
— утечка из будущего через данные: склейка фьючерсов, пересчитанная назад, или параметры, подобранные на всём ряду.
Две проверки, которые ловят это механически. Сдвиньте исполнение на один бар позже: честный край слабеет плавно, а заглядывание обваливается в ноль. Прогоните систему на перемешанных доходностях того же инструмента: там она обязана дать ноль минус издержки. Если зарабатывает — ошибка в коде.
📈 «Walk-forward прошёл — система устойчива»
Скользящая проверка честна в одном: каждый кусок проверки лежит после своего окна подбора. Но окна подбора соседних шагов почти целиком совпадают. Подбор на 12 месяцах со сдвигом на месяц — соседние окна общие на 11/12. За 10 лет истории это 108 переоптимизаций, а непересекающихся окон подбора среди них 9. Параметры, выбранные на соседних шагах, — почти одно и то же решение, а не 108 независимых подтверждений.
Как пересечение подделывает вывод, я видел на своём замере. Проверял, сохраняется ли порядок вариантов параметра от окна к окну. Полное окно против собственной второй половины дало ранговую корреляцию 0,97 — «порядок переносится». Две непересекающиеся половины того же ряда — 0,20: не переносится. Прибор тот же, вердикты противоположные, разница целиком в пересечении.
Склеенная кривая проверки превращается в коллаж из одних и тех же лет, только если шаг меньше окна проверки — тогда один день попадает в неё несколько раз. В обычной схеме этого нет, и обвинять её в этом не нужно.
⚠️ Оговорка, без которой пост будет враньём
Поправка на кластеры требует знать ρ, а её оценка по тем же данным тоже шумит. Число N_eff — порядок величины, а не точный ответ: 150 или 250, но точно не 1000.
0,97 и 0,20 сняты на одной системе и одном инструменте; на другом ряду цифры будут другими, направление — то же.
И главная дыра скользящей проверки — не пересечение, а выбор её самой. Длину окна, шаг и критерий подбора тоже выбирают, обычно после нескольких попыток. Перепробовали пять схем и показали лучшую — склеенная кривая снова стала подгонкой.
💡 В сухом остатке
Считайте ставки, а не строки: N_eff, а не длину журнала. Слишком хороший результат на малом N_eff — сначала сдвиг на бар и перемешанный ряд, потом радость.
Walk-forward описывает, как система меняет параметры во времени. Доказательством устойчивости служат непересекающиеся окна и отложенный кусок истории, который ни разу не участвовал ни в подборе, ни в выборе схемы проверки.
