UP | HOME

The beans manual

Table of Contents

1 About beans

beans is a plain text accounting tool in the tradition of ledger, hledger and beancount.

1.1 Project goals

1.1.1 Built-in file importers

The greatest pain of plain text accounting is to import financial statements from financial service providers such as banks and credit cards. beans strives to include importers for known formats.

1.1.2 Rule-based categorization

beans provides a domain-specific language (DSL) to specify rules for assigning accounts based on transaction features such as amount, description or dates.

1.1.3 Proper multi-commodity and valuation

beans aims to make it simple to do both at-cost and at-market valuations of your assets, while maintaining correctness of the balance. Instead of converting aggregated account data and adding valuation as an afterthought, beans applies valuation directly at the transaction level. For example, if you choose to display a balance at market prices, beans will transparently insert valuation transactions to reflect gains and losses due to price changes.

1.1.4 Simple and elegant implementation

beans is written in Haskell, an excellent language for concise and beautiful code. Also, while beans adopts concepts from other tools, compatiblity is not an objective.

2 Getting beans

2.1 Obtaining the source

beans' source code can be found on github. For the moment, you have to build from source.

Make sure you have git installed and run:

git clone https://github.com/sboehler/beans.git

2.2 Installing beans

2.2.1 Using Stack

stack is probably the easiest option on most platforms to get started quickly. First, follow the instructions here to install stack for your platform. Then:

cd beans
stack install

This will install the beans binary in $HOME/.local/bin/beans. Add this directory to your path and you're good to go:

export PATH=~/.local/bin:$PATH

Please file a bug if you encounter problems using stack.

2.2.2 Using Nix

Make sure you have the nix package manager installed for your platform. Then:

cd beans
nix-build --attr beans release.nix

The beans binary will be made available locally in ./result/bin/beans and can be run from there.

2.2.3 Using Cabal

If you intend to develop beans or run the test suite. Make sure cabal and hpack are installed:

cd beans
cabal new-build

The beans binary will be made available in ./dist/build/beans/beans and can be run from there.

3 Working with beans

beans is a command line tool and has some self-documenting features. Run the following command to get started:

beans --help
beans

Usage: beans COMMAND
  A plain text accounting tool

Available options:
  -h,--help                Show this help text

Available commands:
  balance                  Print a generic balance
  incomeStatement          Print a formatted income statement
  balanceSheet             Print a formatted balance sheet
  import                   Import data
  journal                  Show the changes in one or several accounts over a
                           period

Use beans <command> --help to get further help on available options.

3.1 Importing data

beans offers assistance with importing bank account statements, the most tiring process in plain text accounting.

3.1.1 Importers

In a first step, bank account statements need to be parsed. The following is what a statement from my bank might look like.

Datum von:;2017-05-23
Buchungsart:;Alle Buchungen
Konto:;CHXXXXXXXXXXXXXXXXXXX
Währung:;CHF
Buchungsdatum;Avisierungstext;Gutschrift;Lastschrift;Valuta;Saldo
2017-06-01;"Acme Corp";;-135.00;2017-06-01;
2017-05-31;"FOOBAR COMMUNICATIONS";;-52.60;2017-05-31;
2017-05-29;"Transfer 01-45-06 Bigbank";;-1040.00;2017-05-29;36096.54
2017-05-26;"Cleaning Service";;-300.00;2017-05-24;37136.54
2017-05-26;"Supermarket Fine Foods";;-115.20;2017-05-26;
2017-05-26;"Bank Nextgen ";;-250.00;2017-05-26;
2017-05-26;"Tire Car Sales";;-95.85;2017-05-26;

Disclaimer:
Dies ist kein durch PostFinance AG erstelltes Dokument. PostFinance AG ist nicht verantwortlich für den Inhalt.

This is a kind of a CSV format, but then not really, so this is difficult to parse with a general parser. beans strives to have built-in support for as many file formats as possible. Currently, the following parsers are available:

  • us.interactivebrokers
  • ch.postfinance
  • ch.supercardplus

3.1.2 Assigning accounts

The second step is equally tiring, even when transactions are autogenerated: assigning accounts to transactions. However, it is conceptually simple to automate. beans offers a very simple domain-specific language (DSL) to write rules for importing:

description =~ "Acme" -> Expenses:Groceries
description =~ "FOOBAR" -> Expenses:MobilePhone
description =~ "(Bigbank|Nextgen)" -> Assets:Investments
description =~ "Clean.*" -> Expenses:Cleaning
description =~ "Supermarket" -> Expenses:Groceries
description =~ "Car" && abs amount < 1000 -> Expenses:Car
description =~ "Zapote" && abs amount == 21.80 -> Assets:Car
date == 2018-06-14 -> Assets:Something
True -> Expenses:ToBeEditedManually

