Beancount getting started

Hey all,
i finally switched to beancount. i must admit it was not too easy to get stuff running, especially since i started using linux (ubuntu WSL) just at the same time.

now, anybody here has some scripts already made to import postfinance account statements?

would be really nice :slight_smile: @hedgehog maybe, if you are still around?

thanks!

3 Likes

I cannot help you with postfinance but I would be interested if anybody has scripts for IBKR or revolut. I have some scripts for UBS and cembra credit card. Basically you can easily tune the csv script to work with any csv list, even different ones at the same time. I just had some troubles with the original file encoding depending on the provider.

Webgui looks awesome ( https://beancount.github.io/fava/ )
Demo: https://fava.pythonanywhere.com/example-with-budgets/income_statement/

I also found another ledger/beancount tool, but this one has a postfinance and interactive brokers parser: https://github.com/sboehler/beans

I found some importer for beancount:

DKB

ING-DiBa

Commerzbank

N26

I’m using beancount for a while and I’m really happy!!
I started with imports, etc…and finished doing passing all to CSV, from there to Numbers or Excel and… adding unique identifiers after each field to copy and paste everything to a power text editor, kind of Visual Code where I format in beancount format.

It’s long and I don’t have time to explain the complete method but is something like that: You have:

10.10.2019. “Buy in COOP” 123 CHF

I put. In excel columns like:

10.10.2019 * ###_### “Buy in COOP” —- Expenses:Groceries 123 CHF

Copy and paste to Visual Code and find all the “special” fields to make a global “enter” and spaces…etc… you edit a line but you are editing the thousand of lines that have your file… I don’t know if is clear.

Takes time, I know, but is much more quicker than finding an importer :wink:

You can use this https://sboehler.github.io/beans/ , it provides parsing for:

us.interactivebrokers ( Interactive Brokers )
ch.postfinance ( Postfinance )
ch.supercardplus ( Supercard Plus )

"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. "

2 Likes

Do we have a beancount expert or python coder here?
I’m new to beancount and need an importer for revolut and cashback creditcards.
Some example files:
https://www.dropbox.com/sh/yrpjw2tvmo8uszk/AAB00B6XAoe2UGWeMOGiGCGwa?dl=0

I pay you a beer or coffee :wink:

@nugget
I posted a parser for postfinance ( https://sboehler.github.io/beans/ ) , works perfect with beancount :slight_smile:


19

With the csv you can parse it and use it with beancount.
You can edit the “examples.rules” for the matching:

description =~ “Mintos Marketplace” -> Assets:DE:Mintos:Investments
description =~ “Wohnungsmiete.*” -> Expenses:Home:Rent

And parse your csv file with beans:
./beans import -i ch.postfinance -c example.rules -a Assets:CH:Postfinance:Shared postfinance20191102.csv >> myfile.beans

1 Like

ahahah i never scrolled down that page to realize the export-button. thanks for pointing out!

thanks for posting the command too, i’m quit new to unix and it always takes ages to figure out the next command :smiley:

1 Like

… anyone looked at beancount.io and furious.ca? seems to me the author removes some content and moves towards a paid solution. what u think?

I’m not even sure it’s from the same author:

Beancount.io is not affiliated with github.com/beancount but uses Fava under MIT license

The source code is still available from the bitbucket repo but the doc on furius.ca seems to be gone, weird.

yes exactly, i find alot of dead links recently

Anyone got the

beancount.price

stock quote fetching running?

[edit] yes! yahoo works, now working on google:

bean-price -e USD:yahoo/VTI
2019-11-19 price VTI 158.73 USD
bean-price -e USD:google/NYSEARCA:VTI
ERROR : Could not fetch for job: DatedPrice(base=‘NYSEARCA:VTI’, quote=‘USD’, date=None, sources=[PriceSource(module=<module ‘google’ (namespace)>, symbol=‘NYSEARCA:VTI’, invert=False)])

I always put both Google and yahoo, I’m not sure if Google is still working.

could you share your explicit line of code? thanks :slight_smile:

Google API is not maintained/available for a while…
Yahoo or Alphavantage are your best alternatives.
I’ve been using Yahoo with Beancount for months without any problem.

Some other ideas:

An advice for people starting with beancount:

  • Install VS Code, is a free ASCII editor available in all the platforms. Is very well done.
  • Install a extension named: VSCode-Beancount and follow the instructions about how to organise the files!!!

https://marketplace.visualstudio.com/items?itemName=Lencerf.beancount

You’ll love beancount after that :wink:

Tino.

I think I got exactly to this solution - by some chance :joy::joy:
no idea on how cruel it is if I started doing stuff with nano (i am new to ubuntu…) :smiley:

thanks for mentioning :smiley:

I got help from the beancounts maillinglist for revolut import.

The code for the importer:

from dateutil.parser import parse
from io import StringIO
from beancount.ingest import importer
from beancount.core import data
from beancount.core import amount
from beancount.core.number import D
from beancount.ingest.importers.mixins import identifier
import csv

  class Importer(identifier.IdentifyMixin,
  importer.ImporterProtocol):
      """An importer for Revolut CSV files."""
  
      def __init__(self, regexps, account, currency):
          identifier.IdentifyMixin.__init__(self, matchers=[
              ('filename', regexps)
          ])
          self.account = account
          self.currency = currency
  
      def name(self):
          return super().name() + self.account
  
      def file_account(self, file):
          return self.account
  
      def extract(self, file, existing_entries):
          entries = []
  
          with StringIO(file.contents()) as csvfile:
              reader = csv.DictReader(csvfile, ['Date',
  'Reference','PaidOut', 'PaidIn', 'ExchangeOut', 'ExchangeIn',
  'Balance', 'Category', 'Notes'], delimiter=';',
  skipinitialspace=True)
              next(reader)
              for row in reader:
                  metakv = {
                      'category': row['Category'].strip(),
                  }
                  exchangeIn = row['ExchangeIn'].strip()
                  exchangeOut = row['ExchangeOut'].strip()
                  if exchangeIn and exchangeOut:
                      metakv['originalIn'] = exchangeIn
                      metakv['originalOut'] = exchangeOut
                  elif exchangeIn:
                      metakv['original'] = exchangeIn
                  elif exchangeOut:
                      metakv['original'] = exchangeOut
  
                  meta = data.new_metadata(file.name, 0, metakv)
                  entry = data.Transaction(
                      meta,
                      parse(row['Date'].strip()).date(),
                      '*',
                      '',
                      (row['Reference'].strip() + ' ' +
  row['Notes'].strip()).strip(),
                      data.EMPTY_SET,
                      data.EMPTY_SET,
                      [
                          data.Posting(self.account,
  amount.Amount(D(row['PaidIn'].strip()) -
  D(row['PaidOut'].strip()), self.currency), None, None, None,
  None),
                      ]
                  )
                  entries.append(entry)
          return entries`

config.py:

`from dateutil.parser import parse
from io import StringIO
from beancount.ingest import importer
from beancount.core import data
from beancount.core import amount
from beancount.core.number import D
from beancount.ingest.importers.mixins import identifier
import csv

  class Importer(identifier.IdentifyMixin,
  importer.ImporterProtocol):
      """An importer for Revolut CSV files."""
  
      def __init__(self, regexps, account, currency):
          identifier.IdentifyMixin.__init__(self, matchers=[
              ('filename', regexps)
          ])
          self.account = account
          self.currency = currency
  
      def name(self):
          return super().name() + self.account
  
      def file_account(self, file):
          return self.account
  
      def extract(self, file, existing_entries):
          entries = []
  
          with StringIO(file.contents()) as csvfile:
              reader = csv.DictReader(csvfile, ['Date',
  'Reference','PaidOut', 'PaidIn', 'ExchangeOut', 'ExchangeIn',
  'Balance', 'Category', 'Notes'], delimiter=';',
  skipinitialspace=True)
              next(reader)
              for row in reader:
                  metakv = {
                      'category': row['Category'].strip(),
                  }
                  exchangeIn = row['ExchangeIn'].strip()
                  exchangeOut = row['ExchangeOut'].strip()
                  if exchangeIn and exchangeOut:
                      metakv['originalIn'] = exchangeIn
                      metakv['originalOut'] = exchangeOut
                  elif exchangeIn:
                      metakv['original'] = exchangeIn
                  elif exchangeOut:
                      metakv['original'] = exchangeOut
  
                  meta = data.new_metadata(file.name, 0, metakv)
                  entry = data.Transaction(
                      meta,
                      parse(row['Date'].strip()).date(),
                      '*',
                      '',
                      (row['Reference'].strip() + ' ' +
  row['Notes'].strip()).strip(),
                      data.EMPTY_SET,
                      data.EMPTY_SET,
                      [
                          data.Posting(self.account,
  amount.Amount(D(row['PaidIn'].strip()) -
  D(row['PaidOut'].strip()), self.currency), None, None, None,
  None),
                      ]
                  )
                  entries.append(entry)
          return entries`

Run with command:
bean-extract config.py Revolut-CHF.myname.csv

1 Like
By reading and partipating to this forum, you confirm you have read and agree with the disclaimer presented on http://www.mustachianpost.com/
En lisant et participant à ce forum, vous confirmez avoir lu et être d'accord avec l'avis de dégagement de responsabilité présenté sur http://www.mustachianpost.com/fr/