Statement Analyzer
Extracts every account and position from a brokerage statement and decides what can transfer in kind. A language model reads the document; a tested, deterministic rule chain makes every decision.
Overview
Extracts every account and position from a brokerage statement and decides what can transfer in kind. A language model reads the document; a tested, deterministic rule chain makes every decision.
The problem
Before each transfer, someone read the client’s statements by hand to list every account and holding and spot anything that could not move. It took 30 to 45 minutes per client, and mistakes surfaced weeks later as rejected transfers.
What I built
- A pre-check that skips files that are not statements or are too old to use.
- Extraction of every account, position, quantity and value into structured data.
- A 15-layer rule chain that classifies each position: transfer in kind, sell first, or needs review.
- A household roll-up across all of a client’s statements.
- A review queue for the few items the rules cannot decide.
- A one-page PDF summary for the advisor.
Key decisions
The model only reads
The language model turns a PDF into data. Every decision comes from deterministic, tested rules, so a reviewer can see exactly why.
Stop at the first failing rule
The chain records which layer decided and why, which makes a wrong answer quick to trace.
Totals must reconcile
Extracted positions must add up to the statement total, or the statement goes to review.
Cache the expensive step
Extraction runs once per document. Re-running the rules after a rule change costs nothing.
Architecture
Python · FastAPI · Gemini · Postgres · React · fpdf2
The demo
The demo never calls a model. Extractions of six synthetic statements are produced offline; the rule chain runs live on them. Uploads are disabled.
Live demo in progress
This demo is being rebuilt on synthetic data. This page will link to it when it ships.