Questions for rigorous cap gains tracking

86 views
Skip to first unread message

Eric Altendorf

unread,
Jul 14, 2023, 11:19:47 PM7/14/23
to bean...@googlegroups.com
I'm looking into Beancount for the specific purpose of rigorous capital gains tracking for crypto transactions.  I just read the docs, and now have a few questions, hoping someone can help.  Thanks in advance!  :)

I'd like to run my own rules for booking (mostly HIFO, except able to select a slightly lower basis lot if it qualifies for long term instead of short term cap gains .. maybe some other special cases).  I'm guessing I will need to implement these rules in my importer somehow, and have the importer label each lot and sale?  Or should I implement the rules in Beancount directly?

I'll have a few (maybe 3-6) CSVs of all-time transactions from wallet software or downloaded from exchanges.  Should I write Beancount importers, or just scripts that generate Beancount text files?  Does my need for custom lot-selection rules affect this decision?

What's a good workflow for taking the booking decisions Beancount makes for a given tax year and "locking" them in so they can't be changed when I run again in the next tax year -- e.g., if I tweak my booking algorithm?

I saw in the docs somewhere that transaction merging isn't well supported.  Is that still the case?  This is something I'll encounter since transfers between an exchange and a cold wallet will result in one leg being imported from the exchange and the other from the cold wallet.

I was a little surprised that Beancount doesn't deal with times or timezones :)  Are there cases where ordering of intraday transactions can mess things up?

This page discussed Beancount's incomplete handling of acquisition costs/commissions:
Is that still an outstanding issue?

In cases where a transaction has legs in non-USD (e.g., a USDT (Tether stablecoin) / BTC swap), but it needs to be tracked for taxes in USD terms, is it a good practice to split the transaction with a synthetic temporary position in USD (i.e., one USDT-USD tx and one USD-BTC tx?)

This doesn't matter yet for crypto, but are there ways to catch/prevent wash sales using Beancount?

Thanks again!

Eric


Martin Blais

unread,
Jul 30, 2023, 11:39:02 AM7/30/23
to bean...@googlegroups.com
On Sat, Jul 15, 2023 at 11:19 AM Eric Altendorf <erical...@gmail.com> wrote:
I'm looking into Beancount for the specific purpose of rigorous capital gains tracking for crypto transactions.  I just read the docs, and now have a few questions, hoping someone can help.  Thanks in advance!  :) 

I'd like to run my own rules for booking (mostly HIFO, except able to select a slightly lower basis lot if it qualifies for long term instead of short term cap gains .. maybe some other special cases).  I'm guessing I will need to implement these rules in my importer somehow, and have the importer label each lot and sale?  Or should I implement the rules in Beancount directly?

Those are not pluggable (but it would be a good idea to restructure some of my code to make it so).
You'd have to make the change to the "master" branch, if you mirror the other methods I'd welcome a PR (it should be easy I think).


I'll have a few (maybe 3-6) CSVs of all-time transactions from wallet software or downloaded from exchanges.  Should I write Beancount importers, or just scripts that generate Beancount text files?  Does my need for custom lot-selection rules affect this decision?

Not really. I think it's a matter of whether you think the identify/extract/archive functionality is useful to you.
Based on all the emails that follow this one, I suspect not; a custom script is probably what you're after.

Also note: if you'll invest a lot of time into this, if your only purpose is to get booking like HIFO you can probably just as well do away with Beancount and write something custom.


What's a good workflow for taking the booking decisions Beancount makes for a given tax year and "locking" them in so they can't be changed when I run again in the next tax year -- e.g., if I tweak my booking algorithm?

You don't reimport the same material. Updating your Beancount input file should be an incremental process. Don't overwrite that you already imported. Similar to my previous comment -- if you're going to automate importing everything from scratch every time you might as well build something distinct; I did that myself with github.com/blais/johnny.


I saw in the docs somewhere that transaction merging isn't well supported.  Is that still the case?  This is something I'll encounter since transfers between an exchange and a cold wallet will result in one leg being imported from the exchange and the other from the cold wallet.

That's still the case.  For context: by "merging" what is meant here is that the two halves of a two posting transaction are inserted in the input as two distinct transactions and automatically merged into one.  (It just requires a feature that matches the transactions and inserts postings to transfer accounts, a bunch of design questions would come up.)


I was a little surprised that Beancount doesn't deal with times or timezones :)  Are there cases where ordering of intraday transactions can mess things up?

That was an explicit design decision to (a) keep things simple (it can get pretty hairy), (b) because the various institutions don't usually include time and we're just trying to represent the data from the institutions. At this stage my sense is that all we need is a way to resolve ordering.  Given that balance checks are done sparsely on the flow of transactions changes in ordering don't cause dramatic problems, but like the ability to resolve the mismatch in dates from two sides of a transaction, it would be nice to eventually solve this properly.

 

This page discussed Beancount's incomplete handling of acquisition costs/commissions:
Is that still an outstanding issue?

Yes.  Historically the few times I needed this I wrote a script to do this at reporting time. Johnny also deals with this properly.


In cases where a transaction has legs in non-USD (e.g., a USDT (Tether stablecoin) / BTC swap), but it needs to be tracked for taxes in USD terms, is it a good practice to split the transaction with a synthetic temporary position in USD (i.e., one USDT-USD tx and one USD-BTC tx?)

