Command-line Accounting in Context

Martin Blais, July 2014

http://furius.ca/beancount/doc/motivation

This text provides context and motivation for the usage of double-entry
command-line accounting systems to manage personal finances.

Motivation

What exactly is “Accounting”?

What can it do for me?

Keeping Books

Generating Reports

Custom Scripting

Filing Documents

How the Pieces Fit Together

Why not just use a spreadsheet?

Why not just use a commercial app?

How about Mint.com?

How about Quicken?

How about Quickbooks?

How about GnuCash?

Why build a computer language?

Advantages of Command-Line Bookkeeping

Why not just use an SQL database?

But... I just want to do X?

Why am I so Excited?

Motivation

When I tell people about my command-line accounting hacking activities, I get a variety of reactions.

Sometimes I hear echoes of desperation about their own finances: many people wish they had a better handle and understanding of their finances, they sigh and wish they were better organized. Other times, after I describe my process I get incredulous reactions: “Why do you even bother?” Those are the people who feel that their financial life is so simple that it can be summarized in 5 minutes. These are most often blissfully unaware how many accounts they have and have only an imprecise idea of where they stand. They have at least 20 accounts to their name; it’s only when we go through the detail that they realize that their financial ecosystem is more complex than they thought. Finally, there are those who get really excited about the idea of using a powerful accounting system but who don’t actually understand what it is that I’m talking about. They might think it is a system to support investment portfolios, or something that I use to curate a budget like a stickler. Usually they end up thinking it is too complicated to actually get started with.

This document attempts to explain what command-line bookkeeping is about in concrete terms, what you will get out of doing it, how the various software pieces fit together, and what kinds of results you can expect from this method. The fact is, the double-entry method is a basic technique that everyone should have been taught in high school. And using it for yourself is a simple and powerful process you can use to drive your entire financial life.

What exactly is “Accounting”?

When one talks about “accounting,” they often implicitly refer to one or more of various distinct financial processes:

In this document, I will describe how command-line accounting can provide help and support for these activities.

What can it do for me?

You might legitimately ask: sure, but why bother? We can look at the uses of accounting in terms of the questions it can answer for you:

I’m sure there is a lot more you can think of. Let me know.

Keeping Books

Alright, so here’s the part where I give you the insight of the method. The central and most basic activity that provides support for all the other ones is bookkeeping. A most important and fundamental realization is that this relatively simple act—that of copying all of the financial transactions into a single integrated system—allows you to produce reports that solve all of the other problems. You are building a corpus of data, a list of dated transaction objects that each represents movements of money between some of the accounts that you own. This data provides a full timeline of your financial activity.

All you have to do is enter each transaction while respecting a simple constraint, that of the double-entry method, which is this:

Each time an amount is posted to an account, it must have a corresponding inverse amount posted to some other account(s), and the sum of these amounts must be zero.

That’s it. This is the essence of the method, and an ensemble of transactions that respects this constraint acquires nice properties which are discussed in detail in some of my other documents. In order to generate sensible reports, all accounts are further labeled with one of four categories: Assets, Liabilities, Income and Expenses. A fifth category, Equity, exists only to summarize the history of all previous income and expense transactions.

Command-line accounting systems are just simplistic computer languages for conveniently entering, reading and processing this transaction data, and ensure that the constraint of the double-entry method is respected. They’re simple counting systems, that can add any kind of “thing” in dedicated counters (“accounts”). They’re basically calculators with multiple buckets. Beancount and Ledger may differ slightly in their syntax and on some of their semantics, but the general principle is the same, and the simplifying assumptions are very similar.

Here is a concrete example of what a transaction looks like, just so you can get a feeling for it. In a text file—which is the input to a command-line accounting system—something like the following is written and expresses a credit card transaction:

2014-05-23 * "CAFE MOGADOR  NEW YO" "Dinner with Caroline"
  Liabilities:US:BofA:CreditCard    -98.32 USD
  Expenses:Restaurant

