1 Ноября 2026 · исследование

Как прогреть бэктест, не засчитывая lookback как результат?

Как прогреть бэктест, не засчитывая lookback как результат?

20-дневный Donchian в спецификации выглядит безобидно. Агент пишет 20-барный скользящий максимум, бэктест стартует с первой строки parquet-файла, и первые 2 недели «20-дневный максимум» — это просто нарастающий максимум по тем барам, которые уже есть. На 4-й день это 4-дневный максимум. Стратегия, которую вы думали тестируете, — не та, что породила первый десяток исполнений.

У меня есть ноутбук по дневным барам ETHUSDT, где Sharpe на полной выборке равен 1.4. Отрежьте первые 20 сессий — и он падает до 0.6. Оставьте эти 20 и выбросьте остаток первого года — и он печатает 3.1. В завтра никто не утекал. Стратегия использовала прошлое, просто недостаточно прошлого, а отчёт принял эти недостроенные сделки за доказательство.

1.4Sharpe на полной выборке, незавершённое окно включено
0.6тот же код после 20 завершённых сессий
3.1Sharpe, если оставить только сделки прогрева

Пусть окно торгует, пока ещё наполняется

Обычная катастрофа — min_periods=1. Pandas посчитает скользящее среднее по одному бару, если вы ему позволите. Агенты делают это постоянно: NaN вверху фрейма ощущается как баг, а заполнить его — и unit-тест зеленеет.

20-дневный таргет realized-vol с 2 наблюдениями доходности — это взрыв размера. Дисперсия 2 чисел — это орёл или решка: вы её инвертируете, и первая позиция оказывается в несколько раз больше задуманного риска. Z-score относительно почти нулевого стандартного отклонения проделывает тот же трюк со знаком: кажется, у стратегии бритвенно точный вход, который больше никогда не появляется, как только окно становится честным.

Пробои хуже, потому что выглядят как настоящее правило. 20-барный канал на баре 6 — это 6-барный канал. Вы получаете кластер сделок сразу на старте, часто на спокойном участке, который не сработал бы у достроенного индикатора. Спокойные рынки чуть дрейфуют. Узкий канал стреляет. Кривая капитала получает фору, которую ни один более поздний год не повторяет.

Заполнение нулём и forward-fill выдумывают другую ложь. RSI, равный 0, читается как перепроданность. Отсутствующий ATR, равный 0, взрывает размер юнита, и бэктест послушно покупает склад. Я лучше позволю NaN убить заявку, чем дам 0 её выдумать.

Я до сих пор ловлю себя на том, что рисую график со строки 0, потому что пустой месяц слева на чарте выглядит незавершённым. Пустой месяц — это как раз честная часть.

Обрезать кривую капитала, сохранить позицию

Эта проходит код-ревью. Вы корректно считаете 20-дневные признаки, выбрасываете первые 20 строк из нарисованной кривой и публикуете с 21 января. Позиция 21 января была открыта 14 января. High-water трейлинг-стопа, счётчик пирамиды, кэш после этих сделок прогрева: всё это вошло в «чистую» выборку.

Катастрофа — бумажная стратегия, которую нельзя запустить с даты из статьи. Перезапустите с нулевой позиции на заявленной дате старта — и заявки первой недели не совпадут. Иногда бэктест уже в сделке, в которую бумажной системе нечем входить. Иногда бумажная система входит, потому что её lookback холодный, а бэктест сидит в стороне, потому что скрытый месяц уже взял пробой. Две стартовые книги, одна опубликованная дата старта.

Фолды walk-forward делают это тихо. У каждого тестового окна есть хвост lookback, который вы не рисуете. Не симулировать этот хвост — и первые тестовые сделки снова сделки незавершённого окна. Симулировать его и отчитываться только по тестовым дням — и позиция тестового дня обусловлена исполнениями, которые вы не показываете. Второй вариант может быть законным исследовательским выбором. Называть первое утро фолда холодным стартом, пока трейлинг-стоп уже жив с хвоста, — вот как два исследователя получают два Sharpe из одной конфигурации.

Если перезапуск с нулевой позиции на опубликованной дате старта меняет P&L, прогрев сидит в трек-рекорде. Данные lookback могут быть. Сделок lookback быть не может.

Прогревать в календарных днях, когда признак — не день

«Дайте ему 30 дней» оставляет признак недоопределённым. 30 календарных дней на 5-минутном Donchian — это тысячи баров сверх 20-периодного lookback. 30 дней на дневном признаке, которому нужно 20 сессий, — либо жирно, либо тонко, в зависимости от выходных и дыр.

Z-score ставки фондирования на одной из наших perp-площадок получил 30-дневный прогрев, потому что в спецификации стояло 30 периодов, а кто-то перевёл периоды в календарь. Фондирование там публикуется каждые 8 часов. 30 дней — это около 90 расчётов. 30 периодов — это 10 дней. Лишние 2 месяца прогрева случайно захватили неделю депега. Выкинув её, живое окно стало выглядеть спокойнее, чем реальная история стратегии. Люди винили чувствительность к дате старта. Прогрев съел режим.

А крипто против акций заставляет то же число менять смысл без правки параметра. 20 «дней» ETH включают субботы. 20 сессий акций — это почти календарный месяц. Скопируйте 20-дневный lookback из ноутбука по акциям на часовые свечи перпетуалов — и получите 20-часовой канал с 20-дневным именем. Первый валидный бар тогда либо через 20 часов, либо через 20 дней, если какая-то более поздняя функция ресемплирует, и я видел оба варианта в одном и том же diff агента.

Зафиксируйте первую торгуемую метку времени

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

ПризнакЧто обычно пишет спецификацияЧто на самом деле должно существоватьТихая подмена
20-дневный Donchian20 дневных максимумов20 завершённых сессийСкользящий максимум с min_periods=1
30-дневная realized vol30-дневное окно30 доходностей close-to-close2-дневная дисперсия, инвертированная в размер
z-score фондирования на 20 принтах20 дней20 расчётов фондирования20 календарных дней (~90 принтов) или 20 баров неверного таймфрейма
14-периодный RSI на 5m14 периодов14 закрытых 5-минутных баров14 дней или 14 баров с дырами, заполненными forward-fill

P&L до этой метки времени остаётся вне трек-рекорда. Состояние до этой метки времени всё равно может понадобиться симулировать, чтобы трейлинг-стоп или кулдаун были настоящими, когда часы доходят до первого торгуемого бара, но эти исполнения не идут в Sharpe, в число сделок и в расчёт ёмкости. Затем прогоните неприятную проверку: перезапуск с нулевой позиции на этой метке времени, lookback доступен только как данные. Если заявки меняются, вы выкатывали скрытые сделки.

Бумажная торговля стартует по тому же правилу. И каждое тестовое окно walk-forward тоже. Если график выглядит так, будто не хватает месяца, оставьте его недостающим.

бэктестингинженерия данныхwalk-forwardAI-агентыбумажная торговля
ПоделитьсяXLinkedInFacebookRedditHacker NewsWhatsAppTelegramEmail
← Все статьи