Rules are meant to be reusable across different sources of information. Various standardized variables from the importer's output are available, as well as operators to process them:

  • description, amount, type, date, and importer
  • boolean operators !, && and ||
  • arithmetic operators + and -
  • comparison operators ==, !=, <, <=, >=, and >
  • the abs function
  • a regex test for perl-compatible regexes: =~

Rules return, when matched, the account specified on the right hand side of the arrow (->). The rules file can be concluded with a catch-all, which can yield a TODO account for later manual editing. Rules files are independent of importers, thus one file can be used for various sources.

3.1.3 Importing data

Having both a parser and a rules file, converting the bank account statement to transactions is a simple command:

beans import -i ch.postfinance -c examples/example.rules -a Assets:Checking examples/postfinance.csv

import outputs a simple list of transactions to stdout, in a format parseable by beans and with correct accounts assigned. It is up to the user to pipe them into a journal or a temporary file for further editing.

2017-05-26 * "Bank Nextgen "
  Assets:Checking -250.00 CHF
  Assets:Investments 250.00 CHF

2017-05-26 * "Cleaning Service"
  Assets:Checking -300.00 CHF
  Expenses:Cleaning 300.00 CHF

2017-05-26 * "Supermarket Fine Foods"
  Assets:Checking -115.20 CHF
  Expenses:Groceries 115.20 CHF

2017-05-26 * "Tire Car Sales"
  Assets:Checking -95.85 CHF
  Expenses:Car 95.85 CHF

2017-05-29 * "Transfer 01-45-06 Bigbank"
  Assets:Checking -1040.00 CHF
  Assets:Investments 1040.00 CHF

2017-05-31 * "FOOBAR COMMUNICATIONS"
  Assets:Checking -52.60 CHF
  Expenses:MobilePhone 52.60 CHF

2017-06-01 * "Acme Corp"
  Assets:Checking -135.00 CHF
  Expenses:Groceries 135.00 CHF

The importing functionality of beans can of course also be used if you use another plain-text accounting tool. beancount's syntax is largely compatible with beans.

3.2 Creating a journal

3.2.1 Journal files

Most commands in beans are based on a journal. beans journals uses a format largely similar to beancount:

; -*- mode: Org; eval: (beancount-mode 1); -*-

option "operating_currency" "USD"

** Accounts

2018-01-01 open Equity:Valuation
2018-01-01 open Equity:OpeningBalance
2018-01-01 open Income:Salary USD
2018-01-01 open Expenses:Rent USD
2018-01-01 open Expenses:Groceries USD
2018-01-01 open Expenses:Books USD

2018-01-01 open Assets:Checking USD
2018-01-01 open Assets:Portfolio AAPL
2018-01-01 open Assets:Wallet BTC

** Some Transactions

*** Initial balances

2018-01-01 * "Opening balance"
  Assets:Checking 15000 USD
  Equity:OpeningBalance

2018-01-01 * "Opening balance"
  Assets:Portfolio 0 AAPL
  Equity:OpeningBalance

2018-01-01 * "Opening balance"
  Assets:Wallet 0 BTC
  Equity:OpeningBalance

*** Checking account

2018-01-02 * "Rent January"
  Assets:Checking -2000 USD
  Expenses:Rent

2018-01-10 * "Food"
  Assets:Checking -300 USD
  Expenses:Groceries

2018-01-25 * "Salary January"
  Assets:Checking 4000 USD
  Income:Salary

2018-02-01 * "Rent February"
  Assets:Checking -2000 USD
  Expenses:Rent

2018-01-12 * "Hungry again"
  Assets:Checking -200 USD
  Expenses:Groceries

2018-01-20 * "Something to read"
  Assets:Checking -100 USD
  Expenses:Books


2018-02-25 * "Salary February"
  Assets:Checking 4000 USD
  Income:Salary

2018-03-01 * "Rent March"
  Assets:Checking -2000 USD
  Expenses:Rent

2018-03-02 * "Yet more food"
  Assets:Checking -200 USD
  Expenses:Groceries

2018-03-20 * "More food"
  Assets:Checking -400 USD
  Expenses:Groceries

2018-03-25 * "Salary March"
  Assets:Checking 4000 USD
  Income:Salary

*** Investments

2018-01-10 * "Investing in stock"
  Assets:Portfolio +10 AAPL
  Assets:Checking -1700 USD

2018-01-14 * "I want to be part of this!"
  Assets:Wallet 0.25 BTC
  Assets:Checking -3500 USD

** Prices

2018-01-01 price BTC 13412 USD
2018-02-01 price BTC 9052 USD
2018-03-01 price BTC 10907 USD
2018-04-01 price BTC 6816 USD
2018-05-01 price BTC 9067 USD
2018-06-01 price BTC 7518 USD
2018-07-01 price BTC 6347 USD
2018-08-01 price BTC 7603 USD
2018-09-01 price BTC 7192 USD
2018-10-01 price BTC 6578 USD
2018-11-01 price BTC 6358 USD

