Been scouring the internet looking for a personal finance library written in Go? Having trouble finding one flexible enough to model your budget? You have arrived at a library that aims to give you the building blocks to represent your finances no matter how you look at them.
Whether you're using Go modules or $GOPATH, you can acquire this library by simply running the following command from the root directory of your project:
$ go get github.com/marstr/envelopes
The Balance
type represents an amount of funds
available.
Let's say you're working in Euros, you could initialize a balance of €10,76 the following way:
mySimpleBalance := envelopes.Balance{
"EUR": big.NewRat(1076, 100),
}
You'll notice above that Balance
isn't a scalar type, but rather a dictionary. This is so accounts which hold multiple
types of assets (like brokerage accounts) can have their contents fully represented. For instance, what if you need to
represent the balance of a brokerage account that has 90 shares of T-Mobile (TMUS), and 89.143 shares of Tesla (TSLA)?
myComplexBalance := envelopes.Balance{
"TSLA": big.NewRat(89143, 1000),
"TMUS": big.NewRat(90, 1),
}
When you do arithmetic with balances, each term will be combined with like terms. That is to say, when you Add
or Sub
balances, the "EUR"
component of one
balance will be summed against the other balance's "EUR"
component, etc. Notably, because different stocks and
currencies have different values, greater than and less than operations can't be done directly on instances of Balance
. You'll need to Normalize
them
first.
While not all modern currencies in the world are decimalized, even the exceptions are subdivided only once; by a factor of five. The two exceptions are the Malagasy ariary and the Mauritanian ouguiya). So at the time of writing, this library should work reasonably well for any currency.
The Accounts
type seeks to help answer the question
"Where is my money?" It is a collection of account names to the Balance in each account. Accounts are flat,
and do not contain other accounts. For accounts like bank accounts and brokerage accounts, which hold assets, the
magnitudes should be positive. For accounts like credit cards, which hold liabilities, the intention is to have balances
be negative. In this regard, the sum of the balances of your accounts should be the total of your tracked value. As you
spend money (be that on a credit card, or with a debit card) the total goes down. This is a little simpler than
traditional doubly-entry accounting, which has credits/debits get swapped based on the type of the account.
The Budget
type seeks to help answer the question
"How do I want to spend my money?" Unlike accounts, Budgets can be nested (a budget can live inside another
budget.). Because they can be nested, they have both an immediate balance and a recursive balance, which is the sum of
its balance and all the balances of its children. The system is designed to use both accounts and budgets at the same
time, as we'll discuss in #states.
A State
combines all your account balances with a root
budget. This reinforces the way the fundamental abstraction that is alluded to in the #accounts and
#balances sections above. A state allows you to separate the "where" and the "for what" of you money. The
idea here is that you may want to have more control than "all of my stocks are being saved for a down payment", or
"the money in this savings account is my emergency budget."
A Transaction
captures metadata around a change
in the current State
. It could be associated with a financial institution, or it may just capture funds being
transferred between two budgets. This library was inspired by Git, and borrows a lot its
architecture and ideas. One of the most notable consequences is that instead of using amount of a transaction to figure
out the current state, it uses the current state (and the one immediately proceeding it) to figure out the amount of
the transaction.
Conceptually, each of the models above are immutable. A SHA1 uniquely identifies each one so that it can be stored to disk and referred to later unambiguously. This immutability has not made its way into the code, however. This allows objects to be built up and modified more easily between being committed to disk.
baronial is a command line interface that exposes the concepts enumerated above in a way that is ready to be scripted against, or just interacted with by a person comfortable working in a terminal.
envelopes-azure implements a client for storing
serialized IDer
s in Azure, instead of just using filesystem constructs.
The nerdy gopher is artwork by the amazing Ashley Willis (McNamara), and is based on the gopher drawn by Renée French. It is licensed under the Attribution-NonCommercial-ShareAlike 4.0 International License. You can find this gopher, and many more like it, at: https://github.com/ashleymcnamara/gophers