10年个人财务,纯文本文件
10 years of personal finances in plain text files

原始链接: https://sgoel.dev/posts/10-years-of-personal-finances-in-plain-text-files/

## 与Beancount共度十年:个人财务总结 过去十年,作者一直使用Beancount(一种纯文本会计系统)细致地跟踪个人财务。这包括每月花费30-45分钟下载银行对账单(CSV格式)并将其导入Beancount账本的过程。 十年间,这产生了包含超过45,000行数据、分布在16个纯文本文件中的账本,总计约10,000笔交易和20,000条分录,涉及1086个虚拟账户。大约500份支持文件(如收据)也链接到交易。分录数量稳步增加,并在2023年达到峰值。 工作流程包括将CSV数据转换为Beancount可读格式,将其附加到账本,并手动平衡条目以确保准确性。每年,交易都会被归档到单独的文件中,以提高可读性。 为了简化他人的入门流程,作者还撰写了一本关于使用Beancount的书籍,该书收到了积极的反馈和Beancount社区的认可。最终,作者重视将财务数据作为纯文本、本地存储,并且不依赖于任何特定服务或应用程序所带来的控制权和持久性。

一个黑客新闻的讨论围绕着使用纯文本文件和开源软件(如Beancount)来管理个人财务。最初的帖子链接到一个资源,详细介绍了以这种方式进行10年的财务跟踪。 几位评论者分享了他们的经验。许多人欣赏基于文本系统的灵活性和控制力,利用Vim、grep和Git等工具进行编辑、搜索和版本控制。Beancount被强调为一个特别通用的选择,不仅可以跟踪财务,还可以跟踪股票、休假和其他资产。 然而,这种方法并非适合所有人。一位评论员指出,它最适合开发人员或熟悉文本界面的人,而另一位则质疑作者与Beancount核心项目的关系,尽管他写了一本相关书籍。尽管需要投入时间(可能10年里需要60-90小时),用户认为这是值得的,可以换取数据的所有权和定制化。
相关文章

原文

January 2026 will mark 10 years since I started storing my personal finances in plain text files using Beancount. Since January 2016, I've taken out about 30-45 minutes every single month to download my monthly bank statements and import them into my Beancount ledger.

There's a lot to talk about here, but let's start with some fun numbers!

The 10 year old Beancount ledger

10 years of financial transactions is a lot of data! All in all, my ledger contains over 45,000 lines of Beancount entries spread across 16 plain text files. All of it is stored in a finances directory (version controlled) on my laptop. Here's a snapshot:

❯ find . -name "*.beancount" | xargs wc -l
    4037 ./includes/2020.beancount
    3887 ./includes/2018.beancount
      27 ./includes/cash.beancount
    4398 ./includes/2021.beancount
    5531 ./includes/2019.beancount
    5267 ./includes/2022.beancount
    3287 ./includes/2017.beancount
    5506 ./includes/2024.beancount
    5606 ./includes/2023.beancount
    1454 ./includes/2016.beancount
    1089 ./includes/open/04-expenses.beancount
      66 ./includes/open/03-income.beancount
      11 ./includes/open/05-liabilities.beancount
      37 ./includes/open/02-assets.beancount
       1 ./includes/open/01-equity.beancount
    4807 ./main.beancount
   45011 total

Running bean-query on main.beancount tells me I have about 10,000 transactions in total, that in turn contain about 20,000 postings (in double-entry bookkeeping, one transaction may have multiple postings).

❯ uv run bean-query main.beancount
Input file: "Goel"
Ready with 12466 directives (19743 postings in 9895 transactions).
beanquery>

There are 1086 accounts in total.

beanquery> select count(*) from (select distinct(account));
coun
----
1086

... which does not mean that there are 1086 bank accounts. Accounts in Beancount are virtual, and you can create as many as you like. Imagine one account for categorizing supermarket spending, one for tracking your income, one for your Netflix subscription, and so on.

Next, there are about 500 documents in the repository.

❯ find documents/ -name "*.pdf" | wc -l
     507

Beancount lets you attach documents (e.g. receipts or invoices) to transactions, that makes bookkeeping very efficient. I love the fact that whenever I need to do my tax returns, I can just take a look at my Beancount ledger and find all the invoices right there next to the relevant transaction.

Lastly, in terms of postings, I started out with 715 in the year 2016, and the year 2023 was the busiest so far in terms of just the total postings count.

beanquery> select year(date), count(*) where year(date) < 2025 group by year(date);
year  coun
----  ----
2016   715
2017  1422
2018  1605
2019  2437
2020  1582
2021  2022
2022  2435
2023  2651
2024  2602

The Monthly Ritual

I wrote earlier that every month I take about 30-45 minutes to import my financial transactions into Beancount. What does that workflow look like? I wrote another, much more detailed blog post about it a few years ago, but here's a gist.

It starts with me logging in to my bank account(s) to download my monthly statement(s) in CSV (CSV because it's much more predictable to parse compared to PDF). I then run these CSV files through what's called an "importer", that converts this CSV data into data structures that Beancount understands. I then append all those extracted entries into my current .beancount file (which is the main file containing all my financial transactions in plain text). I then go through each entry one by one and make sure it's balanced (in double-entry bookkeeping, all the postings in a transaction must sum to zero, and not all postings/transactions that an importer outputs are balanced). Some of that balancing is manual and some of it is automated (e.g. the importer code can look at the transaction's description and decide which account it should go into, and balance automatically). This last part (balancing) is where most of those 30-45 minutes go.

Whenever a new year starts, I move all the transactions from the past year into a <year>.beancount file and add an include <year.beancount> in the active main.beancountfile, mostly to avoid the main file from becoming too long. Not that it would be an issue for Beancount, but just for the sake of readability.

With such a workflow, all my financial transactions from the beginning of time are contained in a few plain text files in one directory on my laptop.

Building Beancount Importers for German Banks

Beancount only provides the foundations for working with money, but it has no knowledge of what your bank statements look like. This is where the concept of an importer comes in. An importer is a (Python) class that takes in a bank statement of sorts (e.g. a CSV export of your transactions) and converts them into something that Beancount can work with.

I live in Germany and my bank accounts are with German banks, so I had to write a few importers for a few different banks, specifically beancount-dkb, beancount-ing, beancount-n26, and beancount-commerzbank. I closed out my Commerzbank account a while ago, so I don't maintain that integration anymore, but the first three libraries are actively maintained (and used)!

From User to Author

My start with Beancount was a bit bumpy. The documentation is very comprehensive but as a newcomer, I found it tricky to get a grasp on the overall workflow. It took me some trial and error to figure things out and have that "aha" moment.

I figured that if I found it tricky, maybe it's tricky for others as well. So I wrote a short book to help newcomers get up and running with Beancount easily. If you're interested, here's a link: https://personalfinancespython.com.

The feedback on the book has been super positive. It got mentioned on Beancount's external contributions page, and the reader reviews have all been very encouraging!

Closing Thoughts

Having all my finances in a bunch of plain text files tracked in a git repository feels invaluable to me. And hitting the 10 years mark on that almost feels like a milestone.

Perhaps the nicest bit about all this is that this data is sitting on my own machine, not in some data center somewhere else. All of it is in plain text files that I can open up in my editor, and analyze using the tools that the Beancount ecosystem gives me. All of it will outlive any app or service, and that, I feel, is why plaintext accounting is so powerful.

联系我们 contact @ memedata.com