2018-01-01 price AAPL 169 USD
2018-02-01 price AAPL 167 USD
2018-03-01 price AAPL 175 USD
2018-04-01 price AAPL 166 USD
2018-05-01 price AAPL 169 USD
2018-06-01 price AAPL 190 USD
2018-07-01 price AAPL 185 USD
2018-08-01 price AAPL 201 USD
2018-09-01 price AAPL 227 USD
2018-10-01 price AAPL 225 USD
2018-11-01 price AAPL 222 USD

I am using Emacs with org-mode to manage my journal in one large file, however there is an include directive as well which allows for splitting a journal in different files.

3.2.2 Conventions

  • Accounts must be opened (and closed, if so desired) explicitly. They can be open for all commodities (default) or restricted to a list of them
  • Account names must start with "Assets", "Liabilities", "Equity", "Expenses" or "Income", depending on their type.
  • Transactions need not be ordered, beans automatically orders them by date.
  • Transactions with only one commodity can have a 'wildcard' booking, which is automatically assigned the total of the other bookings (this is the same as in other plain-text accounting tools)
  • However, transactions with several commodities (e.g. the stock trade in the example above) must not have wildcard bookings. The reason is that beans cannot decide on a useful way to balance different commodities. Depending on whether one wants to convert commodities at cost or at market value, beans will add balancing accounts automatically.
  • Unlike beancount, beans uses the convention that balance directives refer to balances at the end of the given date. This is congruent with standard practices in the financial industry.

3.3 Tracking changes in accounts

beans allows for sophisticated analysis and reconciliation of account balances.

3.3.1 Tracking changes in one account

A simple use case is to reconcile start and ending balances of a specific account:

beans journal -j ./examples/example.bean --filter Assets:Checking
|------------+----------+-----+----------------------------+-----------------------+-----------+------|
| <MIN_DATE> |          |     | Assets:Checking            |                       |           |      |
|------------+----------+-----+----------------------------+-----------------------+-----------+------|
| 2018-01-01 | 15000.00 | USD | Opening balance            | Equity:OpeningBalance | -15000.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-01-02 | -2000.00 | USD | Rent January               | Expenses:Rent         |   2000.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-01-10 |  -300.00 | USD | Food                       | Expenses:Groceries    |    300.00 | USD  |
|            | -1700.00 | USD | Investing in stock         | Assets:Portfolio      |     10.00 | AAPL |
|            |          |     |                            |                       |           |      |
| 2018-01-12 |  -200.00 | USD | Hungry again               | Expenses:Groceries    |    200.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-01-14 | -3500.00 | USD | I want to be part of this! | Assets:Wallet         |      0.25 | BTC  |
|            |          |     |                            |                       |           |      |
| 2018-01-20 |  -100.00 | USD | Something to read          | Expenses:Books        |    100.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-01-25 |  4000.00 | USD | Salary January             | Income:Salary         |  -4000.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-02-01 | -2000.00 | USD | Rent February              | Expenses:Rent         |   2000.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-02-25 |  4000.00 | USD | Salary February            | Income:Salary         |  -4000.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-03-01 | -2000.00 | USD | Rent March                 | Expenses:Rent         |   2000.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-03-02 |  -200.00 | USD | Yet more food              | Expenses:Groceries    |    200.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-03-20 |  -400.00 | USD | More food                  | Expenses:Groceries    |    400.00 | USD  |
|            |          |     |                            |                       |           |      |
| 2018-03-25 |  4000.00 | USD | Salary March               | Income:Salary         |  -4000.00 | USD  |
|            |          |     |                            |                       |           |      |
|------------+----------+-----+----------------------------+-----------------------+-----------+------|
| <MAX_DATE> | 14600.00 | USD | Assets:Checking            |                       |           |      |
|------------+----------+-----+----------------------------+-----------------------+-----------+------|

The table shows starting and ending balances of the selected account, as well as all transactions in between. Columns 2 - 4 show what happened in the selected accounts, columns 5 - 7 show the corresponding counterbookings and the respective amounts and units.

3.3.2 Analyzing a group of accounts

But we are not restricted to selecting one account. The next example shows a combined journal for all Asset accounts:

