WealthPilot
A portfolio auditor that simulates every goal in a C++ Monte Carlo engine and flags what's off.

- backend tests
- 180
- line coverage on the analytics engine
- 99%
- tests on the C++20 simulation engine
- 34
- writes the public demo accepts
- 0
Overview
WealthPilot reads a Zerodha account through Kite Connect and answers the question the broker's app can't: will each goal make it? The analytics engine is plain Python functions with no framework in them, so it's tested on its own. The one CPU-heavy job, simulating thousands of market paths per goal, runs in a C++20 service behind gRPC instead of in the request path. Around it: a daily snapshot job, a live price stream, and an access token that expires every day and is detected and recovered instead of failing. The public demo runs on a fictional investor, read-only.
More screens

Problem → built → result
- Problem
- A broker app shows balances. It can't say whether a goal will actually be met.
- Built
- Next.js on async FastAPI, a C++20 Monte Carlo engine over gRPC, a rules engine for risk.
- Result
- 180 backend tests · 99% engine coverage · live demo
Features
- Monte Carlo goal simulation in a multi-threaded C++20 service behind gRPC, with an in-process fallback so the backend runs and tests without it
- A pure analytics engine (bucket classification, risk rules and goal glide-paths) at 99% line coverage, flagging concentration, sector clusters and drawdowns
- Kite Connect's daily token expiry is detected, surfaced and recovered; a scheduled job snapshots the portfolio each weekday
- Orders only through a human-in-the-loop sell flow: a dry run by default, placed only on explicit confirmation
- A public demo mode that serves a fictional portfolio read-only: every write is refused and every key dropped, even if the environment sets one
Decisions
- 1
Move only what's CPU-bound.
Simulating thousands of market paths per goal is the one heavy job, so only it runs in a multi-threaded C++20 service behind gRPC. An in-process fallback keeps the backend running and testable without it.
- 2
Keep the engine free of frameworks.
Bucket classification, risk rules and goal glide-paths are plain Python functions with nothing to mock, which is what keeps 99% line coverage cheap to hold.
- 3
Expect the token to expire.
Kite Connect's access token expires every day, so expiry is a normal state that's detected, surfaced and recovered, not an error the page falls over on.
- 4
A human places every order.
The sell flow is a dry run by default and places an order only on explicit confirmation. The public demo goes further: every write is refused and every key dropped.
Why it's shaped this way
Only the simulation is CPU-bound, so only the simulation moved out of Python. Everything else stays where it's easiest to test, and every number the page shows comes from an engine with tests behind it.