2.5 KiB
BT-002 Historical Options Snapshot Provider
What shipped
BT-002 adds a point-in-time historical options snapshot provider for backtests.
The new provider lives in app/services/backtesting/historical_provider.py and plugs into the same BacktestService / engine flow as the existing synthetic provider.
Provider contract
The snapshot provider exposes the same backtest-facing behaviors as the synthetic provider:
- load underlying daily closes for the scenario window
- validate
ProviderRef - open positions at scenario start using only the entry-day snapshot
- mark open positions later using the exact same contract identity
This lets backtests swap:
- synthetic pricing:
synthetic_v1 / synthetic_bs_mid - observed snapshot pricing:
daily_snapshots_v1 / snapshot_mid
Contract-selection rules
The provider uses explicit, deterministic, point-in-time rules:
- filter to the entry-day option chain only
- keep contracts with expiry at or beyond the target expiry date
- choose the nearest eligible expiry
- within that expiry, choose the nearest strike to the target strike
- on equal-distance strike ties:
- puts prefer the higher strike
- calls prefer the lower strike
These rules avoid lookahead bias because later snapshots are not consulted for entry selection.
Daily mark-to-market rules
After entry, the provider marks positions using the exact same contract_key.
It does not silently substitute a different strike or expiry when the original contract is missing.
Current fallback policy:
- use the exact same contract from the same-day snapshot
- if missing before expiry, carry forward the previous mark for that same contract and emit a warning
- if the valuation date is at or after expiry, settle to intrinsic value and close the position
Data-quality tradeoffs
The current BT-002 slice intentionally keeps the data model simple:
- snapshots are assumed to provide a precomputed daily
mid - the provider does not currently derive mids from bid/ask pairs
- missing exact-contract marks are explicit warnings, not silent substitutions
- the engine currently still supports
continuous_unitssizing for snapshot-backed runs
Known limitations / follow-up
This slice does not yet include:
- file-backed or external ingestion of real historical snapshot datasets
- listed-contract rounding / contract-size-aware position sizing
- persistent run-status objects beyond template-level warnings
Those follow-ups should remain explicit roadmap work rather than being implied by BT-002.