跳到主要内容
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.
查看所有作者

【Beancount】账单导出及查看方法

· 阅读需 2 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.

支付宝

参考 此文章

微信

参考 此文章

招商银行(CMB)信用(Credit)卡

通过 " 掌上生活 "APP->点击 " 我的 "->查账 ->选择需要查的账单 ->查账 ->右上角 " 更多 "->账单补寄 (补寄方式为「电邮发送」)->申请补寄。

中国银行(BOC)储蓄(Debit)卡

通过 " 中国银行 "APP->搜索 " 交易流水打印 "->申请。

工商银行(ICBC)储蓄卡

通过 " 中国工商银行 "APP->点击 " 我的 "->找到 " 银行卡 "->在 " 账户服务 " 中找到 " 明细打印 ",选择需要的时间跨度下一步。

农业银行(ABC)储蓄卡

通过 " 中国农业银行 "APP->搜索 " 明细查询 "->右上角点击 " 明细 导出 "。

中信银行(CITIC)信用卡

宁波银行(NBCB)储蓄卡

通过 " 宁波银行 "APP->搜索 " 交易流水打印 "->选中 " 展示我的完整卡号 " 和 " 展示交易对手信息 "," 交易类型 " 选 " 全部 "->提交申请。

华夏银行(HXB)储蓄卡

通过 " 华夏银行 "APP->点击 " 我的 "->选择 " 收支账单 "->右上角点击选择 " 流水下载 "->选中 " 展示交易对手信息 " 和 " 展示完整卡号/账号 " 后发送至邮箱。

工商银行(ICBC)企业账单

通过 " 工行企业手机银行 "APP->点击 " 我的 "->在 " 资产负债总览 " 中点击 " 余额明细查询 "->选择 " 账单明细 "->右上角点击 " 更多查询 "->最多选择半年的时间跨度,点击 " 明细发送至邮箱 "->选择 "EXCEL 格式 (.xlsx)" 确定。

建设银行(CCB)储蓄卡

通过 " 中国建设银行 "APP->点击 " 我的 "->" 银行卡 "->选择想要查询的银行卡点击 " 详情 "->在管理窗口中点击 " 流水打印 ">" 流水打印申请 "->" 交易信息展示 " 栏将 " 完整展示对方账号 "、" 完整展示对方户名 "、" 展示交易地点/附言 " 均勾选 ->文件类型选择 Excel 发送 ->根据提取码解压邮箱获取。

浙江农商银行(ZJRCUB)储蓄卡

通过 " 丰收互联 "APP->单击 " 我的 "->" 我的账户 "->选择 " 账单导出 "->明细种类选择 " 详细版 "。

光大银行(CEB)储蓄卡

通过 " 光大银行 "APP->进入首页选择 " 明细 "->右上角点击 " 电子证明 "->" 申请 "。

【Beancount】6. 善用工具

· 阅读需 3 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.

有前面五篇文章的铺垫,接下来的操作对非程序员来说可能有点硬核。懒惰是第一生产力,如果能让人提升生产力,那可以试试水。

Beancount 语法小抄

img

Beancount-Trans 自动解析账单

https://trans.dhr2333.cn/

nginx 配置公网访问账本(需认证)

image-20221101162308122

参考链接

致谢

https://byvoid.com/zhs/blog/beancount-bookkeeping-3/ # [推荐] 完整项目

https://wzyboy.im/post/1063.html # Beancount —— 命令行复式簿记

https://wzyboy.im/post/1317.html # 使用 Beancount 记录证券投资

https://blindwith.science/tags/beancount/ # Blind with Science

http://morefreeze.github.io/2016/10/beancount-thinking.html # MoreFreeze's Sanctuary

https://www.skyue.com/19101819.html # 基础用法

https://www.skyue.com/20050218.html # 股票实践

https://blog.zsxsoft.com/post/41 # Beancount 复式记账:接地气的 Why and How

https://beancount.github.io/docs/beancount_language_syntax.html # 官网

https://lug.ustc.edu.cn/planet/2020/08/keeping-account-with-beancount/

https://zhuanlan.zhihu.com/p/166191611 # 高级用法

https://blog.csdn.net/wbsu2004/article/details/124920383 # 移动端

https://www.bmpi.dev/self/beancount-my-accounting-tool-v2/ # 各账本初始化

https://einverne.github.io/post/2021/02/beancount-import-bill.html # 账单导入

https://blog.sy-zhou.com/%E7%94%A8%E4%BA%8E%E6%94%AF%E4%BB%98%E5%AE%9D%E5%92%8C%E5%BE%AE%E4%BF%A1%E8%B4%A6%E5%8D%95%E7%9A%84beancount-import/ # Importer 使用

【Beancount】5. 项目管理

· 阅读需 7 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.

Beancount 系列文章的前四篇已经基本覆盖了常用的复式记账方法。记账本身是一门经验的学问,不仅包括账本身怎么记,还包括了「账本」怎么整理。这篇文章不涉及复杂的会计学概念,只是从经验、工程的角度来讲一讲我实际记账过程中账本是怎么组织的。

账本组织结构

目前为止我们假设所有的 Beancount 记录都是在单一文件中的,这个文件会随着账目的增多越来越膨胀,直到用编辑器维护不便。

Beancount 允许将账本拆分,然后通过 include 语法将账本进行关联起来。利用这个简单的语法,就可以将一个巨大的账本分成若干个较小的账本,方便管理和查找。但 Beancount 最终会把所有交易都读到内存里后按日期重新排序,所以每条交易在文件里出现的顺序并不重要。

尽管有 " 文件包含语法 (include)",但每条记录到底怎么划分还是一个仁者见仁智者见智的话题,下面是我根据自己的经验对账单进行一个分割管理。但首先要明白划分的目的:

  1. 降低维护成本
  2. 尽量减少可能的错误

