Investment Operations Suite
Live back-office platform — five operations modules over one continuously evolving market simulation.
5 ops modules · 1 live market sim · FRED-anchored
The problem
Investment back-office tooling is usually demoed against a one-off CSV. That hides the actual problem: the same trades flow through reconciliation, NAV, data-quality monitoring, document extraction, and the ledger — and they have to agree. The suite is a single market simulator with five operations modules wired on top, so every module sees the same evolving book and the same breaks.
Who this is for
Fund operations / middle-office engineers, anyone interviewing for a back-office or fintech-platform role who wants to see infra-style ML thinking applied to ops.
Architecture
- Market simulator
- Continuously evolving prices anchored to real FRED macro series; drives every module.
- Recon module
- GET /api/recon — pulls internal vs custodian positions, surfaces breaks and aging.
- Reporting module
- GET /api/reporting/mandates → /report/{mandate_id} — NAV, performance, attribution per mandate.
- Data quality module
- GET /api/dataquality — multi-source consistency monitoring (price, holdings, FX).
- Documents module
- POST /api/documents/extract + /ask — trade-confirmation extraction with an SOP-grounded assistant.
- Ledger module
- GET /api/ledger — double-entry accounting over executed trades and cash flows.
Request / data flow
- 01Simulator ticks → prices and holdings update.
- 02Recon snapshots both books, flags breaks above tolerance.
- 03Reporting recomputes NAV / performance from the latest holdings + prices.
- 04Data quality watches the same feeds for inconsistencies before they reach a downstream module.
- 05Documents accepts uploaded trade confirmations, extracts structured fields, and answers SOP questions grounded in policy docs.
- 06Ledger posts double-entry journals from executed trades and aged cash.
Key decisions
One simulator instead of fixtures per module.
whyReconciliation and NAV that disagree on the same trade is the whole interesting failure mode. Per-module fixtures would mask it.
FastAPI single backend, modules as routes (not microservices).
whyThe modules share data and one-shot deployment matters more than independent scaling at portfolio scale.
Anchor to FRED instead of synthetic-only data.
whyReal macro context makes the simulator behave plausibly under regime changes; pure random walks look fake in a demo.
Stack
If I rebuilt it
- ›Persist a real ledger DB instead of in-memory; expose a trial-balance endpoint.
- ›Surface a single combined event log so a break can be traced from market tick → recon → ledger.