If you are used to paying everything by card you will surely have less difficulty in finding the answer to the title question. By now almost all banks allow you to automatically categorize your expenses and have a monthly statement. But do they allow you to customize the process? Can you change the category of an expense? Can you add new categories? Can you have categories and subcategories? If you use multiple banks how do you merge the data that comes from the various apps? The goal of this post is to answer all of these questions through the use of Ledger.
What is Ledger
Ledger is a double-entry accounting tool designed to be used through the command line. Lots of big words, but I assure you it’s all simpler than it sounds.
Accounting tool
Surely you already understand what accounting is, but why keep it, you’re not a business. True, you’re not a company, but managing your money is getting more complicated every day. The main reason for this increase in complexity is the number of accounts we use; we have the current account where we receive our salary, then there is a deposit account, we have an account we use for travel, Satispay to exchange money with friends. And that’s not all, many also have an investment account, others have wallets for cryptocurrencies, some have money on their PayPal account, some on Amazon and so on. We use more services than before and every service has its reason, but keeping track of our financial situation is more complicated, so we have to approach the problem with the right tools.
Double-entry bookkeeping
Double-entry bookkeeping is an accounting method first used by Florentine merchants in the 14th century. The idea behind the method is to always record a transaction on at least two accounts. This means that if an account increases by 10€, another account must necessarily decrease by 10€, because it is not possible to create money from nothing. At first it may seem a bit counter intuitive, but if it has been used for six hundred years there will be a reason.
used through the command line
I’m not going to lie to you, this post makes extensive use of the terminal and you probably don’t like the terminal. Before you close the page let me just tell you that Ledger started a movement called Plain Text Accounting and there are many software that follow to this movement. Some of these also come with a GUI so you can apply many of the concepts discussed in this post to other tools as well.
Plain Text Accounting
The idea behind plain text accounting is to keep track of accounting through the use of plain text files. What is a plain text file? Simple it is a text file, nothing more, nothing less. No, not like Word, where there are fonts, sizes, bold, color, etc. A plain text file contains only text, nothing else.
Does that sound too limited? I assure you it is not. With plain text files you can do so much with them, like in this case keeping track of accounting. They also have two great advantages:
- A plain text file can be opened even in a hundred years.
- A plain text file can also be understood by humans.
Within a Ledger file, often called a journal, there are mostly transactions that alter the balance of various accounts. A transaction consists of a header line, which contains the date and payee/cause of payment, and n lines each representing a change in an account. Here is an example of a transaction in Ledger.
2021-01-17 Airbnb
expenses:travel:accommodation 550 EUR
assets:current:revolut -550 EUR
How does it read? On January 17th, I made a payment to Airbnb. The rental cost was categorized as a travel expense, specifically falling under the accommodation subcategory. The 550€ payment was made through my Revolut account.
Simple no? Maybe too simple, let’s try something more complex. To prepare for the trip, the next day, I bought on Amazon a travel pillow that cost 10€. Also I saw that there is a new kindle model on offer (100€), so I bought that too. Again I want to pay with my Revolut card, but I still have 25€ on my Amazon account, so the transaction on ledger will look like:
2021-01-18 Amazon
expenses:travel:accessories 10 EUR ; cuscino da viaggio
expenses:entertainment:books 100 EUR ; kindle
assets:current:amazon -25 EUR
assets:current:revolut
Ok here there seems to be something strange. First of all, you didn’t specify how much money was withdrawn from the Revolut account, but don’t worry this is not an error. Since Ledger uses double-entry bookkeeping, the sum of all changes in the various accounts must always be zero. In our case we have 10 + 100 - 25 so to bring it to zero we need -85. So Ledger is smart enough to understand that 85€ has been taken from Revolut1.
The other peculiarity of the previous transaction is the presence of the symbol ;
.
A semicolon, in Ledger, is used for notes.
If the note is put on a line with a movement (as in the example) then the note refers to the single movement.
Whereas when the note is on a line of its own then this refers to the entire transaction.
Account Structure
After looking at the previous examples, you should already understand the way Ledger manages accounts, that is, in a hierarchical way.
Each category (e.g. expenses
) can have multiple subcategories (e.g. travel
) which in turn can have other subcategories (e.g. accessories
) and so on.
Each level is separated by the colon (:
) and there can be infinite sub-levels.
The name of the accounts is totally free and is decided by the user. Although I haven’t used them, the name of an account can also contain spaces and capital letters.
Ledger is democratic with accounts and treats them all the same. This means that the accounts with our expenses in Ledger’s eyes are totally equal to the ones where our belongings are. In fact, I’ll tell you more, Ledger doesn’t even know that the “expenses” account contains our expenses. We are the ones who give semantics to the various accounts, that is why it is important to use meaningful names.
I repeat, you are totally free to use any name you want for your accounts, but I suggest you introduce some rules to manage everything better. In particular, I suggest you to limit to five the number of main accounts and to use the ones listed below.
assets
: these are the accounts where you store your money.expenses
: accounts where your money goes.income
: are the accounts where your money comes from.liabilities
: these are the accounts where the money you owe to others resides.equity
: this is a bit complicated. From a theoretical point of view, these accounts show the real value of your assets. From a practical point of view, these accounts are used as jolly accounts. However, don’t worry, this account is used very little.
Record your income
Before we can see how Ledger works, I need to explain how to record your income. First we need to take a snapshot of the initial situation. So if we start keeping track of our accounts as of January 1, 2022 we need to tell Ledger what our financial situation is.
Assuming we have the following financial situation on January 1:
- Revolut account: €243
- Illimity current account: 729€
- Amazon account balance: 25€
- cash: 37€
we will have the following Ledger transaction:
2022-01-01 Opening Balances
assets:current:revolut 243 EUR
assets:current:amazon 25 EUR
assets:current:illimity 729 EUR
assets:current:cash 37 EUR
To verify that the file is correct and understandable to Ledger we use the command stats
that in addition to interpreting the file with the transactions provides us with various statistics.
In my case the complete command is ledger --file ledger.journal stats
because I have inserted the transaction in the file ledger.journal
.
An error occurred?
Don’t worry, it’s not your fault.
The truth is that I am an asshole and I made you make a mistake on purpose.
Looking at the transaction again, you can see that we violated Ledger’s first rule: The sum of all transactions must be zero.
Ledger wants to know where this 1034€ comes from.
It’s money that is already in our account, so it’s not correct to put it as income, so the best solution is to use the jolly category and then the equity
account.
Therefore our opening transaction will be:
2022-01-01 Opening Balances
assets:current:revolut 243 EUR
assets:current:amazon 25 EUR
assets:current:illimity 729 EUR
assets:current:cash 37 EUR
equity:open -1034 EUR
Now if you try to run again the command ledger --file ledger.journal stats
you should not see any errors, but some statistics on your journal.
Ok the fifteenth of the month has arrived and we receive our paycheck, how to mark this income? Just enter a new transaction in the journal where we add 1500€ (our salary) to the Illimity account (the account where we get our salary). Where do we get this 1500€ from? Simple from our employer’s account.
2022-01-15 Employer
assets:current:illimity 1500 EUR
income:salary -1500 EUR
Balance & Register
Now that it should be clear how to register movements between our accounts it’s time to see how Ledger works and in particular the two most used commands; balance and register. I recommend that you run the commands I’ll show you step by step, and to get the same results as me, you need to use this journal.
Balance
The command balance
allows you to view the current balance of all accounts.
Running from terminal the command ledger --file ledger.journal balance
gives the following output:
1607 EUR assets:current
37 EUR cash
1509 EUR illimity
61 EUR revolut
-1034 EUR equity:open
927 EUR expenses
100 EUR entertainment:books
47 EUR food:restaurants
220 EUR groceries
560 EUR travel
10 EUR accessories
550 EUR accommodation
-1500 EUR income:salary
--------------------
0
From this output you can see the hierarchical organization of accounts in Ledger.
If you have problems with this representation, you can use the flag --flat
.
In other cases you don’t want to know the balance of all accounts, so Ledger allows you to select only the accounts which match a regular expression.
In case you are interested in knowing the position of all the money you have and display the various accounts in a flat way you can use the command ledger --file ledger.journal balance assets --flat
which generates the following output:
37 EUR assets:current:cash
1509 EUR assets:current:illimity
61 EUR assets:current:revolut
--------------------
1607 EUR
Register
Another fundamental command of Ledger is register
whose task is to simulate a cash register.
This command allows you to see the effect on accounts of every single movement.
Again, the report can be reduced to only certain accounts.
To see all transactions in groceries we can use the command ledger --file ledger.journal register groceries
which has the following output:
2022-01-10 Esselunga expenses:groceries 137 EUR 137 EUR
2022-01-23 Esselunga expenses:groceries 83 EUR 220 EUR
In addition to the date and account of the transaction in the output there are two columns, the first shows the amount of the transaction, while the second keeps track of the sum of all transactions.
How much did I spend this month?
After this long introduction we can finally answer the title question.
The best tool, provided by Ledger, to know our expenses is the register
command.
In particular, if we are interested only in the expenses of the current month, we must also use the flag --period
which allows us to select only a specific time interval.
So to know all the expenses of this month we use the command: ledger --file ledger.journal register expenses --period 'this month'
2.
2022-01-10 Esselunga expenses:groceries 137 EUR 137 EUR
2022-01-17 Airbnb expenses:travel:accommodation 550 EUR 687 EUR
2022-01-18 Amazon expenses:travel:accessories 10 EUR 697 EUR
2022-01-18 Amazon expenses:entertainment:books 100 EUR 797 EUR
2022-01-23 Esselunga expenses:groceries 83 EUR 880 EUR
2022-01-29 Pub expenses:food:restaurants 47 EUR 927 EUR
In the output we have the list of all expenses for the month. In the first column there is the date of the expense and the commercial establishment where it was made. In the second column is reported the category and in the third the amount. The last column shows the current sum, so to know the total expenses for January we must look at the last column of the last row. So in this example in January we have spent 927€.
Not interested in all expenses, but only in travel expenses?
Nothing simpler, just use the following command: ledger --file ledger.journal register expenses:travel --period 'this month'
2022-01-17 Airbnb expenses:travel:accommodation 550 EUR 550 EUR
2022-01-18 Amazon expenses:travel:accessories 10 EUR 560 EUR
In other cases we are not interested in individual transactions, but in the total for each category.
In these cases we can use the flag --subtotal
obtaining the following command: ledger --file ledger.journal register expenses --period 'this month' --subtotal
.
2022-01-10 - 2022-01-29 expenses:entertainment:books 100 EUR 100 EUR
expenses:food:restaurants 47 EUR 147 EUR
expenses:groceries 220 EUR 367 EUR
expenses:travel:accessories 10 EUR 377 EUR
expenses:travel:accommodation 550 EUR 927 EUR
In this case the most important column is the third in which it comes brought back the total expense for the category. So in this example we spent 100€ in books, 47€ in restaurants and so on.
We arrived at the end of this first post on Ledger. Probably this tool will seem overkilled to you for the purpose we set at the beginning of the post and in part you are right. Ledger is a very powerful and flexible tool that gives its best only when you get the hang of it. In the next posts of the series there will be a way to cover different topics and expand on those already mentioned. Stay tuned!
This post contains several referral links.
Of course it is possible to leave only one value blank, so by leaving two blank Ledger is no longer able to determine the missing ones. ↩︎
Ledger allows us to express time intervals through various expressions. Relative expressions like ‘this month’ are convenient because they allow us to use the same command that automatically fits the current situation, but there are cases where we need to identify the reference period more directly. For example if you are reading this article in February you won’t get any result because for Ledger ‘this month’ is equivalent to February. In these cases you can use the name of the month (
--period 'jan'
) or define the interval explicitly (--period 'from 2022-01-01 to 2022-01-31'
). ↩︎