选择自己合适的组织结构,这是一项大工程

我的账本目录结构如下:

Beancount-Trans-Assets/
.
├── 2022 ; 以年做分割
│ ├── 00.bean ; include该目录下的其他所有文件
│ ├── 01-expenses.bean ; 2022年01月份账单(支出、转账等)
│ ├── 02-expenses.bean
│ ├── 03-expenses.bean
│ ├── 04-expenses.bean
│ ├── 05-expenses.bean
│ ├── 06-expenses.bean
│ ├── 07-expenses.bean
│ ├── 08-expenses.bean
│ ├── 09-expenses.bean
│ ├── 10-expenses.bean
│ ├── 11-expenses.bean
│ ├── 12-expenses.bean
│ ├── cycle.bean ; 周期性费用/交易目录(每月信用卡还款、水电费、车贷房贷等)
│ ├── event.bean ; 事件记录(位置、入职离职情况、重要日子记录等)
│ ├── income.bean ; 除投资外的所有收入(薪资、红包、副业等)
│ ├── invoice.bean ; 报销
│ ├── price.bean ; 跟踪通货(例如黄金、股票等)价格情况,方便在合适的时候买入卖出
│ ├── securities.bean ; 投资记录
├── account ; 保存五类经典账户的启用及关闭
│ ├── assets.bean
│ ├── equity.bean
│ ├── expenses.bean
│ ├── income.bean
│ └── liabilities.bean
├── depreciation.bean ; 折旧账单,具体使用看'结余与资产',已经列出该账单的详细使用
├── document ; 存放例如账单文件等文档目录
│ └── Syntax_Cheat_Sheet.png ; beancount格式小抄
└── main.bean ; 主账本,使用fava main.bean输出可视化界面

最底下的 main.bean 是我的主账本(查账执行 fava main.bean)。该文件的内容如下:

; main文件
; 1. 账本信息
option "title" "xxx的账本"
option "operating_currency" "CNY" ; 人民币
option "operating_currency" "COIN" ; 不可流通,1:1转换人民币
option "operating_currency" "TIME" ; 按次记录
2022-01-01 custom "fava-option" "language" "zh" ; 配置fava以中文显示

; 2. 账户设置
include "accounts/assets.bean" ; 资产账户设置
include "accounts/equity.bean" ; 负债账户设置
include "accounts/expenses.bean" ; 支出账户设置
include "accounts/income.bean" ; 收入账户设置
include "accounts/liabilities.bean" ; 权益账户设置

; 3. 插件管理
plugin "beancount.plugins.forecast" ; 分期插件
plugin "beancount.plugins.auto_accounts" ; 根据条目自动添加账户插件

; 4. 定期折旧
include "depreciation.bean"

; 5. 交易记录
include "2021_template/2021_template.bean" ; 该文件是模板文件
include "2022/2022.bean"

我使用 include 导入了 6 个文件,其中 5 个账户设置文件,1 个年度账本。

Assets 账户设置文件模板如下:

; 人民币,包括各类银行卡,微信支付宝和别人的欠款
2022-01-01 open Assets:Savings:Bank:ZhaoShang:C8837 CNY ; 银行卡
2022-01-01 open Assets:Receivables:Personal:XXX CNY ; XXX的欠款(自己的资产,可以理解为先给对方保管,当对方还钱后再加回到银行卡并关闭账户)

; 代币,不方便流通但与人民币1:1等值兑换,包括储值卡,公积金账户及投资
2022-01-01 open Assets:Savings:Recharge:YiMing COIN ; 充值
2022-01-01 open Assets:Savings:Recharge:YongHeDouJiang COIN ; 2022-01-01是我的初始化时间
2022-09-09 close Assets:Savings:Recharge:YongHeDouJiang ; 当储值卡不再使用后推荐及时关闭,fava中也随之不再显示
2022-01-01 open Assets:Investment:AliPay:Gold ; 投资,可以按克重来计算

; 点券,与人民币非等值兑换
2022-01-01 open Assets:Savings:Recharge:HuaWei:Read TOKEN
2022-01-01 open Assets:Savings:Recharge:WangZhe TOKEN ; 例如在王者荣耀中1人民币=10点券

; 按次消费
2022-09-04 open Assets:Savings:Time:Foot TIME ; 洗脚,有点类似储值消费但又是按次来使用的(经实际验证我将该记录保存至time.bean文件,消费后则关闭该账户)

2022.bean 文件仍然没有交易记录,而是继续导入其它账本,其账本如下:

; 2022.bean文件
include "0-default/00.bean" ;默认目录,每月日常支出,收入,转账等(当年的收入、转账、event 事件)
include "1-securities/00.bean" ;证券投资目录(股票和基金买卖记录)
include "2-trip/00.bean" ;旅行 & 出差目录(旅行出差的账本,命名日期-地点.bean)
include "3-cycle/00.bean" ;周期性费用/交易目录(每月信用卡还款、水电费、车贷房贷等)
include "4-project/00.bean" ;项目目录(车子、房子等大宗商品)

概括起来,我的账本结构分三层:

第 1 层:main.bean 作为主账本,include 各个账户文件及每年账本文件。

第 2 层:每年有个目录,下设 年份.bean 的文件,include 各个子目录下 00.bean 文件。

第 3 层:每个子目录下 00.bean 文件 include 该目录下所有正式的记账文件。

这样设计优点:

  • 按年组织,往年数据直接存档,不会被破坏
  • 年份目录下进行分类记录,避免放在一个文件不好维护

总结

