Beancount getting started

I started using specific accounts of Liabilities: oder Assets:. Example:
I travel for my employer, and purchase a ticket for CH 100 on 1.1.2020. My employer reimburses me on 1.3.2020.

then I will have two transctions:

2020-01-01 "Employer" "Travel expenses"
    Assets:CreditCard   -100 CHF
    Assets:Claims:Employer  100 CHF

2020-01-03 "Employer" "Reimursement"
    Assets:Checkings 100 CHF
    Assets:Claims:Employer -100 CHF

This way, my personal expenses and earnings will not be affected by cash flow of my employer.

It then also does not matter if you book in 2019 or 2020, as this way of booking preserves your net worth.

Accounts with Liabilities: work the same way, but with opposing sign (-)

2 Likes

Thanks @nugget and @Ed_Waadt!

I found another treasure, which was hiding in plain sight:
http://furius.ca/beancount/doc/contrib

This is the current list of my plugins. They just add extra validations and thanks to them I fixed some errors I had in my text files.

  • plugin ā€œbeancount.plugins.nounusedā€
  • plugin ā€œbeancount.plugins.unique_pricesā€
  • plugin ā€œbeancount.plugins.onecommodityā€
  • plugin ā€œbeancount.plugins.noduplicatesā€
  • plugin ā€œbeancount.plugins.check_commodityā€
  • plugin ā€œbeancount.plugins.coherent_costā€
  • plugin ā€œbeancount-plugins-zack.file_orderingā€
  • plugin ā€œbeancount-plugins-zack.no_missing_documentsā€

Speaking of recurring transactions, there is beancount-interpolate, which looks great on the first look. I havenā€™t integrated it yet though. I am not sure if the convenience is worth losing the explicitness.


With regards to reimbursements, there is beancount-reds-plugins.zerosum, which also looks nice, but I am not sure I see a benefit of using it yet. It basically moves matched transactions into a separate account.


Last interesting plugin I found is beancount_reds_plugins/effective_date, which solves exactly the problem I outlined above: paying for utilities in a different month or year.

I have another question. Suppose I am living with a roommate and weā€™re both paying % of the rent. Each of us pays the rent from our own account. How would you account for this?

Ideally I would like to have a complete picture of all three accounts (mine, my roommates and the rent company). The motivation is that last time I was changing roommates, it was hard to figure out exactly who paid how much and how much we owe.

Should I use a specialized ledger file? I do not want to see my roommateā€™s transactions in my own. And I do not want to see the total in my Expenses:Rent in my own ledger. However, having a separate ledger would mean duplicating some transactions and extra overhead.

Hi,

Iā€™ve been thinking about your problem. Really interesting.
I didnā€™t solve but I was close. :wink: Iā€™m going to tell you how I was thinking in case that give you some idea to follow.

I was thinking about create a separate file for the roommates, letā€™s say room.bean.

In this file you put:

2020-01-01 open Equity:Room-Inicial CHF ; To avoid mixing with your Equity

2020-01-01 open Account:GuyA
2020-01-01 open Account:GuyB
2020-01-01 open Account:GuyC

2020-01-01 open Expenses:GuyA:House
2020-01-01 open Expenses:GuyB:House
2020-01-01 open Expenses:GuyC:House

And other Expenses you need, Electricity, taxes, etc.

You manage this account normally when you have to write the movements.

In your personal file, you add at the end:

include "room.bean"

The only problem I see is that you need to rename all the accounts shared with the room.bean to include all the movements in your personal account. If you had, Expenses:Rent:House, you must rename to Expenses:GuyA:House and so on.

If not, another solutions is tell your friends that your account will be Expenses:Rent:House and for them Expenses:GuyB:House.

I see some problems in this approach but I hope helps you to find a solution.

Regards.

1 Like

Hi Tino, thanks for the suggestion, but I think youā€™re trying to find answer to a different problem - sharing the ledger file with other people.

I do not want to share my ledger, I simply want to have an overview of all transactions without polluting my Expenses and my Assets.

Let me give an example:

open Assets:Bank
open Income:MyRoommate
open Expenses:Rent

2020-01-01 * "Paying rent - my part"
  Assets:Bank -1000 CHF
  Expenses:Rent 1000 CHF

2020-01-01 * "Paying rent - my roommate"
  Income:MyRoommate -1000 CHF
  Expenses:Rent 1000 CHF

This is very close to what I want to achieve. I am able to see

  1. how much we paid in total - just look at Expenses:Rent
  2. how much each of us paid - tuple of Expenses:Rent plus filter on where the money came from

