Skip to content

Repository files navigation

Personal Finance Dashboard

Local-only Python pipeline that pulls financial data from Akahu (a New Zealand open-banking aggregator), stores it as plain JSON on disk, and provides a CLI for spending analysis, budgeting, investments, net-worth tracking, and HTML reports. Optimised for fast AI-driven iteration — every artefact is hand-readable and git diff-able.

Status: Actively used. All commands are implemented and tested (467 unit tests, all green). See ROADMAP.md for what's next and REVIEW.md for a recent code review.


Quick start

# 1. Install
python3 -m venv .venv
source .venv/bin/activate
pip install -e .

# 2. Configure
cp .env.example .env
# edit .env and fill in AKAHU_USER_ACCESS_TOKEN + AKAHU_APP_ID_TOKEN

# 3. First sync
finance accounts           # list connected accounts; copy IDs into config/accounts.json
finance sync --full        # pull all available history (~365 days for personal apps)
finance categorize         # apply config/category_rules.json → data/derived/

# 4. Iterate on categories
finance spend uncategorised      # see what's not matching yet
finance review                   # interactive merchant review — appends rules
# (optional) finance review --ai # pre-fill suggestions using Claude Haiku

# 5. Analyse
finance spend                                        # current pay cycle (default)
finance spend month                                  # current calendar month
finance spend cycle 2026-04                          # named pay cycle
finance spend by-category --from 2026-04-01 --to 2026-04-30
finance spend top-merchants --n 10
finance spend trend --months 6                       # per-cycle category trend
finance spend cat "Eating Out" --cycle 2026-04       # drill into a single category
finance spend income                                 # income breakdown
finance budget status                                # actuals vs config/budgets.json
finance budget status --cycle                        # same, on pay cycle

# 6. Investments & net worth
finance investments                                  # KiwiSaver + Sharesies + manual
finance net-worth snapshot                           # record today's net worth
finance net-worth                                    # latest snapshot
finance net-worth trend                              # over time

# 7. Debt tracking
finance debt                                         # summary: balances, rates, payoff dates
finance debt payoff "Home Loan"                      # amortisation drilldown
finance debt payoff "Home Loan" --extra 200          # what-if: +$200/mo extra payment
finance debt payoff "Visa"      --lump  5000         # what-if: $5,000 lump sum first

# 8. HTML report
finance report                                       # open a self-contained report.html
finance report --cycle 2026-04                       # a specific pay cycle
finance report --month 2026-04                       # calendar month instead
finance report --output ~/Desktop/april.html         # custom output path
finance report --no-open                             # write without auto-opening

# 8. Savings & goals
finance savings                    # current-cycle savings summary by bucket
finance savings cycle 2026-04      # specific cycle
finance savings trend              # savings rate trend over time
finance goals                      # progress toward each financial goal
finance forecast                   # net-worth projection scenarios

# 9. Export / validate
finance export --from 2026-01-01 --out 2026.csv      # CSV export
finance validate                                     # check rules against taxonomy

CLI reference

Command Purpose
finance sync Pull last 90 days of transactions + current balances. Idempotent. Use --full for all history.
finance accounts Show connected accounts with IDs and balances. Use this to seed config/accounts.json.
finance categorize Apply config/category_rules.json (regex) and config/akahu_category_map.json (Akahu fallback) to data/raw/data/derived/transactions_categorised.json.
finance review Interactive merchant review — walk through uncategorised merchants ranked by spend, append rules. --ai pre-fills suggestions via Claude Haiku; --auto-apply-high accepts high-confidence ones without prompting.
finance spend Defaults to current pay cycle. Subcommands: month, cycle, by-category, top-merchants, trend, cat, income, uncategorised.
finance budget status Actual spend vs config/budgets.json for the current period. --cycle switches calendar→pay-cycle.
finance investments Portfolio breakdown for KiwiSaver, Sharesies, and manually-tracked investment accounts. Shows breakdown, holdings, contributions/returns since first snapshot.
finance net-worth Latest net-worth snapshot. snapshot (record a new one, prompting for manual balances) and trend (over time) subcommands.
finance debt Debt summary: per-debt balance, rate, minimum payment, paid-this-cycle, projected payoff date. payoff <name> for a full amortisation drilldown with --extra and --lump what-ifs.
finance report Generate a self-contained report.html with headline cards, budget progress bars, debt section, top-category breakdown, and a 6-cycle spend trend chart. Opens in the browser automatically.
finance savings Savings summary by bucket for the current cycle. Subcommands: cycle, trend, bucket, goals, plan, reconcile.
finance goals Progress toward each configured financial goal. set subcommand to add/update goals.
finance forecast Net-worth projection scenarios — base, optimistic, pessimistic — incorporating debt paydown and investment growth.
finance export Export categorised transactions as CSV. Stdout or --out FILE.
finance validate Check config/category_rules.json against the taxonomy in config/categories.json.

Global flags on every command: --format {table,json,csv}, --quiet, --no-color.

Filter flags on every spend subcommand: --from YYYY-MM-DD, --to YYYY-MM-DD, --owner, --category.

The iteration loop

When you spot a misclassification:

  1. finance spend uncategorised — see merchants that don't yet match a rule.
  2. Either edit config/category_rules.json directly (add a regex rule with the right category), or run finance review for an interactive walkthrough that writes rules for you.
  3. finance categorize — re-applies rules to all data.
  4. Re-run finance spend ... to verify.

No spreadsheet round-trip, no formula breakage. The whole loop is text and git diff makes every change obvious.

Pay cycles