还是那句话,复式记账只有规范,没有对错。我把我的记账原则总结成了以下规则,在记账前先行判断:

  1. 如果是收入(对于先替别人付,然后别人转账给我的条目记为应收款项而不是收入,参考 Beancount_02_借贷记账法 中的借贷管理),统一记录到当年的 income.bean 中,如果收入较多(我不理解,但我大受震撼),可以将最近的收入上往下记录,这样打开文件可以直接看到最近的收入;
  2. 如果该支出属于投资类型,那么就加入到 securities 目录。若是考虑到投资种类,可以在投资类型下继续细分为股票、黄金等;
  3. 如果该支出是一个周期项目,例如信用卡还款、订阅、话费、贷款、折旧等,加入到 cycle.bean 目录中。
  4. 如果是在旅游、出差过程中产生的支出,则记录在 []-expenses.bean 目录中并打上标签 pushtag #20221001-hangzhoupoptag #20221001-hangzhou 方便索引;如果遇到需要报销的场景,则额外为报销添加链接 ^201909-out
  5. 如果该支出是一个大宗项目(具体多少算大宗根据自身情况),同样根据标签 #Hone 进行索引。
  6. 不属于以上情况,统一加入按日期划分的文件
2024-01-08 * "古茗" "商品详情"
time: "18:23:03"
uuid: "4200002101202401080969304458"
status: "WeChat - 支付成功"
Expenses:Food:DrinkFruit +26.00 CNY
Liabilities:CreditCard:Bank:ZhaoShang:C4523 -26.00 CNY
  1. 每月 1 号早将所有账户 balancae 断言后再对账,所有账单条目清晰后对于利息造成的误差使用 pad 进行填充。对于 pad 和 balance 日期有疑问可回看 Beancount_04_结余与资产
2023-01-14 balance     Liabilities:CreditCard:Bank:ZhongXin:C6428  -4633.20 CNY  ; 信用卡
2023-01-13 pad Assets:Savings:Bank:NingBo:C1746 Income:Investment:Interest ; 投资收益
2023-01-14 balance Assets:Savings:Bank:NingBo:C1746 2395.62 CNY ; 银行卡
2023-01-13 pad Assets:Savings:Bank:ZhaoShang:C8837 Income:Investment:Interest
2023-01-14 balance Assets:Savings:Bank:ZhaoShang:C8837 7959.36 CNY
2023-01-13 pad Assets:Savings:Web:WechatPay Income:Investment:Interest
2023-01-14 balance Assets:Savings:Web:WechatPay 784.54 CNY
2023-01-14 balance Assets:Savings:Web:AliPay 0.00 CNY

【Beancount】4. 结余和资产

· 阅读需 9 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.

借贷记账法 中我粗略介绍了 Beancount 的基本记账方法和一些常见的规范,但这已经能满足日常生活的记账工作了。这篇继续讲述 Beancount 的常用语法,主要内容是对账和资产折旧。

对账

在每次记账后根据 fava 中的错误提示修改出现的错误,其实 Beancount 的语法规范已经避免了很多可能导致「账不平」的错误,但是对于数额本身的错误,或者某条账目漏记并没有办法,这就是为什么我们要定期对账。

所谓对账,其实就是将可视化界面的资产负债表中的结余与自己的实际结余对比,看数额是否一致。在资产负债表上点击任意账户,可以进入账户的明细界面。账户的明细界面列出了涉及该账户的每一笔交易,点开后可以看到具体的交易信息。每一行的最右侧是这一笔交易后的该账户结余,根据账户列出的每一笔交易再与实际账单进行对比,这就是对账的核心。

Fava 日记账案例

定期结余断言

假设已知账户的某日结余金额,只要在这个账户明细界面看一看对应的日期的最后一笔交易后结余是否正确就可以了。如果 Beancount 计算出的结余和已知的是一样的,那么基本上就可以确定账没有问题。

这个步骤看似容易,但是随着账目增多,对账的负担会很重,而且容易看错。更严重的问题是,如果因为某种原因要修改过去的账目,已经对好的账就不一定正确了。唯一保险的办法是每次修改了过去日期的交易后,把涉及到的账户未来的结余再全部重新对一遍。好在这个过程是可以自动化的,方法就是使用结余断言(Balance Assertion)。

结余断言就是在记账中加入已知事实,即标记某个日期某个账户的结余,一本维护良好的账本应当定期做结余断言(assertion)。结余断言的语法非常简单,如下例所示:

2022-09-01 balance Assets:Savings:Bank:ZhaoShang:C8837 18422.00 CNY

唯一需要留意的地方是,结余断言是所声明日期开始的时候的余额,即当日的交易不算在内。因为 Beancount 的时间精度是「日」,所以诸如 open, close, balance 等带日期的语句,均发生在当日的第一笔交易之前,你可以想像它们都是在凌晨发生的,而普通的交易都是发生在白天。因此,要断言一月份的余额,日期应写作 02-01 而不是 01-31。同样地,信用卡等通常为负数的账户也能进行断言,比如小红的信用卡账单日为 20 日,2 月份账单应还款 5000 元,那她的断言应该这样写(注意日期是第二天,也就是 21 日):

2022-08-21 balance Liabilities:CreditCard:Bank:ZhongXin:C6428 CNY -5000.00 CNY

声明结余断言之后,Beancount 会自动检查账户的数字是否与断言的数字相等,如果不相等就把报错。人总是会犯错的,当你因为各种原因在账目上出现了错误,断言能帮助你缩小查错范围——你只需要检查最后一次成功的断言之后的发生的交易即可。如果每个账户都有适当的结余断言,修改过去的交易就可以放心进行了。

合理填充

但是当账户出现与结余断言不一致且不愿意花时间去排查时,可直接通过 pad 关键字直接从指定账户中补齐与断言不一致的金额。例如在上述案例中,我的余额是购买了招商银行的朝朝宝,每天都有相应的收益,若每天对结余进行断言显然不合适,所以我每个月最后一天除了断言开销外,还会从投资收益中直接补齐一个月的利息。

