Skip to content

Personal Finance

TL;DR

A personal finance system built from scratch: bank CSV imports, deterministic transaction categorization, envelope budget tracking, and a monthly reporting dashboard — all running locally. The data never leaves my machine. Stack: Python, PostgreSQL 16, scikit-learn, Apache ECharts, MkDocs Material.

I tracked my finances for years on paper, then in a spreadsheet. After looking at a bunch of personal finance apps that cost money and didn't fit how I actually think about budgeting, I decided to build my own.

It pulls in transactions from my bank and credit card accounts and conforms them into my budget universe, physicalized in a database. Flexible structure, intramonth tracking, and the ability to refactor anything backed by my own data.


How It Works

graph TB
  A["Bank CSVs"] --> B["Ingest & Stage"]
  B --> C["Categorize"]
  C --> D["Clean Data"]
  D --> E["Envelope Tracking"]
  D --> F["Report Generation"]
  E --> G["Dashboard"]
  F --> G

Under the Hood

The pipeline starts with CSV exports from my bank accounts. A Python ingest layer stages them into PostgreSQL, then a categorization pass matches each transaction to a budget category — mostly deterministic rules built up over time, with a TF-IDF-assisted CLI for edge cases that don't pattern-match cleanly. The result is clean, categorized data in my own schema, which I can query and refactor on my own terms.

From there, the system tracks 13 spending envelopes and savings pools, and generates a monthly budget vs. actual report with a 6-month trend view. Everything ships as static JSON that the dashboard reads on load — same architecture as the SF6 tool, different problem domain.

The next step is pulling in retirement account data to close the loop between spending, saving, and long-term planning.

Stack: PostgreSQL 16 · Python · psycopg2 · scikit-learn · Apache ECharts · MkDocs Material


Dashboard access

The live dashboard contains real financial data and is password protected. The writeup above is open. To request access, reach out via the Contact page.