Commit f4072bb
committed
feat(store): LocalTieredStore — Tier-1 SQLite + Tier-2 Parquet (epic #540 phase 3b)
Second slice of Phase 3 of epic #540. Adds a real tiered storage
implementation that ships the analytics value (cross-run DuckDB /
Polars queries) without yet replacing the canonical .iafbt bundle.
Layout under <root>:
index.sqlite Tier-1 (always in sync)
bundles/<handle>.iafbt canonical bytes
parquet/portfolio_snapshots/run_id=<h>/... Tier-2 hive-partitioned
parquet/trades/run_id=<h>/... Tier-2
parquet/orders/run_id=<h>/... Tier-2
Phase 3b deliberately keeps the bundle as the canonical representation;
Tier-2 sidecars are auxiliary, written best-effort, and a malformed
sidecar never blocks a write or a read. This trivially preserves
byte-identical Backtest round-trips today. Byte-identical
Tier-2 -> Backtest reassembly (no bundle on the read path) is Phase 3d.
- decompose.py: Backtest -> flat record lists for snapshots / trades /
orders, adding run_id and window_name columns so downstream tools
group cleanly across walk-forward windows. Extension point for
metric_series and any future kind is the DATASETS tuple.
- LocalTieredStore: implements BacktestStore + SupportsCopyFrom.
write() saves the bundle, upserts the Tier-1 row, and writes
hive-partitioned Parquet sidecars per dataset. delete() removes all
three tiers. iter_index_rows() serves from SQLite directly.
rebuild_index() recreates Tier-1 from the bundles (useful after a
software upgrade that adds new index columns).
- scan('portfolio_snapshots' | 'trades' | 'orders') returns a
pyarrow.dataset.Dataset that DuckDB / Polars can query across every
run with partition pruning on run_id.
- 15 new tests: Protocol + SupportsCopyFrom conformance, three-tier
layout, handle normalisation, round-trip, summary_only, Tier-1
always-in-sync (write/delete/len), Tier-2 cross-run scan, copy_from
from LocalDirStore, rebuild_index, missing-handle errors. Includes
a synthetic-records test that asserts hive partitions are written
and that scan() returns the expected rows + columns.
Targeted suite (backtest_store + backtest_index + cli): 101 / 101 passing.1 parent 13d8a58 commit f4072bb
4 files changed
Lines changed: 723 additions & 0 deletions
File tree
- investing_algorithm_framework/services/backtest_store
- tests/services/backtest_store
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| 22 | + | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| |||
27 | 28 | | |
28 | 29 | | |
29 | 30 | | |
| 31 | + | |
30 | 32 | | |
Lines changed: 70 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
0 commit comments