一直都有记账的想法。

我们经常都会有的困惑:感觉没干什么,工资就没了。随着工作年限的增加,愈发觉得对自我财务进行管理非常重要。这既能察觉不必要的花费,又不至于过于紧缩,什么都不敢消费。也正如 BYVoid 所说:记账是个人理财的基础,更是通往财务自由的必经之路。

复式记账

何为复式记账?

复式记账不同于通常的流水账。

在流水账里,我们把每一笔支出和收入进行一个描述性的记录,例如:

1
2
3
2020年4月15日,抢到红包5.2元,开心。
2020年4月16日,使用支付宝花费34.1元购买水果和酸奶。
2020年4月16日,骑哈罗单车花费1.5元。

但要了解复式记账,就要首先理解下面几个概念:

  1. Income 收入
  2. Assets 资产
  3. Expenses 支出
  4. Liabilities 负债

如图:

图1

图中显示,我们的每次财务行为,都被抽象为钱在这四个“桶”之间流转。如图中所示一样,我们的钱全部来源于“收入”和“负债”,最终流向“资产”和“消费”,总体上始终满足:

1
收入+资产+负债+支出=0

为了等式成立,收入和负债使用负数表示。并且每一次记账行为,至少会涉及两个“桶”间的关联。这里用几个例子说明:

*2020年4月15日,抢到红包5.2元,开心。*可以记录为:

1
2
2020年4月15日,收入-5.2元。
2020年4月15日,资产+5.2元。

*2020年4月16日,使用支付宝花费34.1元购买水果和酸奶。*可以记录为:

1
2
2020年4月16日,资产-34.1元购买水果和酸奶。
2020年4月16日,支出+34.1元购买水果和酸奶。

不难发现,每一笔账单都会有两条记录,并且两条记录的和为0;这也许就是 复式记账(Double Entry Bookkeeping)Double Entry 的所在吧。复式记账记录了资金的流动,使其更具有可靠性和可参考性。

作为一个已经著名经久的记账方法,我们远不至于再在记事本上手写这些账目。这里介绍一种简单且高效的复式记账工具。

安装 Beancount 和 fava

Beancount 的优点很突出:

  1. 开源,使用 Python 实现,可以本地运行。虽然部署需要一些 Python 环境,但身为程序员来说,简直轻车熟路。
  2. 基于文本,使用灵活。也就是可以使用 Git 便捷的进行版本控制。简直为程序员量身打造。

favaBeancount 的可视化工具。虽然关于这两者的部署运行,网上已经有很多文章,这里还是简单列出步骤:

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 安装
pip install beancount fava
# 安装太慢,可以切换为国内镜像源
pip install beancount fava -i https://pypi.tuna.tsinghua.edu.cn/simple

# 2. 从下面地址上下载示例
https://bitbucket.org/blais/beancount/src/default/examples/

# 3. 下载完毕后,在 example.beancount 所在文件目录下执行
fava example.beancount

# 4. 打开浏览器,访问 http://localhost:5000/ 即可

虽然是简单的几步,但是在我第一次安装的时候,还是碰到了一些问题:

  1. pip 下载速度太慢,请求超时。(可以使用国内的镜像源 https://pypi.tuna.tsinghua.edu.cn/simple
  2. windows 10 缺少类库,导致安装失败。(可以下载 Microsoft Visual C++ Build Tools,自行安装即可)
  3. 部分依赖库版本和本地已有的版本不一致导致安装失败。(更新本地的依赖)

开始记账

也许你已经安装完毕,磨拳搽掌准备行动。

我这里介绍一种初始化账单数据的方案,如果你有其他方案,也可以邮件交流。

一个场景:

小明现在有 工行卡1234(10000元),现金(2000元),欠花呗(1200元);有5000元股票。

然后小明决定今天开始记账,他可以按下面操作开始。

首先创建一个账单文件 xiaoming.bean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
* 指定账单使用的货币单位
option "operating_currency" "CNY"

* 开启具有的账户:2020-04-16 指开启时间,之后关于这个账户的资金变动时间不能早于 2020-04-16,否则 beancount 会报错
* CNY 指 货币单位,元
* 工商银行1234
2020-04-16 open Assets:ICBC1234 CNY
* 现金
2020-04-16 open Assets:Cash CNY
* 股票
2020-04-16 open Assets:Stock CNY
* 花呗
2020-04-16 open Liabilities:Huabei CNY
* 可乐消费
2020-04-16 open Expenses:Cola CNY

* 这个账户一般用于初始账户的收支平衡
2020-04-16 open Equity:Opening-Balances CNY

* 初始化已有资产和负债
* 先用 Equity:Opening-Balances 平衡没有数据来源的 Assets:ICBC1234 账户,并且设为 10000 元
2020-04-16 pad Assets:ICBC1234 Equity:Opening-Balances
2020-04-17 balance Assets:ICBC1234 10000.00 CNY

* 同样的方式初始化其他账户
2020-04-16 pad Assets:Cash Equity:Opening-Balances
2020-04-17 balance Assets:Cash 2000.00 CNY
2020-04-16 pad Assets:Stock Equity:Opening-Balances
2020-04-17 balance Assets:Stock 5000.00 CNY
* 债务一般负数表示
2020-04-16 pad Liabilities:Huabei Equity:Opening-Balances
2020-04-17 balance Liabilities:Huabei -1200.00 CNY

* 然后从 4-17 开始记录自己的收入和支出
* 下班用现金买罐可乐
2020-04-17 * "买罐可乐"
Assets:Cash -3.00 CNY
Expenses:Cola 3.00 CNY

xiaoming.bean 目录下执行 fava xiaoming.bean。打开浏览器访问 http://localhost:5000/,应该就可以看到自己的账目信息。

这里需要注意的是,2020-04-17 balance Assets:ICBC1234 10000.00 CNY 这条语句(包括下面几条同语法的语句)中的 balance 一般表示所记录日期当天的开始时间,所以这里记录了 2020-04-16 的资产目录,而从 2020-04-17开始记录每天的资金流水。

关于 fava 的使用,这里就不再赘述。

实践经验

大额转账的处理

对于一个大额的转账类收入或支出,如果直接归入收入或支出,会导致统计图的比例被挤压。
我的方案是:创建一个 Equity:Exchange 负责转账记录,然后在 事件 中创建 转账 条目用以记录。如下:

1
2
3
4
5
2020-05-12 * "爸转账5万元"
Assets:BankCard 50000.00 CNY
Equity:Exchange -50000.00 CNY

2020-05-12 event "转账" "爸转账5万元"

金额的浮点误差

使用一段时间发现 beancount 在金额计算上因为浮点数非精确计算的性质,会出现 0.01 的误差(我的习惯所有账户金额保留两位小数),虽然对总账目影响很小,但还是必死强迫症。

我的方案是:创建一个 Equity:Balance-Error 账户,定期对误差进行消除。

1
2
3
2020-07-10 * "平衡账户浮点误差"
Equity:Balance-Error -0.01 CNY
Assets:BankCard 0.01 CNY

参考文档

Beancount复式记账(一):为什么
Beancount复式记账(二):借贷记账法
Beancount复式记账(三):结余与资产
Beancount复式记账(四):项目管理
Beancount使用经验,通过Beancount导入支付宝&微信csv账单