fire-planner/tests
Viktor Barzin 00ec874889
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
returns: 3 models — Shiller bootstrap (default), manual %, Wealthfolio history
Adds a "Returns model" picker on /what-if that switches how the
simulator's `paths` (n_paths × n_years × 3) is built:

1. shiller (default) — current behaviour, block-bootstrap of the
   Shiller 1871+ historical series (or its synthetic-calibrated
   fallback when the CSV isn't mounted).

2. manual — every year of every path = the user's "real return %"
   input. Deterministic, no fan, useful for sanity checks. New
   helper `constant_real_return_paths` constructs the (n_paths,
   n_years, 3) tensor with stock=bond=real, cpi=0 so the simulator's
   `(1+nominal)/(1+cpi)-1` short-circuits to exactly the input.

3. wealthfolio — pulls daily_account_valuation from the wealthfolio_sync
   PG mirror, sums total_value + net_contribution across accounts per
   day (FX-adjusted), strips contribution deltas to isolate market
   return, compounds daily returns into per-calendar-year samples,
   block-bootstraps with block_size=1 (only ~6 distinct samples
   available, no serial-correlation signal to preserve). Glide path
   is a no-op in this mode — the user's actual blended portfolio is
   treated as a single asset.

API: SimulateRequest gains `returns_mode` ("shiller"|"manual"|
"wealthfolio") + `manual_real_return_pct`. simulate.py's `_build_paths`
dispatches; wealthfolio mode opens a transient session against the
mirror DB.

UI: new Field on the form (next to Strategy / Glide path) with a
contextual hint that explains each option's tradeoff. The "About the
model" panel at the bottom now has a "Returns model" section
mirroring the same content. The Manual % input only shows when
returns_mode='manual'.

10 new tests on the Wealthfolio helper (contribution-stripping,
multi-account aggregation, FX, partial-year drop, TOTAL filter,
empty-input, plus 3 deterministic-paths tests). 198 backend tests +
7 frontend tests. mypy strict + ruff + tsc strict all pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 01:04:25 +00:00
..
__init__.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
conftest.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_api_life_events_goals.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
test_api_networth.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
test_api_scenarios.py api: expand FastAPI surface for scenarios, networth, life-events, goals, simulate 2026-05-09 21:48:36 +00:00
test_api_simulate.py engine+api: plumb life events into the simulator 2026-05-09 22:30:33 +00:00
test_cli.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_db_schema.py schema: add life_event, retirement_goal; extend scenario with kind/parent 2026-05-09 21:36:58 +00:00
test_e2e.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_ingest_wealthfolio_pg.py ingest: switch wealthfolio to pg-sync mirror reads 2026-05-09 21:33:48 +00:00
test_life_events.py engine+api: plumb life events into the simulator 2026-05-09 22:30:33 +00:00
test_reporters_pg.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_returns.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_returns_wealthfolio.py returns: 3 models — Shiller bootstrap (default), manual %, Wealthfolio history 2026-05-10 01:04:25 +00:00
test_scenarios.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_simulator.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_simulator_events.py engine+api: plumb life events into the simulator 2026-05-09 22:30:33 +00:00
test_strategies.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_tax_base.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_tax_other_regimes.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00
test_tax_uk.py Initial extraction from monorepo 2026-05-07 17:06:19 +00:00