Today I’m going to talk about how I manage my finances with a plain-text accounting tool called hledger and some Python scripts.
Why Plain-text accounting?
My requirements were simple:
- Ownership of my data: I don’t want sensitive information about my finances on the cloud servers of some random organization.
- Reasonably automatable: I don’t want to manually keep track of every single transaction I make.
- Reliable: I want something that just works. Please, no janky dashboards with unnecessary fluff.
I have a version-controlled folder in my home directory which contains my annual hledger journal, some Python scripts, and exported files from my banks’ websites.
hledger/ ├── 2023.journal ├── 2023.prices ├── bank-credit-card.csv ├── bank-credit-card.py ├── bank-statement.py ├── bank-statement.xls ├── current.journal -> 2023.journal ├── current.prices -> 2023.prices ├── get-latest-prices.py ├── past │ ├── 2022.journal │ └── 2022.prices ├── tradebook.csv ├── tradebook.py └── update-ledger.sh
I can definitely make this look nicer by using more subfolders, but so far, with a limited number of files, this single-folder-with-everything-in-it approach seems to be working well for me.
Here’s an overview of the files in the list above:
.journalfiles are the core of this system. They contain all the transactions that I make.
.pricesfiles are used to track the prices of my investments over time.
.xlsfiles contain exported transactions from my banks and my broker.
.pyfiles are Python scripts that are used for parsing the exported data files and converting them to hledger transactions.
update-ledger.shscript is for my convenience. It runs all the other scripts and appends their output to the journal or the prices files.
I love hledger. It is free, open-source, and based on the widely used double-entry method of bookkeeping.
This is what a transaction in the journal looks like:
2023-08-20 Coffee expenses:food INR 250.00 debt:credit card
It’s called “double-entry” because there are two entries for each transaction: an account which was debited and another which was credited. For example, in the above transaction, the “expenses:food” account was credited while the “debt:credit card” account was debited.
Once you have a couple dozen of these entries in your ledger, you can use one of the various interfaces that hledger offers to visualise that data. Like with most other tools, I prefer using their CLI interface. For example, using a command like
hledger balancesheet -V, I’m able to get a nice summary of my assets, liabilities, and net worth.
Entries in the prices file are pretty straightforward too. For example,
P 2023-08-31 NIFTYBEES INR 212.77
is used to tell hledger that the price of a single share of the NIFTYBEES ETF on August 31, 2023 was INR 212.77.
If you want to learn more about hledger, I recommend going through their documentation.
It takes me about 15-30 minutes every weekend to update my ledger with the transactions of the week before.
- I start by downloading the transactions of the past week from the websites of my banks and my broker. I have some thoughts on the file formats that banks allow exporting in, but I’ll save those for another day.
- I run the
- runs the Python scripts to convert the entries in the exported files to hledger journal entries
- runs the Python scripts to fetch the latest prices of my investments
- I make any manual changes I want to the entries (e.g. categorizing expenses), and ensure that everything lines up (e.g. by checking that the final values in my ledger match the values on my banks’ websites).
- I stage and commit all changes.
That’s it! Really, the process of logging in, navigating, and exporting transactions from bank websites is what takes the most time.
Each banking institution has quirks about the formats that they let you export your data in.
Most of them allow exporting spreadsheets (
XLSX) and comma separated value (
The great thing about using Python is that there are libraries available to parse most of these formats.
I’ve been using this system for over a year now and I’m pretty happy with it. It is simple and robust.
However, I understand that it may be too technical for most people. I’ve been talking with friends and family and most of them have said that they’d be interested in an app that would allow them to keep a track of their finances “casually”. That seems like an interesting problem statement to me, and I’m pretty confident that with the widespread adoption of systems like NPCI’s UPI, it should be possible to surface the majority of day-to-day spendings for most people with minimal manual inputs from them.
Thanks for reading! If you have any comments, I would love to hear from you at
|Jun 9, 2023||Leaked Build Arguments in Multi-stage Docker Builds via Build Attestations|
|Feb 13, 2023||Adding a Review Checklist to GitHub PRs|
|Jan 18, 2023||Setting Up a Personal ActivityPub Microblog|
|Nov 8, 2022||How to Browse Twitter at College|
|Sep 13, 2022||Hacking ZAP - ZAP Extender Scripts|
|Aug 7, 2022||SICP Exercises 1.16 - 1.19|
|Aug 3, 2022||Peeling Back The Onion|
|Apr 13, 2022||Test Your APIs For Spring4Shell With Levo.ai|
|Mar 8, 2022||ZAPCon 2022 Presentation Resources|
|Dec 14, 2021||Log4Shell Detection with ZAP|