beans journal -j ./examples/example.bean --filter Assets
|------------+----------+------+----------------------------+-----------------------+-----------+-----|
| <MIN_DATE> |          |      | Assets                     |                       |           |     |
|------------+----------+------+----------------------------+-----------------------+-----------+-----|
| 2018-01-01 | 15000.00 | USD  | Opening balance            | Equity:OpeningBalance | -15000.00 | USD |
|            |     0.00 | AAPL | Opening balance            |                       |           |     |
|            |     0.00 | BTC  | Opening balance            |                       |           |     |
|            |          |      |                            |                       |           |     |
| 2018-01-02 | -2000.00 | USD  | Rent January               | Expenses:Rent         |   2000.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-01-10 |  -300.00 | USD  | Food                       | Expenses:Groceries    |    300.00 | USD |
|            | -1700.00 | USD  | Investing in stock         |                       |           |     |
|            |    10.00 | AAPL |                            |                       |           |     |
|            |          |      |                            |                       |           |     |
| 2018-01-12 |  -200.00 | USD  | Hungry again               | Expenses:Groceries    |    200.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-01-14 | -3500.00 | USD  | I want to be part of this! |                       |           |     |
|            |     0.25 | BTC  |                            |                       |           |     |
|            |          |      |                            |                       |           |     |
| 2018-01-20 |  -100.00 | USD  | Something to read          | Expenses:Books        |    100.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-01-25 |  4000.00 | USD  | Salary January             | Income:Salary         |  -4000.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-02-01 | -2000.00 | USD  | Rent February              | Expenses:Rent         |   2000.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-02-25 |  4000.00 | USD  | Salary February            | Income:Salary         |  -4000.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-03-01 | -2000.00 | USD  | Rent March                 | Expenses:Rent         |   2000.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-03-02 |  -200.00 | USD  | Yet more food              | Expenses:Groceries    |    200.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-03-20 |  -400.00 | USD  | More food                  | Expenses:Groceries    |    400.00 | USD |
|            |          |      |                            |                       |           |     |
| 2018-03-25 |  4000.00 | USD  | Salary March               | Income:Salary         |  -4000.00 | USD |
|            |          |      |                            |                       |           |     |
|------------+----------+------+----------------------------+-----------------------+-----------+-----|
| <MAX_DATE> |    10.00 | AAPL | Assets                     |                       |           |     |
|            |     0.25 | BTC  |                            |                       |           |     |
|            | 14600.00 | USD  |                            |                       |           |     |
|------------+----------+------+----------------------------+-----------------------+-----------+-----|

We now see the ending balances in terms of USD and SomeStock units.

3.3.3 Converting to a reference commodity

However, economically, it is more interesting to see all values converted to USD. So let's do that, using the same syntax as for the balance command:

beans journal -j ./examples/example.bean --filter Assets -m USD
|------------+----------+-----+----------------------------+-----------------------+-----------+-----|
| <MIN_DATE> |          |     | Assets                     |                       |           |     |
|------------+----------+-----+----------------------------+-----------------------+-----------+-----|
| 2018-01-01 | 15000.00 | USD | Opening balance            | Equity:OpeningBalance | -15000.00 | USD |
|            |     0.00 | USD | Opening balance            |                       |           |     |
|            |     0.00 | USD | Opening balance            |                       |           |     |
|            |          |     |                            |                       |           |     |
| 2018-01-02 | -2000.00 | USD | Rent January               | Expenses:Rent         |   2000.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-01-10 |  -300.00 | USD | Food                       | Expenses:Groceries    |    300.00 | USD |
|            | -1700.00 | USD | Investing in stock         | Equity:Valuation      |     10.00 | USD |
|            |  1690.00 | USD |                            |                       |           |     |
|            |          |     |                            |                       |           |     |
| 2018-01-12 |  -200.00 | USD | Hungry again               | Expenses:Groceries    |    200.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-01-14 | -3500.00 | USD | I want to be part of this! | Equity:Valuation      |    147.00 | USD |
|            |  3353.00 | USD |                            |                       |           |     |
|            |          |     |                            |                       |           |     |
| 2018-01-20 |  -100.00 | USD | Something to read          | Expenses:Books        |    100.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-01-25 |  4000.00 | USD | Salary January             | Income:Salary         |  -4000.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-02-01 | -2000.00 | USD | Rent February              | Expenses:Rent         |   2000.00 | USD |
|            |   -20.00 | USD | Valuation AAPL             | Equity:Valuation      |     20.00 | USD |
|            | -1089.94 | USD | Valuation BTC              | Equity:Valuation      |   1089.94 | USD |
|            |          |     |                            |                       |           |     |
| 2018-02-25 |  4000.00 | USD | Salary February            | Income:Salary         |  -4000.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-03-01 | -2000.00 | USD | Rent March                 | Expenses:Rent         |   2000.00 | USD |
|            |    80.10 | USD | Valuation AAPL             | Equity:Valuation      |    -80.10 | USD |
|            |   463.69 | USD | Valuation BTC              | Equity:Valuation      |   -463.69 | USD |
|            |          |     |                            |                       |           |     |
| 2018-03-02 |  -200.00 | USD | Yet more food              | Expenses:Groceries    |    200.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-03-20 |  -400.00 | USD | More food                  | Expenses:Groceries    |    400.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-03-25 |  4000.00 | USD | Salary March               | Income:Salary         |  -4000.00 | USD |
|            |          |     |                            |                       |           |     |
| 2018-04-01 |   -90.10 | USD | Valuation AAPL             | Equity:Valuation      |     90.10 | USD |
|            | -1022.71 | USD | Valuation BTC              | Equity:Valuation      |   1022.71 | USD |
|            |          |     |                            |                       |           |     |
| 2018-05-01 |    30.00 | USD | Valuation AAPL             | Equity:Valuation      |    -30.00 | USD |
|            |   562.71 | USD | Valuation BTC              | Equity:Valuation      |   -562.71 | USD |
|            |          |     |                            |                       |           |     |
| 2018-06-01 |   210.10 | USD | Valuation AAPL             | Equity:Valuation      |   -210.10 | USD |
|            |  -387.20 | USD | Valuation BTC              | Equity:Valuation      |    387.20 | USD |
|            |          |     |                            |                       |           |     |
| 2018-07-01 |   -50.00 | USD | Valuation AAPL             | Equity:Valuation      |     50.00 | USD |
|            |  -292.76 | USD | Valuation BTC              | Equity:Valuation      |    292.76 | USD |
|            |          |     |                            |                       |           |     |
| 2018-08-01 |   160.00 | USD | Valuation AAPL             | Equity:Valuation      |   -160.00 | USD |
|            |   313.91 | USD | Valuation BTC              | Equity:Valuation      |   -313.91 | USD |
|            |          |     |                            |                       |           |     |
| 2018-09-01 |   260.00 | USD | Valuation AAPL             | Equity:Valuation      |   -260.00 | USD |
|            |  -102.66 | USD | Valuation BTC              | Equity:Valuation      |    102.66 | USD |
|            |          |     |                            |                       |           |     |
| 2018-10-01 |   -19.90 | USD | Valuation AAPL             | Equity:Valuation      |     19.90 | USD |
|            |  -153.52 | USD | Valuation BTC              | Equity:Valuation      |    153.52 | USD |
|            |          |     |                            |                       |           |     |
| 2018-11-01 |   -30.40 | USD | Valuation AAPL             | Equity:Valuation      |     30.40 | USD |
|            |   -55.00 | USD | Valuation BTC              | Equity:Valuation      |     55.00 | USD |
|            |          |     |                            |                       |           |     |
|------------+----------+-----+----------------------------+-----------------------+-----------+-----|
| <MAX_DATE> | 18409.32 | USD | Assets                     |                       |           |     |
|------------+----------+-----+----------------------------+-----------------------+-----------+-----|