2022-08-31 pad Assets:Savings:Bank:ZhaoShang:C8837 Income:Investment:Interest
2022-09-01 balance Assets:Savings:Bank:ZhaoShang:C8837 18422.00 CNY

由于 pad 与 balance 常关联使用,使用 pad 填充功能其实还有一个隐性的好处。因为 balance 可以指明指定时间指定账户中的余额,无法追溯的金额则统一由 pad 进行自动计算并插入交易。如果某一天,你想起在之前的时间有一段支出未记录,重新记上去,那么这个差额会自动变小。

大宗商品的购入和折旧问题

生活中有一些交易我们需要考虑到底要记为花费,还是资产的购入。在光谱的两端一般没什么争议,譬如吃饭肯定是消费,买房无疑是购入资产。中间许多类别就不一定了,这取决于个人的偏好和目的,例如我会将后续可能出售的资产、大宗商品等记为购入资产(即新建 Assets 账户用于折旧)。

拿买汽车作为例子,无论是新车还是旧车,许多人在开一段时间以后会选择卖掉。如果我们把买车记为消费,卖车记为收入,这本身并没有任何错误。问题是,对很多人来说汽车还是一笔不可忽略的资产,如果直接记为消费,没有对应的资产入账,那就意味着净资产突然大幅减值。几年后卖出,净资产又突然增加。

要解决这个问题,我们就要把汽车记为一项资产,下面是例子:

2023-02-04 * "比亚迪"
Expenses:TransPort:Private:Car 2049.00 CNY ; 底盘护板
Expenses:Finance:Service 4000.00 CNY ; 贷款服务费
Expenses:Finance:Service 500.00 CNY ; 上牌服务费
Assets:Receivables:Organization:BYD 5000.00 CNY ; 中转,两个星期内返还
Assets:Depreciation:Car:BYD -2000.00 CNY ; 定金
Equity:OpenBalance -9549.00 CNY
Income:Government:Subsidy:Car -5000.00 CNY ;
Assets:Receivables:Organization:BYD 5000.00 CNY ; 购车补贴,六个月内返还
Income:Receivables:Card -300.00 CNY @@ 300.00 COIN ; JD购物卡
Assets:Savings:Recharge:JD 300.00 COIN ; 截止至2026年01月09日
Expenses:TransPort:Private:Insurance 7564.47 CNY ; 保险
Liabilities:CreditCard:Bank:ZhongXin:C6428 -7564.47 CNY

2023-02-04 * "比亚迪"
Assets:Depreciation:Car:BYD 259800.00 CNY ; 总金额
Equity:OpenBalance -110000.00 CNY ; 首付
Liabilities:Payables:Organization:BYD -149800.00 CNY ; 剩余贷款
Expenses:Finance:Loans 12188.48 CNY
Liabilities:Payables:Interest:BYD -12188.48 CNY ; 总利息,年利率7.95%,还款期数36期,开始时间2023-02-06

2026-02-04 * "比亚迪" "卖出海豹"
Assets:Depreciation:Car:BYD -259800.00 CNY
Assets:Savings:Bank:ZhaoShang:C8837 160000 CNY ; 以16W卖出
Expenses:Depreciation:CarUsage 99800 CNY ; 3年折旧支出

上述例子是 2023 年 2 月 4 日贷款计息 161988.48 元总计买入价格为 25.98W 的汽车,并计入资产 Assets:Depreciation:Car:BYD。中间省略还贷款的过程,3 年后的 2026 年 2 月 4 日,将车卖给二手商获得 16W,剩下的 9.98W 就是这四年来用车的费用了。

这个方法对买卖交易之间的这段时间内净资产计算仍然不够准确,并没有完全解决净资产跳变。因为汽车的使用是四年来平均花费出去的,而不是最后卖的时候一下子花了 9.98W。要解决这个问题就要引入定期进行折旧(Depreciation)计算。一般的会计方法中把因为资产使用或者随着时间自然减值称为折旧,我记为 Expenses:Depreciation:CarUsage

接下来需要决定的是折旧的周期,即把车的使用费按照多大的粒度来记录。这个完全因人而异,也因金额的大小而异,对于车我可以选择按年折旧,如果希望每个月的花销更加细致,那么按月折旧也是一个方案,只是需要多记录几笔而已。

2024-02-04 * "海豹折旧"
Assets:Depreciation:Car:BYD -30000.00 CNY
Expenses:Depreciation:CarUsage 30000.00 CNY

2025-02-04 * "海豹折旧"
Assets:Depreciation:Car:BYD -30000.00 CNY
Expenses:Depreciation:CarUsage 30000.00 CNY

2026-02-04 * "海豹折旧"
Assets:Depreciation:Car:BYD -30000.00 CNY
Expenses:Depreciation:CarUsage 30000.00 CNY

; 或者使用如下方法进行折旧

2024-02-04 balance Assets:Depreciation:Car:BYD 240094.08 CNY ; 通过商业险获取折旧金额
2024-02-03 pad Assets:Depreciation:Car:BYD Expenses:Finance:Depreciation

下一个问题是,每次折旧减值多少。这个问题就是会计上可以操作的空间了,因为实际的价格只有在出售的时候才知道。一般会计准则是预估一个折旧年限,然后以此为根据来折旧。譬如说,我们预期汽车的寿命是 10 年,即 10 年后该车的价值清零,这样我们可以按照每年 10% 的折旧率每年减记。最终当实际卖出的时候,我们再根据卖出价格做调整,或者差额记为其他类别。如果有特别的事件发生,还可以另外单独折旧。例如发生了车祸,车的估值大幅下降,可以在此时额外减值。

Beancount 并没有自动折旧的功能,每一笔都是要自己写的。如果怕忘了,其实可以把未来日期的折旧也写上。另外还有第三方的插件 beancount-interpolate 可以尝试使用。

周期

