Intro
For a few months now I've been trying to find a good home-grown solution to budgetting and tracking my finances.
About a year ago I used ledger-cli
for a time which is a fairly nice plain-text double-entry accounting system. It worked pretty well and served its purpose but I was always a bit uncomfortable with some of the ways it worked (for example, the custom syntax and very complex accounting rules).
I also want to move towards a solution which supports the following additional things:
-
git-based storage: So I can use a central storage like Github/Bitbucket that can easily synchronise between devices.
-
separate logic from syntax: Be able to load transactions from
yaml
orjson
, or anything generated from external tooling. -
simplify accounting: Remove concepts of lot-prices, conversion pricing, and a bunch of other things that can be represented in other ways.
-
treat commodities and currencies the same: Currency values like
£100
can be represented as100 £
or100 GBP
.
The implementation would be done as a set of pure-stdlib libraries that can be combined with extensions that provide interactions with other formats, data sources, or analysis.
Core concepts and rules
-
An
amount
is a combination of a mixed-precision decimal combined with acommodity
like£
,$
,GOOG
. -
An
entry
is a negative or positiveamount
combined with an account. It indicates a change in value of that account. -
A
transaction
is a list ofentries
that balance to0
across eachcommodity
. Combined with a precise date/time and metadata such as labels, notes, etc. -
An
account
can contain any number of childaccounts
. The total value of anaccount
is the sum of allamounts
in thataccount
and all childaccounts
. These can be seen as a tree of values. -
An
account
can only be used in anentry
if it has been "defined". The process of defining an account is fairly flexible and allows you to specify some properties, labels, and description.
Data sources
By extracting the core concepts from the data source and presentation, we can easily define a core library from which we can load data.
By treating the data source as just a stream of structured documents, wherein each document represents a transaction, account defintion, or other core type; we get an easily abstracted system which can be extended to cover many different use cases:
- Recursive directory structure containing files of structured documents
- A sqlite database on disk
- A remote database such as Postgresql or Amazon DynamoDB
- A document store like ElasticSearch or Redis
Data presentation
If the core library contains the many concepts that allow access to transactions, accounts, and the sources therein, we can provide an API on top of which various other systems can be built:
- Filtering of transactions and entries by labels, types, etc..
- Analysis of account values over time
- Budgeting and other calculations
- Projections of growth
The API of the core library would be driven by the presentation tools. I'm not going to try and guess at the API at this time, since I'm almost certain I'd get it wrong!
Design goals
Most of my requirements are routed in making this a nice and extensible system without too many edge cases or branch conditions. I'll try and set up an API that makes it easy to built systems on top of this, rather than trying to include all functionality in one place.
For example, the core API doesn't need to know anything about data sources or file reading, or even how to serialise and deserialise the objects. It only needs to support the API that is exposed.