The journal now not only shows explicit inflows and outflows, but also valuation corrections due to price changes at the specific date they occurred.

As a general rule, use the balance command if you are interested in aggregates over a certain period. Use the journal command and suitable filtering to see the details by date. Together, those commands can answer almost any question about a journal.

3.4 Standard reports

beans has some standard reports which allow for easy creation of a nicely formatted balance sheet or income statement. They share a rich set of filtering options.

3.4.1 Income Statement

Let's start with an income statement. Our journal starts at the beginning of 2018, with the following balance:

beans balanceSheet -j examples/example.bean --to 2018-01-01
|------------+----------+-----------+------------------+----------+-----------|
| Account    | Amount   | Commodity | Account          | Amount   | Commodity |
|------------+----------+-----------+------------------+----------+-----------|
| Assets     | 15000.00 | USD       | Equity           | 15000.00 | USD       |
|   Checking | 15000.00 | USD       |   OpeningBalance | 15000.00 | USD       |
|------------+----------+-----------+------------------+----------+-----------|
| Total      | 15000.00 | USD       | Total            | 15000.00 | USD       |
|------------+----------+-----------+------------------+----------+-----------|

No surprise, this is our opening balance.

Now let's get an overview of our income and expenses in January 2018:

beans incomeStatement -j examples/example.bean --to 2018-01-31
|-------------+----------+-----------|
| Account     | Amount   | Commodity |
|-------------+----------+-----------|
| Income      |  4000.00 | USD       |
|   Salary    |  4000.00 | USD       |
|-------------+----------+-----------|
| Expenses    | -2600.00 | USD       |
|   Books     |  -100.00 | USD       |
|   Groceries |  -500.00 | USD       |
|   Rent      | -2000.00 | USD       |
|-------------+----------+-----------|
| Total       |  1400.00 | USD       |
|-------------+----------+-----------|

3.4.2 Balance Sheet

As of 1 February, the balance looks as follows:

beans balanceSheet -j examples/example.bean --to 2018-02-01
|-------------+---------+-----------+--------------------+----------+-----------|
| Account     | Amount  | Commodity | Account            | Amount   | Commodity |
|-------------+---------+-----------+--------------------+----------+-----------|
| Assets      |   10.00 | AAPL      | Equity             | 14400.00 | USD       |
|             |    0.25 | BTC       |   OpeningBalance   | 15000.00 | USD       |
|             | 9200.00 | USD       |   RetainedEarnings |  -600.00 | USD       |
|   Checking  | 9200.00 | USD       |                    |          |           |
|   Portfolio |   10.00 | AAPL      |                    |          |           |
|   Wallet    |    0.25 | BTC       |                    |          |           |
|-------------+---------+-----------+--------------------+----------+-----------|
| Total       |   10.00 | AAPL      | Total              | 14400.00 | USD       |
|             |    0.25 | BTC       |                    |          |           |
|             | 9200.00 | USD       |                    |          |           |
|-------------+---------+-----------+--------------------+----------+-----------|