This is an example transaction with two “postings,” or “legs.” The “Expenses:Restaurant” line is an account, not a category, though accounts often act like categories (there is no distinction between these two concepts). The amount on the expenses leg is left unspecified, and this is a convenience allowed by the input language. The software determines its amount automatically with the remainder of the balance which in this case will be 98.32 USD, so that -98.32 USD + 98.32 USD = 0 (remember that the sum of all postings must balance to zero—this is enforced by the language).

Most financial institutions provide some way for you to download a summary of account activity in some format or other. Much of the details of your transactions are automatically pulled in from such a downloaded file, using some custom script you write that converts it into the above syntax:

The syntax gets a little bit more complicated, for example it allows you to represent stock purchases and sales, tracking the cost basis of your assets, and there are many other types of conveniences, like being able to define and count any kind of “thing” in an account (e.g., “vacation hours accumulated”), but this example captures the essence of what I do. I replicate all the transactions from all of the accounts that I own in this way, for the most part in an automated fashion. I spend about 1-2 hours every couple of weeks to update this input file, and only for the most used accounts (credit card and checking accounts). Other accounts I’ll update every couple of months, or when I need to generate some reports. Because I have a solid understanding of my finances, this is not a burden anymore… it has become fun.

What you obtain is a full history, a complete timeline of all the financial transactions from all the accounts over time, often connected together, your financial life, in a single text file.

Generating Reports

So what’s the point of manicuring this file? I have code that reads it, parses it, and that can serve various views and aggregations of it on a local web server running on my machine, or produce custom reports from this stream of data. The most useful views are undeniably the balance sheet and income statement, but there are others:

You basically end up managing your personal finances like a company would… but it’s very easy because you’re using a simple and cleverly designed computer language that makes a lot of simplifications (doing away with the concepts of “credit and debits” for example), reducing the process to its essential minimum.

Custom Scripting

The applications are endless. I have all sorts of wild ideas for generating reports for custom projects. These are useful and fun experiments, “challenges” as I call them. Some examples:

The beauty of it is that once you have the corpus of data, which is relatively easy to create if you maintain it incrementally, you can do all sorts of fun things by writing a little bit of Python code. I built Beancount to be able to do that in two ways:

  1. By providing a “plugins” system that allows you to filter a parsed set of transactions. This makes it possible for you to hack the syntax of Beancount and prototype new conveniences in data entry. Plugins provided by default provide extended features just by filtering and transforming the list of parsed transactions. And it’s simple: all you have to do is implement a callback function with a particular signature and add a line to your input file.

  2. By writing scripts. You can parse and obtain the contents of a ledger with very little code. In Python, this looks no more complicated than this:

    import beancount.loader

    entries, errors, options = beancount.loader.load_file(‘myfile.ledger’)
    for entry in entries:

Voila. You’re on your way to spitting out whatever output you want. You have access to all the libraries in the Python world, and my code is mostly functional, heavily documented and thoroughly unit-tested. You should be able to find your way easily. Moreover, if you’re uncertain about using this system, you could just use it to begin entering your data and later write a script that converts it into something else.

Filing Documents

If you have defined accounts for each of your real-world accounts, you have also created a natural method for organizing your statements and other paper documents. As we are communicating more and more by email with our accountants and institutions, it is becoming increasingly common to scan letters to PDFs and have those available as computer files. All the banks have now gone paperless, and you can download these statements if you care (I tend to do this once at the end of the year, for preservation, just in case). It’s nice to be able to organize these nicely and retrieve those documents easily.

What I do is keep a directory hierarchy mirroring the account names that I’ve defined, something that looks like this:

.../documents/
              Assets/
                     US/
                        TDBank/
                               Checking/
                                        2014-04-08.statement.march.pdf
                                        2014-05-07.statement.april.pdf
                                        … 
              Liabilities/
                          US/
                             Amex/
                                  Platinum/
                                           2014-04-17.March.pdf
                                           2014-04-19.download.ofx
                                           …
              Expenses/
                       Health/
                              Medical/
                                      2014-04-02.anthem.eob-physiotherapy.pdf
                                      …