在日常的记录中,多久进行一次记录多久进行一次汇总断言呢?刚入门的时候,由于对 Beancount 不太熟悉,可以每日一记,同时将自己跟钱有关的所有账户都记录到 Beancount 中,因为你不可能在刚记账的时候就已经将所有账户都统计到位了,所以每日一记不仅能帮助你熟悉复试记账的用法还能对账户查缺补漏。当对 Beancount 有一定了解,且出现记账错误能根据资产负债表快速定位错误时,可以将记账周期放宽。在刚开始做时,可能会花费 30 分钟到 2 个小时不等的时间,但随着你的消费习惯越来越成熟, 这个时间会快速地缩减。

目前推荐的做法是:每周对常用账户进行记录并 balance 对账(通过支付宝、微信、银行卡、信用卡账单),每月初汇总上月的被动收入,填充无法回溯的支出,回顾支出情况等。当然,如果有兴趣的话可以了解一下 importer 自动导入账单和 账单转换

【Beancount】3. 高级用法

· 阅读需 3 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.

高阶用法

事件

事件指令用于跟踪某个变量的值,例如位置 :

2023-01-04 event "Record" "洗牙"
2022-09-12 event "Location" "浙江杭州 -> 浙江温州"
2022-09-11 event "Location" "浙江温州 -> 浙江杭州"
2021-08-23 event "Employer" "入职 | xxx有限公司 | 温州 | 运维工程师 | 薪资 8000"
2021-08-20 event "Employer" "离职 | xxx有限公司 | 上海 | 技术支持工程师 | 薪资 8500"
2020-10-11 event "Employer" "入职 | xxx有限公司 | 上海 | 技术支持工程师 | 薪资 7500"

上述指令说明,从 2022 年 09 月 11 日起,将 "Location" 事件的值更改为 " 浙江温州 -> 浙江杭州 ",特定事件类型每天只有一个值。

Event 指令的一般格式是:

YYYY-MM-DD event Name Value  ; 这是Event指令的一般格式

Event 事件最好的用法就是跟踪自己的所在位置、国家和工作的入职记录、离职记录等。

标签

标签 (Tag) 可以给记录打上字符串标记:

2022-08-18 * "高德" "打车" #20220910-hangzhou
Expenses:TransPort:Public:Taxi 9.26 CNY
Liabilities:CreditCard:Bank:ZhongXin:C6428 -9.26 CNY

为记录打上标签最大的作用是能将标签作为过滤器,fava 可以只看有关此标签的报告,推荐是将标签功能用来标记所有的旅游。

深度截图_选择区域_20230209124918

另外可以使用特定语法 pushtagpoptag 为所有包含在内的记录打上相同标签,方便统计。

pushtag #20220910-hangzhou

2022-09-06 * "此印酒店" ^ChaoXiang-invoice
Expenses:Entertainment:Hotel 222.71 CNY
Liabilities:CreditCard:Bank:ZhongXin:C6428 -222.71 CNY

2022-09-06 * "中国铁路" "去程及返程票" ^ChaoXiang-invoice
Expenses:TransPort:Public:Railway 651.89 CNY
Liabilities:CreditCard:Bank:ZhongXin:C6428 -651.89 CNY

poptag #20220910-hangzhou

报销

交易可以通过 ^ 链接在一起。可以将链接视为一种特殊的标签,可用于将一组财务相关的交易组合在一起。

垫付有多种情况,聚餐时的 AA 制、公司出差时事后报销,都会导致不得不进行垫付。当然,垫付并不代表实际支出,它只是代表你的钱从你的现金账户里,转移到了「应收账款」这个账户,你的净资产仍然不变。这种情况下应当记账记为:

plugin "beancount.plugins.tag_pending"

2022-09-06 * "此印酒店" ^wlhiot-invoice ; 由ChaoXiang进行报销
Assets:Receivables:Organization:Wlhiot 222.71 CNY ; 应收款项
Liabilities:CreditCard:Bank:ZhongXin:C6428 -222.71 CNY
2022-10-06 * "wlhiot" "报销到账" ^wlhiot-invoice
Assets:Receivables:Organization:Wlhiot -222.71 CNY ; 报销不能算是收入,只能算是资产的流入流出
Assets:Savings:Bank:ZhaoShang:C8837 222.71 CNY ; 招商银行报销到账
Assets:Savings:Bank:ZhaoShang:C8837 -222.71 CNY ; 招商银行还款
Liabilities:CreditCard:Bank:ZhongXin:C6428 222.71 CNY

最佳实践

股票

;证券投资相关的记录会更加完整
;语法:时间 [对账标志位] 收款人 备注
; 账户A 数量 通货名称{成本价} @现价 或者 @@总价
; 账户B 变动情况
; 账户C 变动情况

2022-09-02 * "A股" "33.29元加仓400股中银证券" ; 买入模板
Assets:Savings:Bank:ZhaoShang:C8837 -13316.00 CNY
Assets:Investment:Stocks:NongYe3908 400.00 A_601696 {{13316.00 CNY}}
Expenses:Invest:Cost 5.00 CNY
Assets:Savings:Bank:ZhaoShang:C8837 -5.00 CNY

2022-09-03 * "A股" "43.29元卖出400股中银证券" ; 卖出模板
Assets:Investment:Stocks:NongYe3908 -400.00 A_601696 {{}} @@ 17316.00 CNY
Income:Investment:Interest -4000.00 CNY
Expenses:Invest:Cost 5.00 CNY
Assets:Savings:Bank:ZhaoShang:C8837 -5.00 CNY
Assets:Savings:Bank:HuaXia:C5636 17316.00 CNY

【Beancount】2. 借贷记账法

· 阅读需 9 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.

账户类别