What happened? Our sample person did invest in 0.25 BTC and 10 AAPL during January, as is evident in the journal. This is not reflected in the income statement, as we did not model the trades with income and expenses, but rather against equity.

3.4.3 Valuation at latest prices

Seeing all commodities separately helps tracking the inventory, but they are difficult to compare. Fortunately, we have some prices in the journal, so we can print the same table valued at market prices.

beans balanceSheet -j examples/example.bean --to 2018-02-01 -m USD
|-------------+----------+-----------+--------------------+----------+-----------|
| Account     | Amount   | Commodity | Account            | Amount   | Commodity |
|-------------+----------+-----------+--------------------+----------+-----------|
| Assets      | 13133.06 | USD       | Equity             | 13133.06 | USD       |
|   Checking  |  9200.00 | USD       |   OpeningBalance   | 15000.00 | USD       |
|   Portfolio |  1670.00 | USD       |   RetainedEarnings |  -600.00 | USD       |
|   Wallet    |  2263.06 | USD       |   Valuation        | -1266.94 | USD       |
|-------------+----------+-----------+--------------------+----------+-----------|
| Total       | 13133.06 | USD       | Total              | 13133.06 | USD       |
|-------------+----------+-----------+--------------------+----------+-----------|

When valuating the balance in a certain reference commodity, beans accounts for changes in valuation using the Equity:Valuation account. It reflects gains and losses over time with respect to the reference currency.

3.4.4 Analysis & Filtering

Now, how is this valuation loss explained? beans allows for arbitrary slicing:

beans balanceSheet -j examples/example.bean --to 2018-02-01 -m USD --filter Portfolio
|-------------+----------+-----------+-------------+--------+-----------|
| Account     | Amount   | Commodity | Account     | Amount | Commodity |
|-------------+----------+-----------+-------------+--------+-----------|
| Assets      |   -30.00 | USD       | Equity      | -30.00 | USD       |
|   Checking  | -1700.00 | USD       |   Valuation | -30.00 | USD       |
|   Portfolio |  1670.00 | USD       |             |        |           |
|-------------+----------+-----------+-------------+--------+-----------|
| Total       |   -30.00 | USD       | Total       | -30.00 | USD       |
|-------------+----------+-----------+-------------+--------+-----------|

beans balanceSheet -j examples/example.bean --to 2018-02-01 -m USD --filter Wallet
|------------+----------+-----------+-------------+----------+-----------|
| Account    | Amount   | Commodity | Account     | Amount   | Commodity |
|------------+----------+-----------+-------------+----------+-----------|
| Assets     | -1236.94 | USD       | Equity      | -1236.94 | USD       |
|   Checking | -3500.00 | USD       |   Valuation | -1236.94 | USD       |
|   Wallet   |  2263.06 | USD       |             |          |           |
|------------+----------+-----------+-------------+----------+-----------|
| Total      | -1236.94 | USD       | Total       | -1236.94 | USD       |
|------------+----------+-----------+-------------+----------+-----------|

The analysis shows that the lion's share of the loss is due to the BTC trade, which happened in the Assets:Wallet account.

Commodities are freely convertible. How about a balance sheet in BTC?

beans balanceSheet -j examples/example.bean --to 2018-02-01 -m BTC
|-------------+--------+-----------+--------------------+--------+-----------|
| Account     | Amount | Commodity | Account            | Amount | Commodity |
|-------------+--------+-----------+--------------------+--------+-----------|
| Assets      |   1.45 | BTC       | Equity             |   1.45 | BTC       |
|   Checking  |   1.02 | BTC       |   OpeningBalance   |   1.12 | BTC       |
|   Portfolio |   0.18 | BTC       |   RetainedEarnings |  -0.12 | BTC       |
|   Wallet    |   0.25 | BTC       |   Valuation        |   0.45 | BTC       |
|-------------+--------+-----------+--------------------+--------+-----------|
| Total       |   1.45 | BTC       | Total              |   1.45 | BTC       |
|-------------+--------+-----------+--------------------+--------+-----------|

Stepping forward in time, what does the income statement look like over H1/2018?

beans incomeStatement -j examples/example.bean --from 2018-01-01 --to 2018-06-30
|-------------+----------+-----------|
| Account     | Amount   | Commodity |
|-------------+----------+-----------|
| Income      | 12000.00 | USD       |
|   Salary    | 12000.00 | USD       |
|-------------+----------+-----------|
| Expenses    | -7200.00 | USD       |
|   Books     |  -100.00 | USD       |
|   Groceries | -1100.00 | USD       |
|   Rent      | -6000.00 | USD       |
|-------------+----------+-----------|
| Total       |  4800.00 | USD       |
|-------------+----------+-----------|

