fire-planner/README.md
Viktor Barzin 6efe3b0c31
Some checks failed
Build and Push / lint-and-test (push) Has been cancelled
Build and Push / build (push) Has been cancelled
Build and Push / deploy (push) Has been cancelled
Build and Push / notify-failure (push) Has been cancelled
docs(fire-planner): document FIRE countdown; flag stale playbook
README: add spend_model/geo/fire_target modules, the recompute-fire-targets
command, and the fire_target table. PLAYBOOK_VIKTOR.md: add a superseded-notice
header — it anchors on Cyprus/£1.5M/£60k, but the base case moved to Bulgaria,
real NW is ~£1.13M, and the simulator now drains tax (so its regime-invariant
claim is false). Point readers to the live FIRE Countdown dashboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 11:53:41 +00:00

2.5 KiB
Raw Blame History

fire-planner

Risk-adjusted, tax-minimised FIRE retirement planner. Consumes today's portfolio, savings rate, and RSU vest schedule from sibling services (wealthfolio, payslip-ingest, hmrc-sync) and returns the after-tax probability of success for each combination of jurisdiction, withdrawal strategy, and "year you break UK tax residency".

Layout

  • fire_planner/ — package
    • tax/ — per-jurisdiction tax engines (UK, nomad, Malaysia, Thailand, Cyprus, Bulgaria)
    • returns/ — Shiller 1871+ data + block bootstrap sampler
    • strategies/ — Trinity 4% SWR, Guyton-Klinger guardrails, VPW
    • ingest/ — pulls from wealthfolio / payslip-ingest / hmrc-sync
    • simulator.py — vectorised NumPy MC engine
    • scenarios.py — Cartesian product over (jurisdiction × strategy × leave-UK-year × glide)
    • spend_model.py — per-Case real-GBP spend, COL-scaled per country (the FIRE-countdown cases: Solo / Household / Family)
    • geo.py — COL city → tax jurisdiction
    • fire_target.py — solves each Case's "FIRE number" (smallest liquid NW where Guyton-Klinger hits the 99% bar); see docs/adr/0001
    • app.py — FastAPI on-demand /recompute
    • __main__.pyclick CLI: ingest, simulate, recompute-all, recompute-fire-targets, migrate

Common commands

poetry install
pytest -v
mypy .
ruff check .
yapf --recursive .

# Run migrations against the local DB:
DB_CONNECTION_STRING=postgresql+asyncpg://... alembic upgrade head

# CLI
DB_CONNECTION_STRING=... python -m fire_planner ingest
DB_CONNECTION_STRING=... python -m fire_planner simulate --scenario=cyprus-vpw-leave-y3
DB_CONNECTION_STRING=... python -m fire_planner recompute-all

# Solve the FIRE-countdown targets (per Case × country) for the wealth
# Grafana dashboard's "FIRE Countdown" section:
DB_CONNECTION_STRING=... python -m fire_planner recompute-fire-targets --countries all

Schema

Core tables in fire_planner schema on pg-cluster-rw:

  • account_snapshot — daily NW per account (Wealthfolio)
  • scenario — Cartesian-product scenario definition
  • mc_run — execution metadata + summary stats per (scenario, run_at)
  • mc_path — sparse storage (top decile, bottom decile, median)
  • projection_yearly — deterministic point projection per scenario
  • scenario_summary — denormalised fast-read for Grafana
  • fire_target — solved FIRE number per (Case × country × with-home) for the "FIRE Countdown" section of the wealth Grafana dashboard