I have no idea (I don't do crypto).
It sounds to me more onerous than to just use USD right away, but I have no idea how those things get taxed.


This doesn't matter yet for crypto, but are there ways to catch/prevent wash sales using Beancount?

Oh gosh... I went down the rabbit hole of attempting to compute them some years ago, I remember I went deep on that one. After spending days building something and looking into all the minute details and examples from the IRS I came out with the conviction that it's an ill-defined problem, there are cases you can't resolve. I can't remember now. I'm scarred.

But that's a separate issue. It should be easy to build something that warns you as of a particular date (say "today") and across all your accounts what you can't trade. I think I do that in Johnny, it has page in its web interface I can consult. I don't think that was done in Beancount (at least not by me).

 

Thanks again!

Eric


--
You received this message because you are subscribed to the Google Groups "Beancount" group.
To unsubscribe from this group and stop receiving emails from it, send an email to beancount+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beancount/CAFXPr0v18V479ZF4h8Rvz%2B_6fmAjttrkZamDpQXhE%2BHx%3DKg7sg%40mail.gmail.com.

Eric Altendorf

unread,
Aug 1, 2023, 3:39:30 PM8/1/23
to bean...@googlegroups.com
On Sun, Jul 30, 2023 at 8:39 AM Martin Blais <bl...@furius.ca> wrote:
On Sat, Jul 15, 2023 at 11:19 AM Eric Altendorf <erical...@gmail.com> wrote:
...
I'd like to run my own rules for booking (mostly HIFO, except able to select a slightly lower basis lot if it qualifies for long term instead of short term cap gains .. maybe some other special cases).  I'm guessing I will need to implement these rules in my importer somehow, and have the importer label each lot and sale?  Or should I implement the rules in Beancount directly?

Those are not pluggable (but it would be a good idea to restructure some of my code to make it so).
You'd have to make the change to the "master" branch, if you mirror the other methods I'd welcome a PR (it should be easy I think).

I took a look at the code -- looks like it should be pretty easy to add new methods there.  I'm not that far along yet, but when I get there I'll be in touch about it.

...
You don't reimport the same material. Updating your Beancount input file should be an incremental process. Don't overwrite that you already imported. Similar to my previous comment -- if you're going to automate importing everything from scratch every time you might as well build something distinct; I did that myself with github.com/blais/johnny.

Understood.  For now I'm using the Beancount engine, data structures, and query language as a way to batch process the transactions, which I know is not the intended use.  So far it's been OK, and what Beancount offers has been useful, but we'll see how far it takes me.  It does seem like the core engine is amenable to use in a variety of workflows...

I saw in the docs somewhere that transaction merging isn't well supported.  Is that still the case?  This is something I'll encounter since transfers between an exchange and a cold wallet will result in one leg being imported from the exchange and the other from the cold wallet.

That's still the case.  For context: by "merging" what is meant here is that the two halves of a two posting transaction are inserted in the input as two distinct transactions and automatically merged into one.  (It just requires a feature that matches the transactions and inserts postings to transfer accounts, a bunch of design questions would come up.)

As mentioned elsewhere, I'm startinng to feel this is better addressed by the ZeroSum pattern than implicit merging.  So far I'm happy with that.
 

I was a little surprised that Beancount doesn't deal with times or timezones :)  Are there cases where ordering of intraday transactions can mess things up?

That was an explicit design decision to (a) keep things simple (it can get pretty hairy), (b) because the various institutions don't usually include time and we're just trying to represent the data from the institutions. At this stage my sense is that all we need is a way to resolve ordering.  Given that balance checks are done sparsely on the flow of transactions changes in ordering don't cause dramatic problems, but like the ability to resolve the mismatch in dates from two sides of a transaction, it would be nice to eventually solve this properly.

Yeah, i get it. :)  I do agree that ordering is the primary issue; if we got correct ordering without timestamps and timezones that would probably be good enough.  Since crypto trades 24/7 and in exchanges in different timezones, discrete nominal days don't reflect the underlying reality very clearly.  I ran into a number of cases where ordering was an issue because negative balances simply aren't treated the same.  However, it was pretty easy to work around by attaching a timestamp on the metadata and sorting the transactions myself by that.
 
...

thanks,
eric 

Eric Altendorf

unread,
Aug 9, 2023, 12:47:13 AM8/9/23
to bean...@googlegroups.com
On Sun, Jul 30, 2023 at 8:39 AM Martin Blais <bl...@furius.ca> wrote:
On Sat, Jul 15, 2023 at 11:19 AM Eric Altendorf <erical...@gmail.com> wrote:

This page discussed Beancount's incomplete handling of acquisition costs/commissions:
Is that still an outstanding issue?

Yes.  Historically the few times I needed this I wrote a script to do this at reporting time. Johnny also deals with this properly.

This is now one of my next issues to deal with.  I could hack my importers to tweak costs and proceeds, but it feels like something better handled by a plugin?  I found this in labs, which I assume means it's only a partial solution:


Are there any other relevant existing plugins?  This seems like a very common need for trading/investing, I would think someone has solved this already...


Eric Altendorf

unread,
Aug 15, 2023, 11:15:16 PM8/15/23
to bean...@googlegroups.com
In the rare chance someone else is following along at home :), i decided to implement this in my importers.  It was a little easier to verify that everything's correct given I have some wonky fee structures (e.g., fees paid in the traded asset rather than USD).  It does make the reporting and human legibility worse, but it's still grokkable, and i leave breadcrumbs in the metadata.

 
Reply all
Reply to author
Forward
0 new messages