Как интерпретировать настройки затрат в бэктесте
Сводка
В этой заметке о конфигурации различаются настройки, которые входят в идентификатор бэктеста, и настройки, действительно влияющие на моделируемые торговые затраты. В рассматриваемом исследовании все зарегистрированные запуски используют векторизованный путь с расчётом доходности до экспирации. Настроенные поля цены исполнения, ставки комиссии и ставки проскальзывания в этот путь не передаются; исполнение по стороне котировки относится к событийно-ориентированному брокеру, которого векторизованные запуски не создают. Настройки остаются в конфигурации, поскольку их удаление изменило бы хешированный идентификатор существующих запусков.
Смоделированные затраты отдельно считываются из файла настройки: спреды входа и выхода по опционам, оценочные спреды хеджирования при каждой ребалансировке и комиссии за контракт или акцию. В заметке указано, что записанное поле суммарного проскальзывания имеет значение null для всей указанной совокупности, хотя затраты начислялись, поскольку этот путь не записывает общие суммы затрат. Это полезный урок для аудита: одно лишь значение конфигурации или отсутствие метрики затрат не показывает, сколько стоил бэктест. Выводы относятся к указанной реализации; их нужно перепроверить, если изменятся запускающий код или механизм передачи затрат.
Ключевые идеи
- Поля конфигурации могут влиять на хешированный идентификатор запуска, даже если путь исполнения их не использует.
- Описанный здесь векторизованный путь с расчётом доходности до экспирации не использует настроенные ставки комиссий и проскальзывания.
- Смоделированные затраты складываются из отдельных затрат на опционы, хеджирование и ликвидацию.
- Значение null в поле суммарного проскальзывания не доказывает, что затраты не взимались.
- Для интерпретации затрат нужно проследить конкретный запускающий код и поток данных.
Теги
Полный текст
# base.yaml ```yaml # Three fields below are inert on the path this case study runs: `execution.execution_price`, # `commission.rate` and `slippage.rate`. Every registered backtest here is `ret_to_expiry`, # which `case_studies/utils/backtest_runner.py` routes to `_run_htm_daily_mtm`, and that call # is not passed `cost_spec` - the only thing that carries these rates into a run. The # `quote_side` fill is read by the event-driven broker, which a `rebalance.mode: vectorized` # case study never constructs. They still reach the registered `backtest_config` and so the # hashed identity, which is why they stay: removing them would re-key 879 backtests to delete # values nothing reads. # # The costs this case study actually pays come from `_htm_backtest.py`, which reads # `config/setup.yaml::costs.components` directly - per-leg entry spread from the real option # quotes, `hedge_spread.estimate_bps_of_notional` on every hedge rebalance, # `commission.option_per_contract` and `commission.equity_per_share`, plus an exit spread on # liquidation. Verified 2026-09-12; `total_slippage` is NULL on all 879 rows because the # vectorized path records no cost totals, not because nothing was charged. account: allow_short_selling: true execution: execution_price: quote_side mark_price: price execution_mode: next_bar commission: model: percentage rate: 0.0005 slippage: model: percentage rate: 0.0002 calendar: calendar: NYSE timezone: UTC data_frequency: daily feed: timestamp_col: timestamp entity_col: symbol price_col: instr_mid close_col: close bid_col: instr_bid ask_col: instr_ask mid_col: instr_mid metadata: case_study: sp500_options ```
Полный текст с указанием источника опубликован на условиях его лицензии. Лицензия: MIT
Это краткое изложение подготовлено исследовательским агентом Stratmill по оригиналу и не является его копией.