3.5 Low-level balancing

3.5.1 Global balance

In addition to the predefined reports, beans has a generic balancing command:

beans balance -j examples/example.bean

This outputs a balance for all accounts without any currency conversions.

|------------------+-----------+-----------|
| Account          | Amount    | Commodity |
|------------------+-----------+-----------|
|                  |     10.00 | AAPL      |
|                  |      0.25 | BTC       |
|                  |  -5200.00 | USD       |
| Assets           |     10.00 | AAPL      |
|                  |      0.25 | BTC       |
|                  |  14600.00 | USD       |
|   Checking       |  14600.00 | USD       |
|   Portfolio      |     10.00 | AAPL      |
|   Wallet         |      0.25 | BTC       |
| Equity           | -15000.00 | USD       |
|   OpeningBalance | -15000.00 | USD       |
| Expenses         |   7200.00 | USD       |
|   Books          |    100.00 | USD       |
|   Groceries      |   1100.00 | USD       |
|   Rent           |   6000.00 | USD       |
| Income           | -12000.00 | USD       |
|   Salary         | -12000.00 | USD       |
|------------------+-----------+-----------|

3.5.2 Balancing options

  1. Flattening the account structure

    There are some formatting options available (some of which also apply to the predefined reports):

    beans balance -j examples/example.bean --flat --depth 0
    
    |----------+-----------+-----------|
    | Account  | Amount    | Commodity |
    |----------+-----------+-----------|
    |          |     10.00 | AAPL      |
    |          |      0.25 | BTC       |
    |          |  -5200.00 | USD       |
    | Assets   |     10.00 | AAPL      |
    |          |      0.25 | BTC       |
    |          |  14600.00 | USD       |
    |          |     10.00 | AAPL      |
    |          |      0.25 | BTC       |
    |          |  14600.00 | USD       |
    | Equity   | -15000.00 | USD       |
    |          | -15000.00 | USD       |
    | Expenses |   7200.00 | USD       |
    |          |   7200.00 | USD       |
    | Income   | -12000.00 | USD       |
    |          | -12000.00 | USD       |
    |----------+-----------+-----------|
    
    
  2. Valuation at market prices

    Valuation at market (i.e. latest available prices) is always an option:

    beans balance -j examples/example.bean -m USD
    
    |------------------+-----------+-----------|
    | Account          | Amount    | Commodity |
    |------------------+-----------+-----------|
    |                  |      0.00 | USD       |
    | Assets           |  18409.32 | USD       |
    |   Checking       |  14600.00 | USD       |
    |   Portfolio      |   2219.80 | USD       |
    |   Wallet         |   1589.52 | USD       |
    | Equity           | -13609.32 | USD       |
    |   OpeningBalance | -15000.00 | USD       |
    |   Valuation      |   1390.68 | USD       |
    | Expenses         |   7200.00 | USD       |
    |   Books          |    100.00 | USD       |
    |   Groceries      |   1100.00 | USD       |
    |   Rent           |   6000.00 | USD       |
    | Income           | -12000.00 | USD       |
    |   Salary         | -12000.00 | USD       |
    |------------------+-----------+-----------|
    
    
  3. Restricting dates and periods

    We can also analyze changes in the balance between specific dates:

    beans balance -j examples/example.bean -m USD --from 2018-06-30 --to 2018-10-30
    
    |-------------+---------+-----------|
    | Account     | Amount  | Commodity |
    |-------------+---------+-----------|
    |             |    0.00 | USD       |
    | Assets      |  115.06 | USD       |
    |   Portfolio |  350.10 | USD       |
    |   Wallet    | -235.04 | USD       |
    | Equity      | -115.06 | USD       |
    |   Valuation | -115.06 | USD       |
    |-------------+---------+-----------|
    
    

    As we didn't record any transactions in the journal for the second half of 2018, the corresponding changes in the balance sheet are uniquely due to market price changes.

    |-------------+---------+-----------|
    | Account     | Amount  | Commodity |
    |-------------+---------+-----------|
    |             |    0.00 | USD       |
    | Assets      |  115.00 | USD       |
    |   Portfolio |  350.00 | USD       |
    |   Wallet    | -235.00 | USD       |
    | Equity      | -115.00 | USD       |
    |   Valuation | -115.00 | USD       |
    |-------------+---------+-----------|
    
    
  4. Analyzing changes in valuation

    Using filtering, we can eliminate the effect of income and expenses and track valuation changes over the entire period:

    beans balance -j examples/example.bean --filter Valuation -m USD
    
    |-------------+----------+-----------|
    | Account     | Amount   | Commodity |
    |-------------+----------+-----------|
    |             |     0.00 | USD       |
    | Assets      | -1390.68 | USD       |
    |   Checking  | -5200.00 | USD       |
    |   Portfolio |  2219.80 | USD       |
    |   Wallet    |  1589.52 | USD       |
    | Equity      |  1390.68 | USD       |
    |   Valuation |  1390.68 | USD       |
    |-------------+----------+-----------|
    
    

    How about bitcoin?

    beans balance -j examples/example.bean -m BTC
    
    |------------------+--------+-----------|
    | Account          | Amount | Commodity |
    |------------------+--------+-----------|
    |                  |   0.00 | BTC       |
    | Assets           |   2.90 | BTC       |
    |   Checking       |   2.30 | BTC       |
    |   Portfolio      |   0.35 | BTC       |
    |   Wallet         |   0.25 | BTC       |
    | Equity           |  -2.44 | BTC       |
    |   OpeningBalance |  -1.12 | BTC       |
    |   Valuation      |  -1.32 | BTC       |
    | Expenses         |   0.65 | BTC       |
    |   Books          |   0.01 | BTC       |
    |   Groceries      |   0.09 | BTC       |
    |   Rent           |   0.55 | BTC       |
    | Income           |  -1.11 | BTC       |
    |   Salary         |  -1.11 | BTC       |
    |------------------+--------+-----------|
    
    

    beans derives arbitrary commodity conversions between all commodities, as long as there is at least one path (possibly over several links) from one commodity to another. For example, conversion from SomeStock in CHF is possible when prices of SomeStock in USD and CHF in USD is available. Inverted rates are derived automatically.

    At the moment, beans offers either no valuation or valuation at market prices. Valuation at cost is yet to be implemented.

