Бэктест — это симуляция, а не калькулятор. Если вы прогоняете исторические цены через индикатор и смотрите на кривую доходности, вы почти наверняка обманываете себя. Знакомая история: стратегия идеальна на графике, а на живых деньгах разваливается за пару сделок. Я через это прошёл, поэтому предупреждаю без нравоучений.
Почему наивный бэктест врёт
Простейший бэктест — это цикл по строкам таблицы с ценами. Есть цена, есть скользящие средние, есть условие купить или продать. Но такой цикл игнорирует три вещи, которые превращают реальную торговлю в совсем другую игру.
Первая — look-ahead bias. Индикаторы считаются по всей истории сразу, хотя в каждой точке у вас есть только прошлые данные. Вторая — издержки. Нет комиссий, проскальзываний и влияния ордера на рынок. Третья — исполнение. В модели вы торгуете по цене закрытия, которую только что увидели, а в жизни заявка исполняется по другой цене.
После трёх часов подбора параметров такая стратегия одинаково красиво выглядит в бэктесте и одинаково больно умирает в реале.
Четыре принципа честного бэктеста
- Событийная симуляция. Вместо цикла по заранее посчитанной таблице — подача рыночных событий объекту стратегии в момент, когда они возникают. Решение принимается только на основе данных, доступных в этот момент времени.
- Явные издержки. Проскальзывание, комиссия и рыночное влияние закладываются в каждое исполнение ордера, а не добавляются потом.
- Изолированное состояние. Позиция, цена входа и прочие данные живут внутри объекта стратегии. Так будущее не протекает в прошлое.
- Векторизованная аналитика. Индикаторы считаются быстро и сразу для всего массива, но основной цикл остаётся событийным.
Когда я собрал такую версию, та же стратегия показала реалистичную просадку. И это было лучше, чем красивая кривая: наконец-то стало видно, где именно заканчивается грааль.
Сравнение двух подходов
| Параметр | Наивный цикл | Событийная модель |
|---|---|---|
| Данные для решения | Вся история сразу | Только прошлые данные |
| Издержки | Нулевые | Комиссия и проскальзывание на каждый ордер |
| Исполнение | По цене закрытия текущей свечи | С проскальзыванием против вас |
| Состояние стратегии | Глобальные переменные | Внутри объекта стратегии |
| Кривая доходности | Идеальная | Похожа на реальность |
Как перейти на честный бэктест
Возьмите стратегию на пересечении скользящих средних 50 и 200 на дневных данных SPY и постройте её заново.
- Посчитайте индикаторы векторизованно для всего набора данных — это быстро и удобно.
- Создайте класс стратегии с полями cash, position, commission и slippage.
- В методе исполнения ордера добавляйте проскальзывание как процент от цены и комиссию с оборота.
- В главном цикле идите по строкам данных, но каждое решение передавайте объекту стратегии. Состояние живёт внутри объекта.
- После каждого бара пересчитывайте капитал как сумму денег и стоимости позиции по текущей цене.
Это не занимает много кода. Но именно эти несколько строк отделяют честную проверку идеи от рисования красивых картинок.
Типичные ошибки
- Считать индикаторы на всей истории, а потом решать, будто знали будущее.
- Забыть про комиссию и проскальзывание. Они съедают небольшую часть каждой сделки, а за год — ощутимый кусок доходности.
- Торговать по цене закрытия текущего бара. В реальности придётся брать цену следующего бара или учитывать проскальзывание.
Вывод
Честный бэктест не гарантирует прибыль, но отсекает большую часть самообмана. Начинайте с простой событийной модели с издержками и изолированным состоянием. Код на Python для этого подходит, и через год такой подход не устареет.
Комментарии (0)
Войдите, чтобы комментировать.
Пока нет комментариев. Будьте первым.