feat(BT-002): add historical snapshot provider
This commit is contained in:
66
docs/BT-002_HISTORICAL_OPTIONS_SNAPSHOT_PROVIDER.md
Normal file
66
docs/BT-002_HISTORICAL_OPTIONS_SNAPSHOT_PROVIDER.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# 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:
|
||||
|
||||
1. filter to the entry-day option chain only
|
||||
2. keep contracts with expiry at or beyond the target expiry date
|
||||
3. choose the nearest eligible expiry
|
||||
4. within that expiry, choose the nearest strike to the target strike
|
||||
5. 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:
|
||||
|
||||
1. use the exact same contract from the same-day snapshot
|
||||
2. if missing before expiry, carry forward the previous mark for that same contract and emit a warning
|
||||
3. 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_units` sizing 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.
|
||||
Reference in New Issue
Block a user