These example files would correspond to accounts with names Assets:US:TDBank:Checking, Liabilities:US:Amex:Platinum, and Expenses:Health:Medical. I keep this directory under version control. As long as a file name begins with a date, such as “2014-04-02”, Beancount is able to find the files automatically and insert directives that are rendered in its web interface as part of an account’s journal, which you can click on to view the document itself. This allows me to find all my statements in one place, and if I’m searching for a document, it has a well-defined place where I know to find it.

Moreover, the importing software I wrote is able to identify downloaded files and automatically move them into the corresponding account’s directory.

How the Pieces Fit Together

So I’ve described what I do to organize my finances. Here I’ll tell you about the various software pieces and how they fit together:

See the diagram below for a pretty picture that illustrates how these work together.

Why not just use a spreadsheet?

This is indeed a good question, and spreadsheets are incredibly useful for sure. I certainly would not be writing my own software if I could track my finances with a spreadsheet.

The problem is that the intrinsic structure of the double-entry transactional data does not lend itself to a tabular representation. Each transaction has multiple attributes (date, narration, tags), and two or more legs, each of which has an associated amount and possibly a cost. If you put the dates on one axis and the accounts on the other, you would end up with a very sparse and very large table; that would not be very useful, and it would be incredibly difficult to edit. If on the other hand, you had a column dedicated to account names for each row, all of your computations would have to take the account cell into the calculation logic. It would be very difficult to deal with, if not impossible. All matters of data aggregations are performed relative to account names.

Moreover, dealing with the accumulation of units with a cost basis would require difficult gymnastics. I don’t even know how I would proceed forward to do this in a spreadsheet. A core part of command-line accounting systems is the inventory logic that allows you to track a cost basis for every unit held in an account and book reductions of positions against existing lots only. This allows the system to compute capital gains automatically. And this is related to the codes that enforce the constraint that all postings on a transaction balance out to zero.

I believe that the “transaction <-> postings” data representation combined with a sensible method for updating inventories is the essence of this system. The need for these is the justification to create a dedicated method to build this data, such as a computer language. Finally, having our own syntax offers the opportunity to provide other types of useful directives such as balance assertions, open/close dates, and sophisticated filtering of subsets of transactions. You just cannot do what we’re doing in a spreadsheet.

Why not just use a commercial app?

How about Mint.com?

Oftentimes people tell me they’re using Mint.com to track their finances, usually with some amount of specific complaints following close behind. Online services such as Mint provide a subset of the functionality of double-entry accounting. The main focus of these services is the reporting of expenses by category, and the maintenance of a budget. As such, they do a great job at automating the download of your credit card and bank transactions. I think that if you want a low-maintenance option to tracking your finances and you don’t have a problem with the obvious privacy risks, this is a fantastic option: it comes with a web interface, mobile apps, and updating your accounts probably requires clicking some buttons, providing some passwords, and a small amount of manual corrections every couple of weeks.

I have several reservations about using it for myself, however:

In other words, I’m a very sophisticated user and yes, a bit of a control freak. I’m not lying about it. I don’t have any ideological objections about using a commercial service, it is probably not for me. If it’s good enough for you, suit yourself. Despite their beautiful and promising websites, I haven’t heard of anyone being completely satisfied with these services. I hear a fair amount of complaining, some mild satisfaction, but I have yet to meet anyone who raves about it.

How about Quicken?

Quicken is a single-entry system, that is, it replicates the transactions of a remote account locally, and allows you to add a label to each transaction to place it in a category. I believe it also has support for synchronizing investment accounts. This is not enough for me, I want to track all kinds of things, and I want to use the double-entry method, which provides an intrinsic check that I’ve entered my data correctly. Single-entry accounting is just not good enough if you’ve already crossed the bridge of understanding the double-entry method.

How about Quickbooks?

So let’s talk about sophisticated software that is good enough for a company. Why wouldn’t I use that instead? If it’s good enough for small businesses, it should be good enough for me, no? There’s Quickbooks and other ones. Why don’t I use them:

How about GnuCash?

I don’t like UIs; they’re inconvenient. There’s nothing quite like editing a text file if you are a programmer. Moreover, GnuCash does not deal with multiple currencies well. I find bugs in it within the first hour every time I kick the tires on it, which I do every couple of years, out of curiosity. Other programs, such as Skrooge, also take the heavy-handed big UI approach.

Why build a computer language?

A bookkeeping system provides conditions for a solution that involves a simple computer language for many reasons.

Single-entry bookkeeping is largely insufficient if you're trying to track everything holistically. Existing systems either limit themselves to expense categories with little checking beyond "reconciling" which sometimes involves freezing the past. If you're not doing the bookkeeping for a company, sometimes just changing the past and fixing the mistakes where they occurred makes more sense. More importantly, the single-entry method leaves us wanting for the natural error-checking mechanism involved in the double-entry system.

The problem is also not solvable elegantly by using spreadsheets; the simple data structure that forms the basis of the double-entry system infers either a very sparse spreadsheet with accounts on one dimension and transactions on the other. For real-world usage, this is impractical. Another iteration on this theme would involve inserting the postings with two columns, one with the account and one with the amount, but the varying number of columns and the lookup code makes this inelegant as well. Plus, it's not obvious how you would deal with a large number of currencies.

Programs that provide fancy graphical or web-based user interfaces are inevitably awkward, due to the nature of the problem: each transaction is organized by viewing it through the lens of one account's journal, but any of the accounts present in its postings provide equally valid views. Ideally, what you want, is just to look at the transaction. Organizing them for most convenient input has little to do with the order in which they are to be presented. Using text has a lot of advantages:

Finally, systems that attempt to automate the process of importing all your data from automated sources (e.g., mint.com) have one major shortfall: most often it's not very easy or even possible to add information for accounts that aren't automated. It is my experience that in practice you will have some entries and accounts to track that will not have a nice downloadable file format, or that simply don't have a real-world counterpart. In order to produce a complete view of one's balance sheet, it is important to be able to enter all of an individual's account within a single system. In other words, custom accounts and manually entered transactions do matter a lot.

For all the reasons mentioned above, I feel that a computer language is more appropriate to express this data structure than a heavy piece of software with a customized interface. Being able to easily bring up a text file and quickly type in a few lines of text to add a transaction is great–it's fast and easy. The ledger file provides a naturally open way to express one's data, and can be source-controlled or shared between people as well. Multiple files can be merged together, and scripted manipulations on a source file can be used to reorganize one's data history. Furthermore, a read-only web interface that presents the various reports one expects and allows the user to explore different views on the dataset is sufficient for the purpose of viewing the data.

Advantages of Command-Line Bookkeeping

In summary, there are many advantages to using a command-line accounting system over a commercial package that provides a user-interface:

Why not just use an SQL database?

I don’t like to reinvent the wheel. If this problem could be solved by filling up an SQL database and then making queries on it, that’s exactly what I would do. Creating a language is a large overhead, it needs to be maintained and evolved, it’s not an easy task, but as it turns out, necessary and justified to solve this problem.

The problem is due to a few reasons:

Finally, input would be difficult. By defining a language, we side-step the problem of having to build a custom user interface that would allow us to create the data.

Nevertheless, I really like the idea of working with databases. A script (bean-sql) is provided to convert the contents of a Beancount file to an SQL database; it’s not super elegant to carry out computations on those tables, but it’s provided nonetheless. You should be able to play around with it, even if operations are difficult. I might even pre-compute some of the operation’s outputs to make it easier to run SQL queries.

But... I just want to do X?

Some may infer that what we’re doing must be terribly complicated given that they envision they might want to use such a system only for a single purpose. But the fact is, how many accounts you decide to track is a personal choice. You can choose to track as little as you want in as little detail as you deem sufficient. For example, if all that you’re interested in is investing, then you can keep books on only your investment accounts. If you’re interested in replacing your usage of Mint.com or Quicken, you can simply just replicate the statements for your credit cards and see your corresponding expenses.