复式记账的最基本的特点就是以账户为核心,Beancount 的系统整体上就是围绕账户来实现的。Beancount 中账户名支持层级,以英文冒号 : 分隔,如 Assets:Card:1234。但第一层必须是以下五个账户之一,日常交易中涉及到的账户,一定可以归于其中某一类:

  1. Assets 资产:储蓄卡余额、支付宝余额、股票、房产、汽车等(房子车子可以以金额入账方便折旧)
  2. Liabilities 负债:信用卡欠款、房贷、车贷等
  3. Equity 权益:可以看作是净资产,也可用于账户初始化、误差处理等
  4. Expenses 支出:生活中的一切支出,指不再进行转卖以获取利益的支出
  5. Income 收入:工资、奖金、投资收益等

接下来需要声明账户的开户时间,格式为 YYYY-mm-dd open [账户名称] [货币]。其中账户名称需自定义且用 : 进行分隔(但必须归属于 5 类账户),货币种类可自定义,例如我在以下例子中就使用了 CNY 作为人民币,COIN 做为储值类代币:

2022-01-01 open Assets:Savings:Bank:ZhaoShang:C8837 CNY ; 银行卡
2022-01-01 open Assets:Savings:Recharge:AliCloud COIN ; 储值类使用COIN指代
2022-01-01 open Liabilities:CreditCard:Bank:ZhongXin:C6428 CNY ; 信用卡
2022-01-01 open Equity:OpenBalance ; 初始化账户

账户如何组织分类完全看个人需求和喜好,譬如我先分账户类型,再分功能,然后是金融机构名,最后是具体账户。分类的作用是可视化的时候,可以看某个账户下面所有账户的汇总。

账户 open 开启时间可用真实时间,若无从考据可设置为开始使用复式记账前一天或今年伊始(例如我 2022-08-16 开始记账,开启时间就设置为 2022-01-01)。开设账户时货币类型不是必须的,但建议加上,记录交易时货币不一致 Beancount 会报错。货币可设多个,用英文逗号(,)分隔,但如果某个账户的货币组成形式较复杂也可省略。

最后,如果一个账户不再使用,比如注销信用卡、关闭充值卡等。可用 close 命令关闭账户:

2022-01-02 close Liabilities:CreditCard:Bank:ZhongXin:C6428 ; 信用卡被注销

为什么需要大量时间来初始化账户?

在正式记账前,一般资产和负债都不会是 0,因此需要提前初始化所有的账户的余额(初始化数量较多可根据实际情况制定),例如 Assets 账户若要精细到各个银行卡账户的余额则要为各个银行卡创建相应的账户并初始化。这需要大量的时间来思考自己有哪些账户且哪些账户需要纳入管理,在 '项目管理' 篇章中提供我定义的所有账户及规范。

初始化需要用到 Equity 账户,以下为初始化案例,C8837 储蓄卡中的 10000 元来自 Equity:OpenBalance 账户:

2022-08-16 * "存款初始化"
Assets:Savings:Bank:ZhaoShang:C8837 10000.00 CNY
Equity:OpenBalance ; Beancount假设总和一定是0,当上条记录为10000时,该条记录自动记录为-10000,无视货币形式(账户允许的情况下)

基本借贷

有了以上定义的账户以后,我们终于可以开始实践记账了。复式记账又叫作「借贷记账」。之所以这么叫,是因为每一条记录都至少有一条借记(Debit)和一条贷记(Credit)。可以看下面这个例子:

2022-09-06 * "中国铁路" "去程及返程票"
Expenses:TransPort:Public:Railway 651.89 CNY
Liabilities:CreditCard:Bank:ZhongXin:C6428 -651.89 CNY

其中:

  1. * 表示这笔交易是确定的,没有疑问。若是 ! ,表示存疑,但一般用不上。
  2. 交易方(中国铁路)和交易备注(去程及返程票),均可省略。
  3. 货币必须与账户设置中对应的货币类型一致。比如账户设置为美元账户,消费时出现人民币,Beancount 会报错。

此外,账户后的金额是带有符号的,如下:

  1. 支出账户:一般为正数。表示花费多少钱。
  2. 收入账户:一般为负数。表示收入多少钱。投资收入账户如果出现正数,则表示投资亏损。
  3. 资产账户:可正可负。正数表示有钱存入,余额增加;负数表示有钱支出,余额减少。
  4. 负债账户:可正可负。正数表示还款,负债减少;负数表示借款,负债增加。

**支出为正,收入为负,**有点反直觉,是会计恒等式逻辑所致。会计恒等式具体表述如下:

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

这里有一个要点:要保证所有条目的总和是 0,否则就会出现 Transaction does not balance: (xxx USD) 这样的错误。这个要求很好理解,因为花出去的钱必须和账户上减少的钱一样,否则就是所谓的「账目不平」了。Beancount 语法的灵活性在于每个记账单元可以有任意多个条目(借记和贷记),只要保证它们的总和是 0 就可以。于是我们还可以这样记录:

2022-10-21 * "日常消费"
Expenses:Food:Breakfast 8.60 CNY
Expenses:Food:Lunch 9.00 CNY
Expenses:Food:Dinner 25.00 CNY
Expenses:Food:DrinkFruit 12.00 CNY
Assets:Savings:Web:AliPay -37.00 CNY
Liabilities:CreditCard:Bank:ZhongXin:C6428 -17.60 CNY

该例子体现了对工资条的内容进行记账,因为每个月的工资条总有各种各样的条目需要扣除。在使用了 Beancount 之后,可以方便地把工资、补贴、五险一金、个税等信息都记录进去,以后能很方便地统计每个月有多少工资是喂狗的。这块需要解释一下,我的工资基数为 8000,但公司只为我缴纳 483 的公积金,剩下的公积金由我自行支出从工资中扣除。

2022-07-21 * "wlhiot" "六月份工资"
Income:Salary:Wlhiot -8000.00 CNY ; 正常薪资
Income:Salary:Subsidy:Meal -357.00 CNY ; 餐补
Income:Salary:Subsidy:Provident -483.00 COIN ; 公司缴纳的公积金
Expenses:Government:Insurance 468.23 CNY ; 社保
Expenses:Government:Provident -1,417.00 CNY @@ 1,417.00 COIN; 以公积金入账
Expenses:Government:Provident 1,417.00 CNY ; 本人额外缴纳的公积金,但以CNY支出
Expenses:Government:IncomeTax 44.15 CNY ; 个人所得税
Assets:Savings:Government:Provident:WenZhou 1900.00 COIN ; 工资金账户
Assets:Savings:Bank:HuaXia:C5636 6427.62 CNY ; 实际银行到账的金额

货币转换

在使用多个货币之前,需要先定义「通货」,通货可以不止一个,例如:

option "operating_currency" "CNY"
option "operating_currency" "COIN"

定义了通货以后,在 fava 界面中可以看到工作货币单独列出的栏目,其他未定义但有记录的货币则会记录到 ' 其他 ' 栏。Beancount 货币转换的语法有两种,一种是使用 @ 记录单位货币的转换价格,另一种方式更符合人的习惯,使用 @@ 记录转换后的总额,之后的记录均以总额进行记账。

使用代币支付

在工资的例子中,其实已经用到货币转换的功能。在日常生活中,也会经常用到该功能,例如储值卡消费、国外旅游等。例如在加油站账户充值了 100 元,我是以人民币形式支出,但是以代币的形式记录在加油站,当在加油站进行消费时,也是以代币的形式进行记录,这是可以通过以下案例来记录(下述账户均已初始化):

2022-08-17 * "MHPC" "加油站储值"
Assets:Savings:Recharge:MHPC 505.00 CNY @@ 505.00 COIN
Income:Receivables:Coupon -5.00 CNY ; 充值赠送
Assets:Savings:Bank:ZhaoShang:C8837 -500.00 CNY
2022-08-17 * "MHPC" "加油站消费"
Expenses:TransPort:Private:Oil 200.00 COIN
Assets:Savings:Recharge:MHPC -200.00 COIN

借贷管理

复式记账的强大之处是每个账户都有状态,而且每个操作都是原子的,这对复杂的资金进出记录非常有帮助。

生活中一个常见的例子是朋友之间的借钱和相互垫付,例如我和 X、Y 三人去一起出游,从东京附近的横须贺坐船到猿岛,费用是每人 1300 日圆的船票和 200 日圆的登岛费,其中船票可以用信用卡支付,而登岛费只能付现金。我们一共需要付 4500 日圆,但是正好谁都没有这么多现金,于是决定我用信用卡付三人的船票,X 用现金付三人的登岛费,最后再结算。

2019-05-25 * "猿岛" "渡轮"
Expenses:Transport:Ferry 1300 JPY ; 个人渡轮费用
Assets:Receivables:X 1300 JPY ; 对X应收款项
Assets:Receivables:Y 1300 JPY ; 对Y应收款项
Liabilities:CreditCard:JP:Rakuten -3900 JPY

2019-05-25 * "猿岛" "登岛费"
Expenses:Transport:Attraction 200 JPY ; 登岛费
Liabilities:Payable:X -200 JPY ; 欠X的钱

第二天,三人结算完毕,X 付给我现金,Y 转账给我。

2019-05-26 * "猿岛" "费用结算"
Assets:Receivables:X -1300 JPY ; X偿还债务
Liabilities:Payable:X 200 JPY ; 偿还对X的债务
Assets:Cash:JPY 1100 JPY ; X实际付给我的钱到账
Assets:Receivables:Y -1300 JPY ; Y偿还债务
Assets:Bank:JP:SMBC:JPY 1300 JPY ; Y实际付给我的钱到账

最终可以看出来,我在 Expenses:Transport:Ferry 类别消费 1300 JPY,在 Expenses:Transport:Attraction 类别消费 200 JPY,信用卡扣款 3900 JPY,收到了 1100 JPY 的现金,Assets:Bank:JP:SMBC:JPY 收到了 1300 JPY 的转账。

以上这种记账方法可以让资金的流动一目了然,类别和金额也准确无误。记录对他人的债权(应收账款)和欠他人的债务(应付账款),我分别使用了 Assets:ReceivablesLiabilities:Payable 下面的账户。

应收账款和应付账款的另一个用途是区分付款和到货时间。一般来说交易是当场进行的,一个账户的借记和另一个账户的贷记同时发生,但是有些时候付款和到货并不是同时发生的,如果需要精确区分发生的时间的话,可以用这种方法把他们分成两笔记录。

到此为止,Beancount 基本的借贷用法已经介绍完毕,剩下比较重要的就是对资产的结余进行断言和 Beancount 项目管理,当学会 借贷断言项目管理 就可以进行完整的记账历程

【Beancount】1. 选型

· 阅读需 7 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.

记账方式

首先先回答我几个问题:

  1. 为什么要记账,换句话说记账的目的是什么?
  2. 现有的记账方式不满足需求吗?

对自己有清晰的认知

接第一个问题,为什么要记账,以及你是否已经想好如何将记账这件事融入你的生活甚至变成一辈子的习惯。记账这件事是那种容易让人因为一时冲动开始,但是很快就放弃的事情。每个记过账的人都有不同的原因和契机,但能坚持下来的则凤毛麟角。

我的回答是,实现财务自由(即资产产生的收入不少于生活开销)。如果不知道自己有多少开销,甚至不知道自己有多少资产、收入,即使一夜暴富,财务自由也是一件虚无缥缈的事,因为你不知道现有的资产够你生活多久,换句话说就是「退休」,只不过有人能在三十多岁退休,有人要六十岁,有人则要到八十岁。只要在预期的寿命之间资产产生的现金流能覆盖生活所需的开销,这就是财务自由。我对资产产生现金流的定义较为宽泛,不仅包括利息、分红、租金、版税这类收入,还包括了直接通过资产折现的收入,即净资产减少。

