Beancount 入坑指北

由于最近钱花的总是不明不白的,于是还是决定开这么一个账本来记账好了。

怎么记

当然,记账的方式千变万化,还有很多 APP 可以用来记账。当然他们的广告做的都不错,号称可以自动导入微信支付宝账单等,但实际感受并不很好用,尤其对于一些特殊情况。

比如,先垫付后报销这种场景,强行记成一笔出一笔入又不能真实反映收入支出情况,这种场景下的收入支出应该都为 0。支出的那笔钱相当于是暂时的,最终还是会回来的,所以不能算作支出。同样的,收入的钱也不算是类似工资的收入,实际上这笔钱只是从你的手上过了一下。但是账本中不计又会导致对账不便,比如银行卡支付,支付宝收款。

这就是传统的单式记账法的局限性,所以我选择了复式记账法,上面的场景就可以简化为:

日期 交易方 摘要 借方 贷方
2024-03-20 垫付 银行卡 -100 对公司的应收账款 +100
2024-03-21 报销 对公司的应收账款 -100 支付宝 +100

十分简洁明了,钱从哪里来到哪里去,一目了然。

为什么选择 Beancount

首先,我是不敢把账本这么私密的东西交给云记账这类软件的,谁知道他会不会把我的数据拿到别的什么地方用,或者直接跑路。

所以还是选择了本地记账,而 Beancount 是我找到的最适合的本地记账工具。纯文本记账的方式非常便于备份和迁移,而且还可以用版本控制工具来管理。

怎么用

Beancount 功能强大,但是也有一些学习成本。不过,我觉得这个成本是值得的,你可以花上一个下午的时间简单学习一下,就可以方便以后的记账了。

首先,你需要安装 Beancount,可以通过 pip 安装:

1
pip install beancount

然后,你需要创建一个账本文件,比如 my-beancount.bean

1
2
option "title" "My Beancount"
option "operating_currency" "CNY"

这个文件就是你的账本,你可以在这个文件中记录你的所有账户。比如:

1
2
3
4
5
6
7
8
9
1919-08-10 open Assets:Bank:ICBC CNY
1919-08-10 open Assets:Bank:Alipay CNY
1919-08-10 open Assets:Receivable:Company CNY

1919-08-10 open Expenses:Food CNY

1919-08-10 open Income:Salary CNY

1919-08-10 open Liabilities:CreditCard CNY

在这里,我们也将应收账款是为一种账户,它一般是正的,表示别人欠你的钱。

然后,你就可以开始记账了,接下来介绍几个常见的使用场景

记一笔支出

1
2
3
2024-03-20 * "早餐" "永X豆浆"
Expenses:Food 10 CNY
Assets:Bank:ICBC

这里会发现,第二行的来源没有写明金额,这是因为 Beancount 会自动计算空格应填入的金额,也避免了帐不平的问题。

记一笔收入

1
2
3
2024-03-20 * "工资" "工资"
Income:Salary -10000 CNY
Assets:Bank:ICBC

这里可以想象成收入(Income)是一个无底大桶,每次获得收入都是从这个桶里掏钱出来,所以是负的。

当然,我们也可以再开立公积金、医保个帐等账户,也可以设置税收这一项支出,但是现在还没人给我发工资,也没人给我交五险一金,所以这里先挖个坑,以后再来填。

来点复杂的

1
2
3
4
2024-03-20 * "Pineapple Inc." "pHone 15 Pro Max 1TB 远峰蓝"
Expenses:Phone 10000 CNY
Liabilities:CreditCard -5000 CNY
Liabilities:Cash:Friend -5000 CNY

比如现在,我在菠萝买了一部手机,但是我的信用卡额度只有可怜的 5000 块,剩下的 5000 则向朋友借来了,于是这笔支出就分别记在了信用卡和朋友的账户上。

1
2
3
4
5
6
2024-03-31 * "信用卡" "还款"
Liabilities:CreditCard -5000 CNY
Assets:Bank:ICBC
2024-03-31 * "朋友" "还款"
Liabilities:Cash:Friend -5000 CNY
Assets:Bank:ICBC

然后,到了月底,我还了这笔钱,现在我的信用卡和朋友的账户的余额都是 0 了,代表我没有负债。

这里就体现出那句经典的 “有借必有贷,借贷必相等” 的原则了。也可以写作

(Income + Liabilities) + (Assets + Expenses) + Equity = 0

这里的 Equity 是所有者权益,也就是你的净资产,是存放在记账之前已有的权益。

下面我们再来模拟一个场景,境外消费。日元消费,美元入账,人民币结算。

1
2
3
2024-03-20 * "SEGA" "某知名八个按键的游戏 * 10pc"
Expenses:Travel:Abroad
Liabilities:CreditCard -6.00 USD @@ 1000 JPY

这里的 @@ 表示总价,也就是说,我信用卡支出了 6 USD,买了总价 1000 JPY 的东西。

当然,Beancount 不会考虑你的货币到底是什么东西,所以你需要在 @@ 后输入总价,或者在 @ 后输入单价

出来混总是要还的,今天美元汇率大跳水,一美元只有 6 RMB 了,于是我还了这笔钱。

1
2
3
4
2024-03-31 * "信用卡" "还款"
Liabilities:CreditCard 36.00 CNY @@ 6.00 USD
Assets:Bank:ICBC
Assets:Bank:ICBC

账本前后金额相符,平账。

我还有一些买基金的习惯,这里也可以记录下来。

1
2
3
2024-03-20 * "基金" "买入"
Assets:Bank:ICBC -1000 CNY
Assets:Investment:Fund

那么到月底,我要结算一下基金的收益,保证基金账户余额和账本一致,就可以简单的使用 pad 和 balance 指令来实现。

1
2
2024-03-31 pad Assets:Investment:Fund Equity:Investment
2024-04-01 balance Assets:Investment:Fund 1011.45 CNY

其实 Beancount 中实现基金统计的方式很多,我因为平时不怎么动基金账户所以直接当成利息处理,但这样其实是不够准确的,等我有时间再来研究一下(坑)。


Beancount 入坑指北
https://blog.sparrowhe.top/2024/03/20/beancount-entry/
作者
Sparrow He
发布于
2024年3月20日
许可协议