Skip to content

Commit 0f056e2

Browse files
committed
Add new blog post: finance-workflow
Signed-off-by: ricekot <github@ricekot.com>
1 parent 9e7fce8 commit 0f056e2

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
---
2+
layout: post
3+
title: "How I Manage My Finances with hledger and Python"
4+
description: An overview of my plain-text accounting workflow.
5+
date: 2023-09-03 08:00 +0530
6+
---
7+
8+
Today I'm going to talk about how I manage my finances with a plain-text accounting tool called [hledger](https://hledger.org/) and some Python scripts.
9+
10+
## Why Plain-text accounting?
11+
My requirements were simple:
12+
- Ownership of my data: I don't want sensitive information about my finances on the cloud servers of some random organization.
13+
- Reasonably automatable: I don't want to manually keep track of every single transaction I make.
14+
- Reliable: I want something that *just works*. Please, no janky dashboards with unnecessary fluff.
15+
16+
## The Setup
17+
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.
18+
19+
```
20+
hledger/
21+
├── 2023.journal
22+
├── 2023.prices
23+
├── bank-credit-card.csv
24+
├── bank-credit-card.py
25+
├── bank-statement.py
26+
├── bank-statement.xls
27+
├── current.journal -> 2023.journal
28+
├── current.prices -> 2023.prices
29+
├── get-latest-prices.py
30+
├── past
31+
│   ├── 2022.journal
32+
│   └── 2022.prices
33+
├── tradebook.csv
34+
├── tradebook.py
35+
└── update-ledger.sh
36+
```
37+
38+
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.
39+
40+
Here's an overview of the files in the list above:
41+
- The `.journal` files are the core of this system. They contain all the transactions that I make.
42+
- The `.prices` files are used to track the prices of my investments over time.
43+
- The `.csv` and `.xls` files contain exported transactions from my banks and my broker.
44+
- The `.py` files are Python scripts that are used for parsing the exported data files and converting them to hledger transactions.
45+
- The `update-ledger.sh` script is for my convenience. It runs all the other scripts and appends their output to the journal or the prices files.
46+
47+
## Understanding hledger
48+
I love hledger. It is free, open-source, and based on the widely used [double-entry](https://en.wikipedia.org/wiki/Double-entry_bookkeeping) method of bookkeeping.
49+
50+
### The `.journal`
51+
This is what a transaction in the journal looks like:
52+
53+
```
54+
2023-08-20 Coffee
55+
expenses:food INR 250.00
56+
debt:credit card
57+
```
58+
59+
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.
60+
61+
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.
62+
63+
### The `.prices`
64+
Entries in the prices file are pretty straightforward too.
65+
For example,
66+
67+
```
68+
P 2023-08-31 NIFTYBEES INR 212.77
69+
```
70+
71+
is used to tell hledger that the price of a single share of the NIFTYBEES ETF on August 31, 2023 was INR 212.77.
72+
73+
If you want to learn more about hledger, I recommend going through their [documentation](https://hledger.org/start.html).
74+
75+
## My Workflow
76+
It takes me about 15-30 minutes every weekend to update my ledger with the transactions of the week before.
77+
78+
1. I start by downloading the transactions of the past week from the websites of my banks and my broker.
79+
I have some thoughts on the file formats that banks allow exporting in, but I'll save those for another day.
80+
2. I run the `update-ledger.sh` script which:
81+
1. runs the Python scripts to convert the entries in the exported files to hledger journal entries
82+
2. runs the Python scripts to fetch the latest prices of my investments
83+
3. 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).
84+
4. I stage and commit all changes.
85+
86+
That's it! Really, the process of logging in, navigating, and exporting transactions from bank websites is what takes the most time.
87+
88+
## The Scripts
89+
Each banking institution has quirks about the formats that they let you export your data in.
90+
Most of them allow exporting spreadsheets (`XLS` or `XLSX`) and comma separated value (`CSV`) files.
91+
The great thing about using Python is that there are libraries available to parse most of these formats.
92+
93+
## What's next?
94+
I've been using this system for over a year now and I'm pretty happy with it. It is simple and robust.
95+
96+
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](https://en.wikipedia.org/wiki/Unified_Payments_Interface), it should be possible to surface the majority of day-to-day spendings for most people with minimal manual inputs from them.
97+
98+
Thanks for reading! If you have any comments, I would love to hear from you at `hello@ricekot.com`.

0 commit comments

Comments
 (0)