2016-07-18 Ledger – virtual postings aka envelopes

As I mentioned some time ago, I’ve been a ledger user since 2014. Until now, however, I did not really use any of its advanced features. There are a lot of them; the problem is, the manual is not the best one I’ve read. (Don’t get me wrong – it’s not that bad. But while it is a decent manual, it makes a very bad tutorial. Yes, there is a tutorial-like section at the beginning, and it’s nice, it does cover only the very basics.) So I figured out that after almost two and a half years of using Ledger, it’s high time to read the manual again.

It turned out that I found one feature I’m probably going to use: virtual transactions. The idea is that I have a budget for some kinds of expenses (notably what I call “life” expenses, mainly food and hygiene-related things like soap, toilet paper, dish soap etc.). I have to say that I’m pretty conservative here: near the beginning of each month, I go to the ATM and then set aside some cash for each week in physical envelopes. I do not own (well, technically nobody does – AFAIK, formally it is the bank’s property) a credit card (they are evil), and I avoid paying with a debit card (which is only slightly less evil). Also, some time ago I counted all my expenses that are due less often than monthly (like electricity, which is paid for once every two months, or car insurance, which is paid for once a year) and took the monthly average; each month I set aside that amount of money to a separate bank account. That way I don’t have liquidity problems when I have to pay a large invoice once a year.

Still, I figure it would be nice if Ledger helped me with all that stuff. And it can, thanks to the idea of virtual postings. Here’s a simple example.

2016/07/01 * Opening balance
    Assets:Cash                              $100.00
    Assets:Bank                             $1000.00
    Equity:Opening balance

2016/07/01 * Salary
    Assets:Bank                             $2000.00
    Income:Salary
    (Budget:Food)                            $500.00
    (Budget:Books)                           $200.00

2016/07/02 * Lunch
    Expenses:Food                             $20.00
    Assets:Cash
    (Budget:Food)                            -$20.00

(Note that all amounts are completely fictitious!) Here, after the opening balance we record the salary and set aside some money for food and books. An example food purchase follows. We can now launch ledger with the --real option to exclude the budget “accounts”:

ledger -f envelopes-1.ledger --real bal

or say

ledger -f envelopes-1.ledger bal ^Budget

to see the remaining budget for this month.

Be warned that virtual postings do not have to balance out: we manipulate our Budget:Food virtual account, but whenever we increase (after we get our salary) or decrease it (after we spend money on food), there is no corresponding posting of the opposite sign anywhere in the system! This means that ledger bal will not report a balance of 0 USD unless we use the --real option. If your OCD really insists on having everything (including virtual postings) balance out, you can use square brackets instead of parens; Ledger will then complain if balance of any transaction is anything but zero.

Now while this is nice, it certainly violates the DRY principle: in the last posting, for example, we record the fact that we had spent 20 USD on food twice. While the account name is not a huge problem, since Emacs’ Ledger mode has autocompletion anyway (and everyone uses Emacs, right?), what would happen if we got the amount wrong the second time?

Enter automatic transactions. Here’s a better way to accomplish exactly the same set of transactions.

2016/07/01 * Opening balance
    Assets:Cash                              $100.00
    Assets:Bank                             $1000.00
    Equity:Opening balance

= /Salary/
    (Budget:Food)                            $500.00
    (Budget:Books)                           $200.00

= /Food/
    (Budget:Food)                               -1.0

2016/07/01 * Salary
    Assets:Bank                             $2000.00
    Income:Salary

2016/07/02 * Lunch
    Expenses:Food                             $20.00
    Assets:Cash

Here, after the opening balance (we could do it earlier, too, of course), we instruct Ledger to add the two budgeting postings to any transactions whose account name matches Salary (this is in fact a regex), and also add a posting with exactly the opposite value as the amount given for all Food-related transactions. (The unitless value -1.0 is treated as a multiplier. In our case, if a posting’s account name matches Food, Ledger adds a posting with the same amount value but opposite sign to the Budget:Food account.)

OK, that’s it for today. Expect some other Ledger-related posts in the future!

CategoryBlog, CategoryEnglish, CategoryLedger