FI Simulator

← Back to Projects

A probabilistic financial-independence planner for India. You enter your real numbers and what “financially free” means to you; it runs thousands of simulated futures — market volatility, inflation, income changes, life shocks — and shows the probability your plan holds, roughly when you could get there, what could derail it, and which changes move the odds the most.


1. Problem Statement

Bank apps show you a balance, not a future. Traditional retirement calculators answer a narrower question — “if I invest ₹X at Y% for Z years, what do I get?” — as if markets, careers and lives ran in a straight line. They don’t, and the single number they return is falsely precise.

The question people actually want answered is “Am I on track — and if not, what specifically should I change?” That needs an honest treatment of uncertainty, and it needs to be about decisions, not just a corpus figure.


2. What It Does

Set up — a ~10-question quick-mode wizard (age, income, expenses, current investments, monthly investment, step-up, FI age, target retirement spending, equity/debt split, life expectancy) with inline validation and a one-click “Try an Example” scenario. The simulation starts running in the background as soon as the minimum inputs exist — there is no “calculate” button.

Understand — the results dashboard:

Output What it shows
Success probability A score with plain-language bands (Fragile → Needs work → Reasonably strong → Strong → Very robust) instead of a fake-precise percentage
FI-age distribution Median / optimistic / conservative age you could become financially independent
Wealth fan chart The signature visual: inflation-adjusted wealth over time, 10th–90th percentile band
Real vs. nominal net worth Toggle between today’s rupees and future rupees — “₹8 crore at 60” is not what it sounds like
“What could go wrong” The biggest threats to your plan, computed from counterfactual runs
Result narrative A deterministic, template-driven paragraph explaining the numbers (no LLM)

Stress tests — 2008-style crash near retirement, multi-year career break, high-inflation stretch, one-time medical shock, long life, and combinations. Each returns a survives / becomes fragile / fails verdict.

Explore — the Action Explorer, framed entirely as “here’s what happens if you try X”, never “you should do X”: a one-change experiment, a side-by-side what-if table, a binary search for the minimum monthly investment that hits a chosen probability target, a tornado/sensitivity chart, a time-vs-money tradeoff grid, four-way scenario comparison, and a Pareto frontier of monthly-investment × retirement-age combinations that all reach the same probability.

Share & export — a share link that encodes only headline numbers into the URL, plus JSON / CSV / PDF export.


3. System Architecture

graph TD A[Browser] --> B[Next.js App Router\nUI components only] B --> C[Web Worker\n10,000-path Monte Carlo] C --> D[lib finance modules\nisolated engine — 12 modules] D --> E[Versioned assumptions config\nreturns, inflation, volatility] B -.->|localStorage| F[Scenario state\nnever sent to a server] B --> G[Server-rendered /shared route\ndecodes summary from URL for link previews]

Everything runs client-side. The only server-rendered route is /shared, which decodes a scenario summary out of the URL for link previews. Running cost stays near zero regardless of traffic, and the product can honestly say your financial inputs never leave your device.


4. Tech Stack

Layer Technology
Framework Next.js 16 (App Router) + React 19
Language TypeScript
Styling Tailwind CSS v4
Charts Recharts (lazy-loaded per page)
Simulation Web Worker, typed numeric arrays
Testing Vitest (23 files, 152 tests)
Hosting Vercel — no backend

5. Key Engineering Decisions

No backend — everything runs in the browser. All simulation runs client-side; scenario state lives in localStorage. This does two things at once: running cost stays near zero regardless of traffic, and the product can honestly claim financial inputs never leave the device.

Monte Carlo in a Web Worker, on typed arrays. The 10,000-path simulation would jank the UI on the main thread, so it runs in a worker — chunked, with cooperative cancellation so a new run interrupts a stale one. The engine uses typed numeric arrays rather than allocating an object per path. A lighter ~1,500-path run updates live while you drag a slider; the results screen runs the settled 10,000+ paths, and recent results are cached so small nudges don’t always trigger a fresh run.

The finance engine is completely isolated from the UI. Every formula lives in lib/finance/* — 12 focused modules (deterministic, monteCarlo, explorer, comparisons, inflation, portfolio, debt, goals, risk, statistics, validation, narrative). Components never compute anything; they only render numbers the engine returns. The public surface is essentially one function, simulateScenario(scenario, options) — so the engine could later move to a Python service for research-grade runs without touching the product.

Assumptions are data, not code. Default returns, inflation and volatility live in a single versioned config. Every value records whether it is nominal or real, before or after tax and fees, its source, and an as-of date. Nothing else in the codebase hard-codes “12% equity returns” — every screen reads from the config or from a scenario seeded from it.

Performance & accessibility. Lazy-loading the five Recharts charts per page cut first-load JS on the heavy screens from ~960 KB to ~600 KB. Accessibility targets WCAG 2.2 AA: full keyboard navigation, an sr-only live-region announcer for simulation status, prefers-reduced-motion respected on every animated chart, a “show as table” disclosure for each chart, and Indian currency formatting (₹1,00,000 / ₹1.2 crore).


6. Testing & Correctness

A financial simulator can’t be verified by eyeballing outputs, so the suite (23 files, 152 tests via Vitest) leans on properties that must hold regardless of the random draw:

  • No returns — with return = 0 and fixed contributions, final wealth = starting wealth + contributions − withdrawals, exactly.
  • Inflation — future value matches PV × (1 + g)^years.
  • Deterministic benchmark — a fixed-return/-inflation scenario matches an independently hand-calculated corpus.
  • Zero volatility — with volatility set to 0, 10,000 simulated paths collapse to effectively one trajectory.
  • Monotonicity — saving more never lowers success probability; retiring later never lowers it; spending more in retirement never raises it.
  • Reproducibility — same seed + same parameters ⇒ identical output, and scenario comparisons reuse common random numbers so the delta isn’t noise.

On top of that: jsdom component tests, an accessibility smoke test, and worker/provider glue tests. pnpm run ci runs typecheck + lint + test + build and is wired to GitHub Actions.


7. Design & Trust Constraints

The product is positioned as financial education and scenario analysis, not investment advice — and in India that distinction is regulatory, not just tonal. SEBI has historically treated automated tools that take a user’s inputs and hand back a personalised ranked recommendation as falling under investment-adviser registration. So the Action Explorer never ranks or recommends: the user picks what to try, and the tool reports what happens. That framing is a load-bearing product decision.

Other rules the UI follows throughout: probability is shown as bands, never 83.271%; every material assumption is visible and editable on the results page; net worth is kept visually distinct from the portfolio that can actually fund retirement; and the copy never says “you will have ₹X” — only “in the simulated futures, the median is ₹X, and the middle 80% ranges from…”.


8. Current Status

Built solo in about a week (~60 commits over a handful of sprints). Feature-complete through the planned V1.1 scope. Deployed but not publicly launched — the default market/inflation assumptions are the spec’s suggested starting values, marked as placeholders in the config, and need an independent sourcing pass before it would be responsible to put in front of real users.

Also still open: a real-hardware mobile and screen-reader smoke pass; a UI surface for the sequence-of-returns illustration (the engine already computes it); and a “historical India mode” that block-bootstraps Nifty TRI / fixed-income history instead of a theoretical distribution.