The simplicity of having to just replicate the transactions in all your accounts over doing a painful annual “starting from scratch” evaluation of all your assets and expenses for the purpose of looking at your finances will convince you. Looking at your finances with a spreadsheet will require you to at least copy values from your portfolio. Every time you want to generate the report you’ll have to update the values… with my method, you just update each account’s full activity, and you can obtain the complete list holdings as a by-product. It’s easy to bring everything up-to-date if you have a systematic method.

To those I say: try it out, accounting just for the bits that you’re interested in. Once you’ll have a taste of how the double-entry method works and have learned a little bit about the language syntax, you will want to get a fuller picture. You will get sucked in.

Why am I so Excited?

Okay, so I’ve become an accounting nerd. I did not ask for it. Just kind-of happened while I wasn’t looking (I still don’t wear brown socks though). Why is it I can’t stop talking about this stuff?

I used to have a company. It was an umbrella for doing contract work (yes, I originally had bigger aspirations for it, but it ended up being just that. Bleh.) As a company owner in Canada, I had to periodically make five different kinds of tax installments to the Federal and Provincial governments, some every month, some every three months, and then it varied. An accountant was feeding me the “magic numbers” to put in the forms, numbers which I was copying like a monkey, without fully understanding how they were going to get used later on. I had to count separately the various expenses I would incur in relation to my work (for deductions), and those which were only personal —I did not have the enlightened view of getting separate credit cards so I was trying to track personal vs. company expenses from the same accounts. I also had to track transfers between company and personal accounts that would later on get reported as dividends or salary income. I often had multiple pending invoices that would take more than two months to get paid, from different clients. It was a demi-hell. You get the idea. I used to try to track all these things manually, using systems composed of little text files and spreadsheets and doing things very carefully and in a particular way.

The thing is, although I am by nature quite methodical, I would sometimes, just sometimes forget to update one of the files. Things would fall out of sync. When this happened it was incredibly frustrating, I had to spend time digging around various statements and figure out where I had gone wrong. This was time-consuming and unpleasant. And of course, when something you have to do is unpleasant, you tend not to do it so well. I did not have a solid idea of the current state of affairs of my company during the year, I just worked and earned money for it. My accountant would draw a balance sheet once a year after doing taxes in July, and it was always a tiny bit of a surprise. I felt permanently somewhat confused, and frankly annoyed every time I had to deal with “moneythings.” It wasn’t quite a nightmare, but it was definitely making me tired. I felt my life was so much simpler when I just had a job.

But one day… one day… I saw the light: I discovered the double-entry method. I don’t recall exactly how. I think it was on a website, yes… this site: dwmbeancounter.com (it’s a wonderful site). I realized that using a single system, I could account for all of these problems at the same time, and in a way that would impose an inherent error-checking mechanism. I was blown away! I think I printed the whole thing on paper at the time and worked my way through every tutorial. This simple counting trick is what exactly what I was in dire need for.

But all the softwares I tried were either disappointing, broken, or too complicated. So I read up on Ledger. And I got in touch with its author. And then shortly after I started on Beancount1. I’ll admit that going through the effort of designing my own system just to solve my accounting problems is a bit overkill, but I’ve been known to be a little more than extreme about certain things, and I’ve really enjoyed solving this problem. My life is fulfilled when I maintain a good balance of “learning” and “doing,” and this falls squarely in the “doing” domain.

Ever since, I feel so excited about anything related to personal finance. Probably because it makes me so happy to have such a level of awareness about what’s going on with mine. I even sometimes find myself loving spending money in a new way, just from knowing that I’ll have to figure out how to account for it later. I feel so elated by the ability to solve these financial puzzles that I have had bouts of engaging complete weekends in building this software. They are small challenges with a truly practical application and a tangible consequence. Instant gratification. I get a feeling of empowerment. And I wish the same for you.


  1. For a full list of differences, refer to this document