Есть вопрос, от которого любой бэктест уклоняется: сделал бы тот же код то же самое, если бы получал тот же рынок вживую? Ответить на него дополнительным бэктестингом невозможно. Ответ даёт только запуск стратегии на живых данных с настоящей семантикой исполнения и последующая проверка — сделка за сделкой — что оба мира сходятся. Мы делаем эту проверку каждый день, автоматически, и она оказалась самым продуктивным охотником за багами во всей платформе.
День первый: строим зеркало
Каждая продвинутая в бумажную торговлю стратегия работает в собственном изолированном живом узле и потребляет реальные биржевые потоки: живые котировки для исполнений, реальные спреды, реальные торговые сессии. Никакого общего состояния между стратегиями — этот урок мы усвоили на собственном опыте: в общем узле запросы позиций одной стратегии протекали в другую. Каждое исполнение записывается вместе со значением сигнала, которое его породило.
Каждое утро: реплей и сравнение
Ежедневная задача берёт бумажное окно каждой стратегии, прогоняет идентичный код через бэктест-движок за тот же период на данных каталога и сопоставляет исполнения один к одному: та же сторона, тот же допуск по времени, тот же размер. На выходе — не корреляция и не «на глаз». На выходе таблица: совпало, только на бумаге, только в реплее. Здоровая стратегия держится на уровне 54 из 55 совпадений. Нездоровая точно показывает, какая сделка разошлась и когда.
Что ломалось — в том порядке, в каком ломалось
- Исполнения на прогреве. Живой узел скармливал историю для прогрева индикаторов — и стратегии с собственными обработчиками баров бодро торговали на ней. Бэктесты этих фантомных входов не видели никогда. Починка легла на уровень подачи заявок, а не на саму стратегию: иначе этот баг наследует каждая стратегия.
- Последовательный прогрев многоногих стратегий. Кросс-секционная стратегия прогревалась по одному инструменту за раз; каждая нога видела пустых соседей, и якорь так и не инициализировался. Вживую она не торговала вообще; в реплее торговала нормально. Ноль совпавших сделок — но сказало об этом вслух только сравнение.
- Крэш-циклы из-за точности тиков. Живые тики aggTrade приходят с иной точностью, чем ожидает инструмент песочницы. Узел уходил в крэш-цикл на проверке, которую бэктест не мог вызвать в принципе, потому что бары каталога уже нормализованы.
- Амнезия после перезапуска. Перезапуск процесса заново запускал логику входа по уже существующим позициям — для ребалансирующей стратегии перезапуск втихую превращался в ребалансировку. В реальной торговле это не сноска о паритете; это красный флаг, к которому привязаны деньги.
Обратите внимание на закономерность: ни один из этих багов не относится к сигналу. Все они — баги на границе исполнения: прогрев, состояние, точность, перезапуски. Это ровно тот класс отказов, к которому бэктесты структурно слепы, потому что в бэктесте бэктест-движок и есть граница исполнения.
Асимметрии, которые мы сохраняем намеренно
Два мира сознательно не идентичны. Бэктест списывает моделируемый половинный спред плюс корневое влияние на рынок внутри PnL; бумажная торговля платит реальный спред в цене исполнения и не моделирует влияние вовсе. Добавить моделируемый спред в бумажную торговлю (или реальный — в бэктест) значило бы посчитать его дважды. Паритет означает те же решения, те же исполнения в пределах допуска, а не побитово одинаковый PnL. Понимать, какие различия обоснованы, а какие являются багами, — и есть бо́льшая часть дисциплины.
Бэктест — это гипотеза. Бумажная торговля — эксперимент. Паритет реплея — лабораторный журнал, который ловит вас на самообмане.
Если вы запускаете стратегии и не сравниваете регулярно живое поведение с воспроизведённым, у вас есть целый класс багов, которых вы ни разу не видели. Мы находим по одному примерно раз в пару недель, и каждый из них был невидим изнутри бэктеста.
← Все статьи