3.6 Transaction-level valuation

beans applies valuation at the level of transactions, which seems unique amongst plain-text accounting tools. In the examples above, if a conversion to a common commodity is desired, beans will:

  • convert all bookings over the entire ledger to that commodity at market value (given by the transitive & reflexive closure of price directives at the transaction date),
  • insert valuation bookings for the accumulated positions of all asset and liability accounts whenever prices change. These adjustment are balanced against an Equity:Valuation account, which is hard-coded for the moment.

Every difference in value of an account over a period is explicitly modeled by corresponding valuation transactions. This greatly facilitates introspection and analysis, as every unit of the valuation commodity can be accounted for explicitly.

4 Developing beans

Development is very much in progress and beans is not really stable yet. It seems though that the basic pipeline (importing - categorizing - balancing) is there, and I am using it to balance my own journal. beans development is at the moment entirely driven by my own needs. It has also been a playground for experiments and lots of refactoring for fun with Haskell.

Use beans at your own risk - at the moment, it is certainly advantageous if you know some Haskell.

4.1 Roadmap

beans still has long way to go. I do this in my spare time and I do not have an explicit road map, but here are some ideas I'd like to be working on in the future:

4.1.1 Shorter term

  • [X] new command to print and filter transactions (as-is or at market value)
  • [ ] provide a more realistic example file
  • [ ] multi-period reports (yearly, monthly, weekly, daily, …)
  • [ ] colored output
  • [ ] friendlier command line
  • [ ] accounting at cost
  • [ ] more importers (I'll do those that I need personally, but I am happy to receive contributions if they are provided with a sample file / test)

4.1.2 Longer term

  • [ ] general reporting infrastructure
  • [ ] more reports (income statement, cash flow statement)
  • [ ] plotting / graphs
  • [ ] portfolio performance calculation
  • [ ] export to other tools (beancount / hledger / ledger)
  • [ ] more UI options (web, terminal)

4.2 Compatibility

beans journals are in syntax and semantics largely similar to beancount journals. However, due to some differences in semantics (e.g. the treatment of mult-commodity transactions), there is no guarantee that a beans journal works in beancount.

The best solution to facilitate use of multiple tools at some point would be an export commmand (like beancount provides), which translates the ledger into other formats.

4.3 Documentation

This manual aims to provide a comprehensive overview of its functionality. It is written in org-mode, please file a pull request against this file if you want to contribute.

4.4 Dev setup

4.4.1 nix / Haskell IDE engine

I am using Emacs and Haskell IDE Engine under Nixos. To setup your development environment and install all dependencies, simply run

nix-shell

if you have the nix package manager installed.

4.4.2 Stack

It should be possible to develop beans with stack. Please file a bug report / pull request if you discover anything that does not work as expected.

4.5 Adding an importer

beans is open to contributions, see the example here how an importer can be implemented. The directory should match the country of the bank. Make a pull request if you want to have it included in beans (preferrably with a test case and an anonymized sample file).

It is still an open question whether importers should be included in the beans repository or whether a more modular system should be adopted. I am open to suggestion.

4.6 Tests

Every importer should have a test and an example file. This being said, test coverage is currently lacking for the existing importers.

5 License

beans is licensed under the BSD-3 license.

Author: Silvio Böhler

Created: 2019-01-27 So 23:37

Validate