Accounting With Ledger
My wife and I took our young children on their first family skiing trip this February and it was a complete success. All agree it beats sunshine holidays.
The problem is that paying for this annually will stress our finances. Immediately upon returning home I began to try to calculate whether we will have saved enough by this time next year to go again.
This ultimately led to the conclusion that we will have to create and stick to a budget for the year. We’ve tried this before, with varying success. The main difficulty is keeping track of where we are against the budget for each of the different expenses.
Most of our assets are in a couple of bank accounts. It can be hard to see how much is available for a holiday when there are so many other expenses to factor in.
On top of our joint account, both myself and my wife have our own accounts, credit cards and savings, making it even harder to track spending. There is no single data source for all the money that is coming and going. I won’t even mention the money I put aside for the children’s future which are in different accounts.
I put all the transactions into a spread sheet, sampling the last year of payments and doing some calculations and predictions. It looks like we will be able to afford to go again next winter without eating into savings; but it will be tight. Staying on top of the budget is going to be key.
This took a bit of effort and was frustrating. I don’t like spread sheets. They are flexible and many people find them useful, but are simply not going to work for me. They are just too fussy. What I need is something more programmatic.
I also want to use source control to track changes. Spread sheet files are binary and don’t work that well with version control software such as Git; it is too difficult to see the changes. CSV was an option to get around this, but it would just add extra steps to reformat every time I use them.
Ledger CLI
After looking around on the internet for a while I found Ledger. It is a command line tool that processes a file containing transactions. It is fast and flexible, able to track position against budget and help show how money within a single account can be allocated to different expense buckets.
Before looking at what a transaction looks like I’ll just run through a few of the things you can do with it.
Balances
The simplest action you can do is to get a list of balances that are in each account. The application suggests keeping the top level categories simple and consistent using five basic categories: Assets, Liabilities, Income, Expenses and Equity.
Assets are things we own like money in a bank account. Liabilities are the debts we have such as mortgages and credit cards. These are easy to understand.
Expenses are what we spend money on. The thing to get used to is that expenses have positive balance, because they take money out of our asset buckets. When we add budget accounts these will mirror the expense sub-categories and be balanced against them.
Equity is harder to understand. The money in your accounts has to come from somewhere when you start your ledger. This is a figure that describes your net worth. It can be excluded from reports for now but is required to balance the ledger.
Income should be straightforward to understand. When you earn money it comes as income from the outside world.
Given a file called sample.dat
containing your ledger, a record of all the transactions you have, you can get the balances with this simple command. Note that the balance command can take a list of regular expressions to limit the accounts returned; I am just showing my assets and liabilities with this command.
$ ledger -f sample.dat balance asset liabilities
€ 10,500 Asset:Current
€ -99,000 Liabilities:Mortgage
--------------------
€ -88,500
Register
To see a list of transactions you can use the register command.
$ ledger -f sample.dat register asset
19-Jan-01 Opening Balances Asset:Current € 10,000 € 10,000
19-Jan-24 My bank Asset:Current € -1,000 € 9,000
19-Jan-24 My employer Asset:Current € 1,500 € 10,500
In this notional example, I get paid a salary on the same date that my mortgage payment is taken. Looking at the transactions against my liabilities might look like this:
$ ledger -f sample.dat register Mortgage
19-Jan-01 Opening Balances Liabilities:Mortgage € -100,000 € -100,000
19-Jan-24 My bank Liabilities:Mortgage € 1,000 € -99,000
19-Feb-01 My bank Liabilities:Mortgage € -100 € -99,100
Different Levels
You can add whatever categories you like to your ledger. The semi-colon character splits the category from lower level. In most of the reports, it will automatically sub-total at each level of the account.
For example, if you are managing both your single and joint credit card, as well as a mortgage account, the balances report will look like this when restricted to show liabilities only
$ ledger -f sample.dat balance liabilities
€ -99,903.30 Liabilities
€ -803.30 Credit Card
€ -679.85 Joint
€ -123.45 Personal
€ -99,100.00 Mortgage
--------------------
€ -99,903.30
This shows the total in the liabilities, total in credit cards and line items for each individual category. The total at the bottom is the same as the liabilities line, because we restricted the report to that line.
Budget
After a short period of time tracking your income and expenses, a sample of about three months will suffice, it will be obvious what the major categories are. The next step is to create a budget and then track progress against that budget.
Getting the balance against a particular account category is straightforward. In this example, the monthly budget for food has been set to €400, however, spending has exceeded the budget.
$ ledger -f sample.dat -b 2019-01-01 -e 2019-01-31 --budget balance Food
€ 45.26 Expenses:Food
The above looks at January’s budget only and limits the result to the account we want with the regular expression Food
. Unfortunately for us, a positive amount indicates that we have over spent.
It is possible to look back at the transactions involved by combining the register with the --budget
option.
$ ledger -f sample.dat -b 2019-01-01 -e 2019-01-31 --budget register Food
19-Jan-01 Budget transaction Expenses:Food € -400.00 € -400.00
19-Jan-05 Grocery Store Expenses:Food € 99.78 € -300.22
19-Jan-12 Grocery Store Expenses:Food € 82.38 € -217.84
19-Jan-19 Grocery Store Expenses:Food € 105.79 € -112.05
19-Jan-25 Grocery Store Expenses:Food € 157.31 € 45.26
Here we can see the initial allocation of €400 is gradually reduced in each of four weekly spends resulting in going over budget. Now that we can see the overspend, we can take action the next time we are in the shops.
There is also a specific budget command that can show the position against each category. I’ve added a travel expense which was not fully used in January to this report to demonstrate:
$ ledger -f sample/sample.dat -b "2019-01-01" -e "2019-01-31" budget Expenses
€ 483.76 € 440.00 € 43.76 110% Expenses
€ 445.26 € 400.00 € 45.26 111% Food
€ 38.50 € 40.00 € -1.50 96% Travel
------------ ------------ ------------ -----
€ 483.76 € 440.00 € 43.76 110%
Entering Data
Ledger uses double entry accounting, which states that a transaction must take something from one account and put it into another. You cannot have money, or any other commodity, simply appear or dissappear. It has to come from or go to somewhere. Every transaction balances to zero.
Each transaction in your ledger will contain at least the following:
- a date
- a payee
- an account where the money (or the commodity) is added
- an account where it comes from
- an amount
- a currency or commodity marker
Budgets can be added with these elements:
- a frequency
- optional start and end dates
- the account it applies to
- the amount
Getting Started
Getting up and running is easy. Open a text editor and start by entering the opening balance transaction. Pick a date that you want to start on. I began mine close the start of the year, so I back-dated it to January and loaded the transactions from my various accounts.
If that seems overwhelming, just start from today and start tracking your expenses. Taking the example that I’ve used above the opening balances would look like this:
2019-01-01 * Opening Balances
Asset:Current € 10,000
Liabilities:Mortgage €-100,000
Liabilities:Credit Card:Personal €-123.45
Liabilities:Credit Card:Joint €-679.85
Equity:Opening Balance
The trick with the above is that the record has to balance. It does this by drawing on the mysterious Equity category. This represents your net worth and is being accessed to create money in each of the accounts.
To reiterate, all transactions must balance. Leave one line without with an amount and ledger will figure out what the balancing figure is for that line. In the example above Equity:Opening Balance will be given the amount 90,803.30 as a positive amount to net against the sum of the other entries.
Running the balance report for just the first two days of the year (use -b
for begin date and -e
for end date) shows this in action:
$ ledger -f sample/sample.dat -b "2019-01-01" -e "2019-01-02" balance
€ 10,000.00 Asset:Current
€ 90,803.30 Equity:Opening Balance
€ -100,803.30 Liabilities
€ -803.30 Credit Card
€ -679.85 Joint
€ -123.45 Personal
€ -100,000.00 Mortgage
--------------------
0
When everything is summed together the amount is zero.
Setting a Budget
We need to add a few lines to the ledger to represent how much of a budget we want to set aside for each Expense. Usually budgets have a period, for example monthly or weekly, and can have stop and start dates so that they can show up in the month they are intended for or stop, for example after you cancel a subscription.
Setting up a budget for travel and food, at a monthly rate can be done as follows:
~ Monthly
Expenses:Food € 400.00
Expenses:Travel € 40.00
Assets
As with any kind of entry in the budget, the transaction must balance, so the Assets line states that this is where the money should be budgeted from.
Adding a Transaction
Enter each transaction like this
2019-01-05 * Grocery Store
Expenses:Food € 99.78
Liabilities:Credit Card
The balance on the Food account will go up while the Credit Card account goes down. If you were to run a budget report now, it would show that we are still within the €400.00 limit for the month.
$ ledger -f sample/sample.dat -b "2019-01-01" -e "2019-01-06" budget Food
€ 99.78 € 400.00 € -300.22 25% Expenses:Food
And that’s basically it. Keep track of your transactions, taking into account cash, debit and credit cards, and see how you are doing against your expected budget.
It may take time to get things right, but in the end you will be able to better predict how much you have to spend on things.
Too Many Accounts
It does not take long to realise that there are a vast number of account categories that you won’t think of at first, places that money sits or things that it is spent on, perhaps irregularly, that you didn’t think of initially.
For example, I host this blog site on Digital Ocean and to pay for it I top up my account every few months with the fees taken monthly.
That means my Digital Ocean balance could appear in the ledger as an Asset account from which monthly transactions are taken. Only when I came across the transaction to put money into the account did I remember that this classification was perhaps necessary.
I don’t have to go to this level of detail; instead I could simply say that the expense is quarterly, matching the cadence of when I top up the account, rather than monthly, requiring me to show each payment in the ledger. The choice is yours on how closely to model your accounts, and how much effort you want to put into the ledger’s maintenance.
Here are some other categories that might be useful.
Paying for Tickets
Something that anyone that goes to sporting or concert events on a regular basis will be used to is buying tickets for a group. Hopefully you will get the money back, but it might not be for a while. How can you track this?
When you purchase on behalf of someone else, they effectively owe you money. You can treat this as an Asset from which you will draw money on in the future. For example, in the transaction below, I will purchase four tickets for a concert, two for myself, and one each for two friends.
Each friend will owe me back the individual ticket amount. My credit card will have to take the full amount. My expenses will be increased by the price of my two tickets. Since I am taking my wife, let’s call this notional event Date Night. In this example each ticket costs €50.
2019-03-01 * Concert Ticket Seller
Expenses:Date Night € 100.00
Assets:Reimbursements:John € 50.00
Assets:Reimbursements:Mary € 50.00
Liabilities:Credit Card:Joint
The above transaction increases the amounts in each of the Expense and Asset accounts and the balancing amount will be € -200.00 in the joint credit card account.
Ultimately Mary and John can pay me back. Perhaps John does so immediately by transferring money to my bank account. This can be represented as follows:
2019-03-04 * John
Assets:Current € 50.00
Assets:Reimbursements:John
This will reduce the amount of the reimbursement to zero so that it no longer shows up on the balance report
$ ledger -f sample/sample.dat balance Reimbursements
€ 50.00 Assets:Reimbursements:Mary
If someone else has purchased on our behalf we can create a Liabilities:Owing account which will help us keep track of what is effectively a short term loan.
Cash Accounts
It can be difficult to keep track of cash spending; you tend to withdraw from the ATM and make any number of payments with cash. Keeping track of all the incidentals can be difficult and may make keeping a ledger seem like a chore.
A compromise approach might be to simply track the big transactions, such as if you paid for the weekly shopping with cash. By asking for and keeping receipts, they can be entered weekly of monthly onto your ledger.
Withdrawing the cash from a bank account and then paying for the shopping with cash can be recorded with:
2019-02-02 * ATM Withdrawal
Asset:Current € -200.00
Expenses:Cash
2019-02-02 * Grocery Store
Expenses:Food € 97.58
Expenses:Cash
The above will leave a balance in the Expenses:Cash account that may not be all that accurate if every single transaction is not captured. Treat it as if it is an expense and even place a budget around it so that you can keep control.
Currencies and Commodities
I won’t go into too much detail about this topic, but it worth noting that ledger can easily track money and amounts in different currencies. It recognises the currency symbols but will also work with text designators.
This allows you to enter commodities such as a number of units in a fund or an amount of shares held. For example, adding the purchase of €1,000 of stock ABC that buys 10 units can be represented like this.
2019-02-15 * Stockbroker
Assets:Current € -1000.00
Assets:Stock 10 ABC
Conclusion
I’ve only scratched the surface in this post of what is possible with ledger. There are lots more subtleties and tricks that can make tracking where you money is going a simple process. The main point is that it is fast, it can process thousands of transactions in milliseconds.
It is easy to get up and running. Simply tracking what you spend is an end in itself; you start questioning whether you really need the thing you are buying.
When entering a subscription in the ledger, such as a mobile phone or streaming service, it will serve to remind you to regularly review whether it is an expense that should be continued with.
If you need to follow a budget to reach those savings goals or to avoid going too far into debt, try out ledger. After a little time to set things up and decide on some budgets, you can keep track of your finances with just a few minutes of upkeep each day.