Pay cycles align with when salary actually lands, not a fixed day of month. On first run the pipeline falls back to a 20th-of-month rule, but as soon as you've categorised any transaction as Income > Salary, assign_pay_cycles_from_salary re-stamps every transaction's pay_cycle based on the most recent pay date on or before it. The cycle label is the YYYY-MM of the pay date itself.

Example: paid 2026-04-18 → all transactions from 2026-04-18 up to (but not including) the next pay date belong to cycle 2026-04.

Architecture at a glance

finance-dashboard/
├── pyproject.toml             # `pip install -e .` registers the `finance` console script
├── .env                       # Akahu + (optional) Anthropic tokens — gitignored
├── README.md                  # this file
├── REVIEW.md                  # recent code review
├── ROADMAP.md                 # phased plan: Now / Next / Later
├── config/                    # hand-edited JSON
│   ├── accounts.json          # account_id → {owner, display_name}
│   ├── categories.json        # canonical taxonomy
│   ├── category_rules.json    # regex → category, with priority + owner filters
│   ├── akahu_category_map.json# Akahu category → your taxonomy (fallback)
│   ├── budgets.json           # per-category budget + default period
│   ├── manual_balances.json   # accounts Akahu can't reach (Squirrel, Whai Rawa, ...)
│   ├── manual_contributions.json # per-cycle contribution ledger
│   └── contributions_map.json # transaction-pattern → investment account
├── data/                      # generated; gitignored
│   ├── raw/                   # source of truth: accounts, transactions/YYYY-MM.json, balances/YYYY-MM-DD.json
│   └── derived/               # rebuilt from raw + config (transactions_categorised.json)
├── finance/                   # the package
│   ├── cli/                   # CLI package (argparse wiring + thin command shims)
│   │   ├── __init__.py        #   build_parser(), main(), global flags
│   │   ├── sync.py            #   sync, accounts
│   │   ├── categorise.py      #   categorize, review
│   │   ├── spend.py           #   all spend subcommands
│   │   ├── budget.py          #   budget status
│   │   ├── investments.py     #   investments
│   │   ├── net_worth.py       #   net-worth (snapshot, trend)
│   │   ├── savings.py         #   savings goals + bucket tracking
│   │   ├── forecast.py        #   net-worth projection
│   │   ├── goals.py           #   financial goals
│   │   ├── export.py          #   export, validate
│   │   └── report.py          #   report (HTML dashboard)
│   ├── config.py              # path constants, env loading, pay-cycle helpers
│   ├── akahu.py               # Akahu REST client (retries, pagination, 429 handling)
│   ├── transform.py           # pure: Akahu shape → internal shape
│   ├── categorise.py          # rules, taxonomy, apply, validate
│   ├── spending.py            # filters + rollups + trend matrix
│   ├── budget.py              # period progress + status_for_period
│   ├── net_worth.py           # snapshot building, totals, trend series, contributions
│   ├── debt.py                # pure: amortisation, payoff projections, what-ifs
│   ├── savings.py             # savings tracking — goals, buckets, inflow attribution
│   ├── transfers.py           # transfer detection + classification rules
│   ├── buckets.py             # savings bucket state + allocation helpers
│   ├── forecast.py            # net-worth projection scenarios
│   ├── goals.py               # financial goal modelling
│   ├── rollover.py            # pay-cycle budget rollover logic
│   ├── report_html.py         # pure: data dicts → self-contained HTML string
│   ├── store.py               # JSON I/O for raw + derived (schema-versioned)
│   ├── review.py              # interactive merchant review
│   ├── ai.py                  # Anthropic API integration (optional, for `--ai`)
│   ├── reporters.py           # `rich` table/kv/JSON/CSV rendering
│   └── __main__.py            # enables `python -m finance`
├── scripts/                   # one-shot migration utilities
└── tests/                     # 467 unit tests, all pure + fast (~13s)

The split is pure functions in the core modules (transform, spending, budget, categorise, net_worth, report_html); I/O at the edges (store, akahu, ai); thin CLI shims (cli/, reporters). This is what makes the test suite cheap to maintain.

Tests & type-checking

pytest          # 467 unit tests
ruff check .    # lint + import order
mypy            # strict type-checking on transform, spending, budget

Tests cover transform, categorise, spending, budget, review, net_worth, debt, savings, transfers, buckets, forecast, goals, rollover, store (schema versioning), and end-to-end CLI smoke tests. Fixtures live in tests/fixtures/. All three checks run in CI on Python 3.10 and 3.12 via GitHub Actions.

Why JSON, not a sheet

The original version of this project wrote everything to Google Sheets. That made iteration painfully slow — every "what's in the data right now?" question required an API round-trip, and formula tabs drifted silently. JSON files on disk give us:

  • Zero round-trip inspection — read a file, see the data.
  • Clean git diff scoped to what actually changed.
  • Hand-editable config — the iteration loop is "edit JSON, re-run CLI, check diff".
  • Snapshot tests that catch regressions in seconds.

Optional: AI-assisted review

If you set ANTHROPIC_API_KEY in .env, finance review --ai will use Claude Haiku to pre-fill category suggestions for each uncategorised merchant. Cost is ~$0.0003 per merchant (a full 100-merchant review is about 3 cents). The default model is claude-haiku-4-5 and can be overridden with ANTHROPIC_MODEL. If the API key isn't set, --ai is silently disabled and review continues in manual mode.

About

Locally hosted, CLI based application for budgeting and personal finance in NZ. Leveraging Akahu's open banking infra.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages