黑客神技!看我如何用Python跟踪个人财务!会计随身携带?让自己的每一笔收支都明细!

577 阅读11分钟

如何使用Python:Snake跟踪您的个人财务:

在这篇文章中,我想描述一下如何使用一个高度关注数据隐私、100%自我托管并且只使用Python生态系统的工作流来跟踪您的个人财务状况。

我也希望你们中的一些人觉得这足够有趣,可以更详细地探讨它。*)

我们都知道钱很重要。有钱给我们带来了自由,而缺乏金钱则是一种压力。那么,我们怎么知道我们在这方面做得好吗?

答案很简单:我们追踪我们的钱。

我们关注的是,有多少钱流入我们的帐户,有多少钱正在流出,以及这些事件何时发生和发生的频率。我们关注的是趋势,经常性的开支是什么,其中有多少是必需的,等等。

你很有可能已经这么做了。有很多现成的解决方案可以从中挑选出来。有移动和SaaS应用程序可以连接到您的所有银行帐户,导入您的所有金融交易,并显示您的综合数据。

并不是说这类应用程序有什么特别的问题。我不认为我的财务数据(从我所有的银行账户)都是只有我应该有统一的访问权限。金融数据是我拥有的最私密的数据之一。所以限制可能的攻击向量在我看来是一个明显的选择。

如果您正在搜索这样的软件,并且将您的搜索限制在仅开放源码的解决方案上,那么您很可能会遇到这样的情况。纯文本会计,这是我在这篇文章中描述的。

大(快速)图片

TL:DR:维护复式会计以纯文本文件为基础的金融交易记录是可行的。

复式会计是一个很好的方法来跟踪你的财务状况。在这个系统中,帐户之间的资金流动是用交易来表示的。你可以把一笔交易看作是一种“条目”,它涉及到账户间资金流动的一个特定实例。在大多数情况下,事务由两条“腿”组成,其中一条腿是信用另一边是借方侧面。

复式会计最重要的规则之一是,交易中单个分支的金额之和必须为零。如果符合这一规则,则称事务是“平衡的”。

下面是一个帮助您可视化的示例事务:

2021-01-01 * "AMAZON.DE"
    Assets:MyBank    -42.00 EUR
    Expenses:Amazon   42.00 EUR

这笔交易代表了我从我的一个账户中扣除钱的亚马逊公司的一笔交易。Assets:MyBank)并添加到亚马逊的费用帐户中。

这类交易的集合构成了你的财务分类账。

复式会计:HEADS:Python=Beancount

Python生态系统包含一个非常整洁的包,名为Beancount .

Beancount是在纯文本文件之上工作的复式记帐系统的命令行实现。它主要提供以下三项内容:

  1. 与金钱打交道的基本基本要素(如。数据结构,如帐户、交易、投递等)
  2. 一种以纯文本格式定义金融事务的语言规范(我前面展示的代码片段是有效的Beancount代码)。
  3. 命令行脚本,它将所有东西联系在一起。

和大多数Python包一样,入门就像创建虚拟环境和运行pip install beancount .

账簿是什么样子的?

我在前面写过,Beancount提供的主要功能之一是以纯文本格式定义金融事务的语言规范。

这种格式是什么样子的?下面是一个简单的例子:

option "title" "Alice"
option "operating_currency" "EUR"

; Accounts
2021-01-01 open Assets:MyBank:Checking
2021-01-01 open Expenses:Rent

2021-01-01 * "Landlord" "Thanks for the rent"
    Assets:MyBank:Checking     -1000.00 EUR
    Expenses:Rent               1000.00 EUR

你在这里看到的是一个虚构的人的非常基本的财务分类账。

在前几行中,我们指定了一些元数据。然后我们打开(初始化)两个帐户。最后三行定义了从其中一个账户中扣除租金并借记到另一个账户的交易。

请注意,帐户名称并不总是对应于现实世界的帐户一对一。您可以为特定目的定义任意数量的帐户。例如,您可以有一个帐户来跟踪您的超级市场费用,一个帐户用于租金,一个帐户用于Netflix,依此类推。

正如我所说,这是一个非常基本的例子。真实世界的分类账文件往往要长得多。

例如,在写这篇文章的时候.beancount文件包含近21,000行。

~/Work/finances main ❯ wc -l goel.beancount
20996 goel.beancount

数据是如何流动的?

我希望在这一点上,您对Beancount和复式会计有一个基本的理解.在本节中,我将快速地向您介绍在这样一个系统中数据是如何流动的。

Beancount的核心思想是用户负责将所有金融交易存储在.beancount档案。该文件是所有银行财务数据的唯一真实来源。

那么,您的银行交易是如何在这个文件中结束的呢?在一系列的三个简单步骤中:

1.从你的银行下载交易

几乎每一家银行都允许您以某种形式导出数据。您应该能够登录到您的银行的网站,选择一个时间框架,并下载一个给定的文件格式的所有交易。这通常是CSV,但您也可以下载PDF,有时还可以下载OFX档案。

这是Beancount驱动的工作流中的第一步:将所有原始数据下载到计算机中。

请注意,理想情况下,这应该是Python可以解析的东西,而不需要太多的仪式。例如,如果我在CSV和PDF之间有选择,我很可能会选择CSV下载。不是因为Python不能解析PDF数据(因为它可以)但是因为CSV是一种比PDF简单得多的数据格式。

2.将事务转换为Beancount格式

下一步是获取这些CSV文件,并将这些数据转换为Beancount所能理解的格式。

Beancount提供了一个进口商框架来帮助这个过程。进口商是接受源文件的Python程序(例如。下载的CSV),解析它,并将数据转换为Beancount提供的数据结构。这些数据结构的文本表示构成了您的个人分类账。

显然,Beancount并不知道地球上所有的银行,他们的CSV出口是什么样子,以及应该如何分析它们。这是Python开发人员可以在这里发光的地方。

这个ImporterBeancount附带的类更像协议。基类实际上被称为ImporterProtocol。它们定义方法签名,并将实现留给您。这样,您就可以继承基础。ImporterProtocol类,重写相关方法,并使用配置文件让Beancount知道这些导入器类的存在。

from beancount.ingest.importer import ImporterProtocol

def convert_to_beancount_data_structs(line):
    """
    Implement me!
    """

class MyBankImporter(ImporterProtocol):
    def extract(self, file):
        """
        Read and parse the file and convert the original data into Beancount
        data structures
        """
        entries = []

        for line in file:
            entries.append(convert_to_beancount_data_structs(line))
            
        return entries

根据您在哪些银行有帐户,您可以定义多个这样的进口商类,并让Beancount知道它们在配置文件中的存在。其他一切都将自动使用Beancount中包含的命令行脚本来处理。

3.平衡交易

下一步也是最有趣的部分(至少我觉得很有趣)。

我们采用前一步的输出,将所有的内容传递给我们的.beancount文件和“平衡”事务。

回想一下,复式会计中的资金流是用涉及至少两个账户的交易来表示的。当您从您的银行下载CSV时,CSV中的每一行都表示输入或发送的资金。这只是交易的一个环节(贷方或借方)。由我们来提供另一条腿。

这种行为被称为“平衡”。

例如,假设上一步的输出是以下事务:

2021-01-01 * "Landlord" "Thanks for the rent"
    Assets:MyBank:Checking    -1000.00 EUR

此事务处理中的支腿总数尚未等于零。这取决于我们如何平衡它。

平衡涉及到弄清楚交易是关于什么的,并分配给它一个相等的和相反的一条腿。在这种情况下,我们可以看到,这笔交易与我们支付租金有关。所以第二回合应该清楚地包含Expenses:Rent账户。

2021-01-01 * "Landlord" "Thanks for the rent"
    Assets:MyBank:Checking     -1000.00 EUR
    Expenses:Rent               1000.00 EUR

这种平衡过程是我们为所有交易所做的事情,这样就可以将整个分类账标记为平衡。

4.就这样!

基本上就是这样。这三个步骤,在一定的时间间隔内执行,应该确保.beancount数据包含您所有的金融交易,并处于良好的状态。

我更喜欢每个月做这个。所以在每个月的第一个星期天,我准备一杯新鲜的咖啡,下载所有的CSV文件,遍历我的进口商,平衡所有不平衡的交易。

你可能觉得这工作太多了。我不得不承认,我刚开始的时候也有过类似的想法。

根据我的经验,情况正好相反。整个过程从没有超过45分钟就完成了。考虑到我每月这样做一次,时间投资似乎是非常公平的。另外的好处是,通过手工平衡这些交易,我可以很好地了解上个月我的账户中发生了什么。

可视化

到目前为止,我们讨论了如何将数据输入系统。

个人会计软件的真正力量在于从这些数据中向你展示真知灼见。在本节中,我将向您快速介绍我使用最多的两个工具:bean-query还有法瓦。

1. bean-query

bean-query是Beancount附带的命令行实用工具,它允许您对财务数据运行SQL-ish查询。查询语言是特定于Beancount的。但是,如果您熟悉SQL,您就会感到宾至如归。bean-query .

下面是我自己的数据中的一个例子,我想知道过去三年我在公共交通上花了多少钱,按年份分组:

beancount> SELECT \
        year, SUM(number) AS total \
        WHERE account ~ 'Expenses:PublicTransport' AND year >= 2019 \
        GROUP BY year;
year total 
---- ------
2019 672.60
2020 328.02
2021  30.50

产出的第一栏是当年,第二栏是我花在购买公共交通车票上的钱总额。

旁注:我从2016年起就一直在偏远地区工作,但从这些数字中可以很清楚地看出,当COVID封锁对我所在的城镇打击最大时。

2.偏袒

Faa是一个由社区维护的Beancount网络界面。它的核心是一个用于读取.beancount文件,并提供各种可视化功能,您会发现它们很有用。

下面是Fava可以为您生成的一份报告的屏幕截图:

有多个报告内置,例如资产负债表,损益表,文件浏览器(另一个整洁的特点,Beancount,你可以附加文件(例如。(发票)交易),以及更多。

您可以使用时间框架过滤所有数据。

在这个URL上有一个在线演示,如果您想了解它的话:fava.pythonanywhere.com/ .

法瓦和bean-query,我用法瓦最多。我觉得法瓦提供的视觉效果让我对我寻找的几乎所有的金融洞察力都有了很好的感觉。

结语

就这样!恭喜你走了这么远!我希望这篇文章能够让你对这种以隐私为中心的追踪个人财务的方式感兴趣。

如果你对学习更感兴趣,你应该考虑买一本我写的关于这个主题的电子书使用Python跟踪个人财务。在这本电子书中,我将详细解释上面提到的概念,以帮助您使用Python构建您自己的个性化多银行应用程序。或者需要此篇文章的完整代码可以:点这里领取

Beancount和复式会计对刚起步的人来说可能有点混乱。因此,这本电子书是我降低进入门槛的尝试。