Now the only problem is that Expenses:Rent does not correctly reflect my own expenses. I donā€™t want to include my roommateā€™s expenses in my own. I could have a separate expense account for my roommate, but then Iā€™d still see this account in my totals and I would have to explicitly filter it out everywhere. I donā€™t want to include a specific filter in all my reporting.

Any ideas how to overcome this?

1 Like

Wellā€¦ Now I understood. Really hard to find a solution without creating a second and completely independent ledger that will force you to write in both sides each time.

One solution could be a python program that regularly check your common rent ledger and extract your data and write in your fileā€¦ But is a bit too much.

I recommend you describing the problem to the ā€œgurusā€ of beancount, including his developer and wait their ideas. I did sometimes:

https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!msg/beancount/HvP95OcrsLM/n3G6eMfkAwAJ

Looking forward for an idea!

Regards.

Edit: Did you check https://beancount.github.io/docs/21_sharing_expenses_with_beancount.html ? I think there is some good ideas!

Does anybody has an importer for?

  • Cashback Visa
  • Cashback American Express?

Thanks :slight_smile:

Well, I think youā€™re not going to be able to see how much you paid together and only your share by looking at the same entryā€¦

Maybe this will help: Beancount - Cookbook - Sharing Expenses - Google Docs

Hi @svecon , the author of beancount_interpolate here :wave:

I feel your problem as I have a similar one quite often. From accounting perspective, youā€™re right that you should expense only your share of rent. I assume that you are the one who gives the rent to landlord - in that case your roommates are called debtors, and whenever they give you their share before or after paying to landlord is secondary. Therefore, the full story would look like this:

2020-01-01 open Assets:Debtors:GuyA
2020-01-01 open Assets:Debtors:GuyB
2020-01-01 open Assets:Debtors:GuyC

2020-05-27 * "GuyA" "Gave rent few days before"
    Assets:Bank 1000 CHF
    Assets:Debtors:GuyA -1000 CHF

2020-06-01 * "Landlord" "Paying rent"
    Assets:Bank -4000 CHF
    Assets:Debtors:GuyA 1000 CHF
    Assets:Debtors:GuyB 1000 CHF
    Assets:Debtors:GuyC 1000 CHF
    Expenses:Rent 1000 CHF

2020-06-01 * "GuyB" "Gave rent just in time"
    Assets:Bank 1000 CHF
    Assets:Debtors:GuyB -1000 CHF

2020-06-06 * "GuyC" "Gave rent late"
    Assets:Bank 1000 CHF
    Assets:Debtors:GuyC -1000 CHF

I made a new plugin beancount_share to simplify the sharing part of it. What you would write with it is the following (notice the tags):

plugin "beancount_share" "{}"

2020-05-27 * "GuyA" "Gave rent few days before"
    Assets:Bank 1000 CHF
    Assets:Debtors:GuyA -1000 CHF

2020-06-01 * "Landlord" "Paying rent" #share-GuyA #share-GuyB #share-GuyC
    Assets:Bank -4000 CHF
    Expenses:Rent 4000 CHF

2020-06-01 * "GuyB" "Gave rent just in time"
    Assets:Bank 1000 CHF
    Assets:Debtors:GuyB -1000 CHF

2020-06-06 * "GuyC" "Gave rent late"
    Assets:Bank 1000 CHF
    Assets:Debtors:GuyC -1000 CHF

Furthermore, if you use also another plugin breancount_oneliner of mine that would become as short as this:

plugin "beancount_share" "{}"
plugin "beancount_oneliner" "{}"

2020-05-27 note Assets:Debtors:GuyA "Assets:Bank   1000 CHF * GuyA     | Gave rent few days before *"
2020-06-01 note Assets:Bank         "Expenses:Rent 1000 CHF * Landlord | Paying rent #share-GuyA #share-GuyB #share-GuyC *" 
2020-06-01 note Assets:Debtors:GuyB "Assets:Bank   1000 CHF * GuyB     | Gave rent just in time *"
2020-06-06 note Assets:Debtors:GuyC "Assets:Bank   1000 CHF * GuyC     | Gave rent late *"

Cheers!

4 Likes

Hey thanks for sharing!
doyou actually know if there is anything like a list of plugins people made? the only one i know is in the beancount docs -i guess many are not listed there

Sorry that I only noticed this question when the thread was bumped, but I actually solved this issue.

I solved it like this:

2020-01-01 * "Landlord" "I pay rent"
  Assets:Bank           -2000 CHF
  Expenses:Rent          1000 CHF
  Liabitilies:Flatmate   1000 CHF

2020-01-10 * "Flatmate" "Flatmate pays me"
  Assets:Bank            1000 CHF
  Liabitilies:Flatmate  -1000 CHF

This way you keep it in line with the real world. As soon as youā€™ve paid, your flatmate has a liability. (you can put his account under assets, too, if you please, it depends if most of the time youā€™re the one owing him, or the other way round). When he pays, the liability is settled.

EDIT: I just read into the solution of @Akuukis and I see itā€™s practically the same idea, so I guess my answer is redundant :stuck_out_tongue:

1 Like

@Bojack Nice, itā€™s the same idea indeed :slight_smile:

@nugget I donā€™t know of a list where one could find everything. But hereā€™s the places I usually check out:

Also Costflow syntax may be interesting although itā€™s a not plugins per se. In one evening I made a nice Telegram bot with it that takes very terse input like @LIDO pusdienas 5.20 > lunch and shouts back fully formatted transactions (2020-10-13 note Assets:Cash "Expenses:Food:Lunch 5.2 EUR * LIDO | pusdienas *", very nice for data input. Iā€™m also considering to upgrade the oneliner plugin to use itā€™s syntax.

Since you seem like a real beancount pro, I guess I could complain a bit to you :smiley:
Iā€™m due for my annual beancount refresh, and Iā€™m already dreading this task. I have to collect all transactions from cumulus, postfinance, IB, revolut etc etc, then convert the pdf, excels, csv, then categorize the transactions (put each transaction into the correct account). Finally, update the prices of currencies and assets. Itā€™s a many-day task just to produce a few charts at the end.

I have not tried any plugins / loaders yet. Are they really worth it? Iā€™m afraid that the more plugins I use, the less maintainable the whole thing becomes. I like the ā€œvanillaā€, ā€œout of the boxā€ approach. And I also canā€™t see how any loader could automatically parse all my cumulus PDFs and then put them into the right categories? What is your approach? How long do you need to process a year worth of transactions?

*** rant over ***

Iā€™m usually importing trx around once a month. Without the importer plugins this wouldnā€™t work for me. Using importer plugins + smart importer for an initial classification works great for me. Iā€™m always importing through fava, so I can adjust the categorization right away.
As a dev, Iā€™m in the situation that I can write or adjust the importers as needed.
The beauty of beancount is that independent of how you get the trx in your files, itā€™s the same. So importers donā€™t influence anything past the import step.

1 Like

@bojack no pro yet, Iā€™m just a developer by profession that has some accounting education :slight_smile: Much to learn about beancount - have not even touched anything related to tracking stock tradingā€¦

I agree with @tarioch - developers are in the situation that they can write or adjust the importers as needed. And thatā€™s a lot of manual labor saved. Imagine to get your whole yearā€™s bank statement into a beancount in one click, and then spend couple of minutes to skim over it to fix and re-categorize some exception cases. PDF are a nightmare indeed, but csv are easy (unless your bank is very creative in breaking the data structure within, like I have oneā€¦). Everyone exports csvā€™s (or at least in xls, which you open in excel and then re-save as csv). The problem is that importers are kinda personal due categorization. If you ever wanted to pickup some scripting/programming, I highly, highly recommend to write an importer for one of your banks. If you can find an existing importer above, thatā€™s perfect - just use it as starting place, and donā€™t hesitate to fix/adjust as needed. Hereā€™s an importer for revolut I have not tried. Good luck!

As per plugins, yes, they may make whole thing less maintainable. May also make more maintainable :slight_smile: I personally love my oneliner plugin, itā€™s a perfect plugin for manual input - first one-line-one-tx resonates with me very well, second as 4x more txs are within my screen the whole file becomes more readable/scannable, and third for input just copy a similar line and adjust some values (most txs are repetitive anyways). If you wonā€™t try you wonā€™t know if it works for you.

From accounting perspective my advice would be - donā€™t bother to count every cent, and usually the last cents are the hardest :smiley: Itā€™s just waste of time for barely any information gained. For such catchup events my strategy is as follows:

  1. write balances for everything (cash, bank1, bank2, ā€¦)
  2. run importers where I have them (all banks), fix or adjust categorization as needed.
  3. write-off the difference to Expenses:Unknown (usually just cash), and spread it over the period since last catchup. Iā€™m a cash person, so usually thatā€™s an uncomfortable huge amount per day at first :smiley:
  4. search for receipts or try remember where I spent it. Write it down. Lower the write-off.
  5. repeat step 4 until unknown expenses are comfortably small enough. Leave it like that and stop here.

Iā€™ve had catchups for 3 months - thatā€™s an one dedicated evening (in theory). Unless I get distracted in philosophy of categorization, overhaul my ledger to account for partner, or need to create a new importer, or start to work on long-wished for plugin. I enjoy writing plugins more than entering data, soā€¦ as you see, I just published the share plugin (+/- week work) but havenā€™t yet done my own catchup :smiley:

I have never filled a backlog of a year :sweat_smile: Actually for a year it wonā€™t make a difference, because importers donā€™t care about amount of transactions. Itā€™s just more transactions to review (fast anyways), and more receipts to enter (still in magnitude of one evening). Buuutā€¦ a backlog for a year means itā€™s a lot more likely I got a new bank (or existing bank changed the csv structure) or any other distraction happened. I had never had a ā€œcalmā€ year so far, therefore, practically, could even be weeks.

Hope that helps and putā€™s your own time in perspective. Cheers!

I have a pretty identical workflow like @Akuukis.
on the weekend after a monthā€™s end i spend realistically 2h on ingesting all my financial data (2x Bank with 5 accounts, broker, revolut).
~15 min for downloading all non-API-able statements (authenticationā€¦)
~2 min for the actual ingestion script
~rest for adjusting account categories, fixing bugs in my code, and ensuring the balances match in the end.
Of course it takes much longer if i get enthusiastic and want to implement another feature.

I basically almost abandoned cash last year, for the simple reason that ingesting transactions is so much better automatable via csv account statements that remembering and typing in the cashier receipts. This way, it is actually not that bad to have my accounting accurate to <1CHF

@Bojack how about an iteration on the beancount meetup? everyone else, feel free to join :slight_smile:

i think the same about being a developer, clearly things come easier to you if you are. however, for me, beancount made me learn alot on python & developing that i use today in my profession. I like it :smiley:

4 Likes

A meetup would be grand, itā€™s just not easy to find the time. Iā€™m currently struggling with the price importer. Could you tell me:

  1. Where do the imported price loader python files go? For example the ones from @tarioch? Where do I put them?
  2. How do I use a price loader? In command line, when I call bean-price -e EUR:coinbase/BTC-EUR, I get the BTC price in EUR for today. But thatā€™s no different than going to the website and checking the price myself. I was hoping for some automated magic. Like, it loads all the prices (daily, monthly, I donā€™t know) and saves them in a .bean file.
  3. What is the function of the ā€œpriceā€ property for a commodity? I defined it like this, but of course it doesnā€™t do anything:
2015-12-31 commodity BTCX
  name: "BTC/CHF"
  price: "CHF:coinbase/BTC-CHF"
  1. Does fava support any of it, or is whatever Iā€™m missing only accessible through command line?

Iā€™d gladly show you my setup via zoom or so, so you can get an idea

fava is totally independend of your other points. fava is the visualisation, not the logic. however it hats a field for the beancount query language, where you can query stuff off your ledger

in my main.bean file, i have a include price.bean (residing in the same folder) where the content is an ever-growing list of stuff like

2020-12-15 price USD                                  0.89 CHF
2020-12-14 price VTI                                189.64 USD

this stuff gets there via a (weekly) cron-jobbed script containing

bean-price --no-cache path/to/main.bean >> path/to/price.bean

and the main.bean in turn contains (via included commodities.bean)

1970-01-01 commodity EUR
    name: "Euro"
    price: "CHF:yahoo/^CHFEUR=X"

1970-01-01 commodity VTI
    name: "VTI"
    price: "USD:yahoo/VTI"

this is either a price, if you are fine with a constant price. or it is a key that certain FX providers uses. in my case, i fetch prices from yahoo

1 Like
meetup date
  • Sunday 6pm
  • Tuesday 7pm
  • Tuesday 10pm
  • Wednesday 7pm
  • Wednesday 10pm

0 voters

My setup is very similar to the one from @nugget

To use my price importers what you need to do is install them, e.g. something like

pip install tariochbctools

and then you can use them in a commodity like

2010-01-01 commodity USD price: "CHF:tariochbctools.plugins.prices.exchangeratesapi/USD"

The price loader I use in the cronjob is a little bit more advanced

#!/usr/bin/env python3
from beancount.prices import price
from beancount import loader
from beancount.parser import printer

entries, errors, options = loader.load_file('main.beancount')
priceJobs = price.get_price_jobs_at_date(entries, inactive=True)
prices = []

for job in priceJobs:
    prices.append(price.fetch_price(job))

prices, ignoredEntries = price.filter_redundant_prices(prices, entries)

for newPrice in prices:
    with open('prices/' + newPrice.currency.lower() + '.beancount', 'a') as priceFile:
        priceFile.write(printer.format_entry(newPrice))

the script loads the file main.beancount to find all the commodities and then fetches the prices and puts them into a file prices/COMMODITY_NAME.beancount

1 Like