为什么要选择复式记账 (Double-Entry)?

要想回答第二个问题,咱们需要先了解普通记账,这也是大部分人使用的方法:只记录收支,而不记录各账户的变动。这就有一个问题,你不清楚自己各个账户中都有多少钱,也就不清楚自己的总资产是多少。而且若是充值消费的场景,你是记为一次性支出呢还是分次来记录呢,如果按一次性支出,当你消费时,就不需要再记录支出的场景就会出现记账的空白;但如果按分次使用来记录,那账单就更乱了(只记录了这么一部分钱,那其他大部分的钱哪儿去了)。这种记账方式一开始简单,但能带来的价值有限,只是开支记录而已,长期看来难以说服自己为了这些价值而忍受麻烦的记账过程。

虽然有各种各样的手机应用号称可以简化记账,它们把用户交互做得更加简单友善,有的还可以从银行账户、信用卡公司直接抓取数据,降低心理障碍,但与此同时它们却带来了另一个问题,就是数据所有权、安全性和持久性的疑虑。这些工具大多都是把数据存储在云端的,对于大公司,利用数据做大数据分析来完善用户画像是必然的事情(账单上的信息真的太多太多)。更麻烦的是,它们几乎都是自己的专有格式,无法导出保存,或者哪怕可以导出也难以使用。一旦软件停止更新,用户的数据就危在旦夕:难以导出,难以复用,很难跨平台或跨设备同步。这也意味着你不得不一直用一个产品,直到有一天倒闭或者服务关闭为止。这对任何人来说都是不可接受的,因为在互联网时代能活过十年的产品非常稀少,无论是像 Google 这样随意关闭服务的大公司,还是随时有可能倒闭的小公司。

相比普通的流水账,复式记账的核心理念是账户之间的进出关系,要求所有的记录全部入账,它可以保证账目的完整性和一致性,即**" 有借必有贷,借贷必相等 "**。复式记账可以提供除了开支记录之外的损益表、资产负债表、现金流量表、试算平衡表等报表。复式记账还可以把投资和消费轻易区分,譬如购入房产、汽车等可以作为资产项目入账并定期折旧。同理对各种代金券、点数积分的购入一样要算入资产而不是消费。

[核心] 会计恒等式

作为会计学的核心,复式记账是一种实践中诞生的技术。除了最基本的会计恒等式之外,复式记账只有规范,没有对错。那么什么是会计恒等式呢?最基本的形式就是:

资产 = 负债 + 权益(净资产)

这个等式对于没有接触过会计学的人来说可能不太容易理解,但是记账实践过马上会明白的。理解的难点在于,会计学上的「资产(Assets)」和一般人对一个人富有程度的理解不太一样,因为资产是负债和权益的总和,负债(Liabilities)也是资产的一部分。

更容易理解的部分其实是权益(Equity),在个人理财的上下文中,又和净资产(Net Assets)是等价的,也就是经常说的「个人净值」。净资产需要由总资产排除负债,一个人到底是否富有,看的是净资产,而不是资产

举例说明,一个人首付 20 万元,贷款 80 万元,买了价格为 100 万元的房产。假设这个人没有别的资产和负债,那么他的资产就是 100 万元,负债是 80 万元,而净资产是 20 万元。在房价没有变化的情况下,买房对一个人的净资产没有什么影响(忽略手续费的话),而他的资产和负债都暴增,也就是所谓的「扩大资产负债表」。

如果你理解了会计恒等式,那么复式记账的一切知识障碍已经扫除了。

Beancount 安装

再说一遍,复式记账在于实践,在开始实践之前学很多艰深的会计学概念没有任何意义。要开始实践,就要有工具上手了。推荐使用 Beancount,原因如下:

  1. Beancount 是一个开源工具,用 Python 实现的,可以本地运行。
  2. 账本是一套基于文本的语法,方便存储和管理,个人拥有全部的数据,如果觉得不好用可以随时转移到另一套工具,还可以使用 Git 管理。
  3. 账本的语法很规范,也具备灵活度,像编程语言一样可以嵌套引入,也有语法高亮和代码检查工具。
  4. 有完整的命令行工具链和可视化工具 fava,还有基于 SQL 的查询和报表生成。
  5. 没有货币概念,记录的是 commodity(通货),你不仅可以拿来记钱,也可以拿来记信用卡积分,记实物黄金等一切能记录的东西。

使用 Beancount 之前首先需要 Python 3 运行环境。Beancount 可以轻易从 PyPI 获得,使用以下命令(这里是一个示例账本:链接):

pip install beancount fava  # 其中beancount是核心包,包括了命令行工具,fava是网页可视化工具
fava example.bean # fava [示例文件]
Running Fava on http://localhost:5000 # 输出反馈

至此为止 Beancount 环境就已经设置好了。

致非程序员群体

不少人畏惧使用命令行(CLI)和纯文本来记账,尤其是非程序员的群体,但这些只是习惯问题。看到这,相信你们大概都使用过 APP 记账,对于 APP 上的支出例如餐饮、交通、居家等,在 Beancount 中不过是换算成餐饮账户、交通账户罢了。且 APP 记账的时间点一般为消费后及时记录,Beancount 则抽出 10 分钟统一为按天/按周进行记录。

在后续账户初始化及项目管理中,可能存在配置复杂的情况,在此 我提供目录结构,程序运行成功后使用浏览器通过 127.0.0.1:5000 即可访问。

Welcome

· 阅读需 0 分钟
Haorui Dai
Wenzhou Tingyun Technology Co., Ltd.