Перейти к основному содержимому

Как TradeJS проводит бэктесты торговых стратегий

Бэктест применяет одну конфигурацию стратегии к историческим свечам и моделирует входы, выходы и управление позициями. Он нужен для проверки сформулированной гипотезы и сравнения конфигураций при одинаковых допущениях, а не для прогноза будущей доходности.

Зафиксируйте условия эксперимента

Чтобы результат можно было воспроизвести, сохраните:

  • стратегию и версию её пакета;
  • полную конфигурацию стратегии;
  • коннектор, инструменты и таймфрейм;
  • точные начало и конец периода;
  • источник свечей и правила корректировки данных;
  • комиссии, проскальзывание, модель исполнения и задержку входа;
  • комбинации параметров и правило выбора результата.

Изменение любого из этих пунктов создаёт новый эксперимент.

Запуск

Проще всего начать с веб-приложения по инструкции Первый бэктест. Сохранённую конфигурацию можно запустить через CLI:

npx @tradejs/cli backtest \
--user root \
--config <StrategyName:configName> \
--connector <connector> \
--timeframe <minutes> \
--tickers <SYMBOLS> \
--tests <limit> \
--parallel <workers>

Если локальные сервисы остановлены, сначала запустите их:

npx @tradejs/cli infra-up

Флаг --cacheOnly запрещает обновлять историю и подходит для повторной проверки на уже сохранённых свечах.

Отделяйте издержки исполнения от оценок стратегии

Для воспроизводимого сравнения передавайте издержки моделирования отдельно от конфигурации стратегии:

npx @tradejs/cli backtest \
--config <StrategyName:configName> \
--executionCosts '{"fees":{"makerRate":0.001,"takerRate":0.001},"slippage":{"baseBps":10,"spreadMultiplier":1,"marketImpactBps":0,"delayRiskMultiplier":0},"funding":{"enabled":false}}'

Комиссии задаются десятичной ставкой для одной стороны сделки, поэтому 0.001 означает 0,1%. Проскальзывание ухудшает цену каждого исполнения, а комиссия считается от полученной стоимости исполнения. Значение false в funding.enabled исключает funding из расчёта. Для включённого funding нужна доступная историческая ставка, в том числе при запуске на сохранённых данных.

TradeJS фиксирует объект для всего запуска и включает его в контрольную точку и результат. Продолженный запуск использует те же издержки. Для других допущений создайте новый запуск.

Поля стратегии RISK_FEE_RATE, RISK_SLIPPAGE_BPS и RISK_MARKET_IMPACT_BPS используются отдельно для проверки входа и расчёта позиции. Изменение --executionCosts не меняет эти оценки стратегии, а изменение оценок не меняет моделируемые комиссии, проскальзывание и funding.

Этапы расчёта

  1. Загружается выбранная сетка параметров.
  2. Определяются инструменты и исторический период.
  3. Загружаются или обновляются свечи.
  4. Формируются комбинации параметров.
  5. Комбинации распределяются между параллельными процессами.
  6. Сохраняются сделки и рассчитывается итоговая статистика.

Бэктест и работа с текущим рынком используют одну реализацию стратегии, но условия исполнения различаются. Бэктест не может полностью воспроизвести место ордера в очереди, влияние на рынок, сбои биржи, сетевые задержки и будущую ликвидность.

Перебор параметров

Каждое поле сетки содержит одно или несколько значений. TradeJS проверяет их декартово произведение с учётом ограничения --tests. Размер поиска должен иметь экономическое обоснование, а правило выбора итогового варианта следует зафиксировать заранее.

Большой перебор повышает вероятность случайно получить привлекательный результат. Выбранный вариант нужно проверить на данных, не использованных при выборе, а также на устойчивость к близким параметрам, комиссиям, проскальзыванию и разным рыночным режимам.

Формат и команды описаны в разделе Сетка параметров бэктеста.

Анализ результата

Не ранжируйте конфигурации только по чистой прибыли. Как минимум проверьте:

  • число сделок и время в позиции;
  • доходность после комиссий и моделируемого проскальзывания;
  • максимальную просадку и время восстановления;
  • profit factor, математическое ожидание и распределение результатов сделок;
  • концентрацию по направлениям и инструментам;
  • устойчивость по подпериодам и рыночным режимам;
  • чувствительность к небольшим изменениям параметров и издержек.

Результат имеет смысл только при достаточной длине периода и размере выборки для характерного срока удержания и оборота стратегии.

Необязательные данные для AI/ML

Флаг --ml записывает строки для ML-набора, а --ai — для офлайн-проверки промптов. Эти флаги только добавляют исследовательские данные и не включают AI/ML-фильтры во время бэктеста. Части набора объединяются командами ml-export и ai-export.

Дальше