An example of some commissions

For those that aren’t familiar with the Binance referral program, let me enlighten you. For every person that you refer to the exchange, Binance pays you 20% (originally 50%) of the trading fees that the user pays when they make trades. This benefit lasts indefinitely, and is paid out in real time. What’s more interesting is that the fees are either collected in the currency traded, or in the form of Binance’s home-grown crypto, Binance Coin (BNB). This means you get a wide range of different crypto-currencies, and in essence creates a portfolio that’s largely based on what users are trading at that moment in time.

At first this was super exciting for me, but as time went on I started to get nervous. The IRS has been fairly vocal about Americans paying their fair share of taxes on crypto-currency related gains recently, and I’m not really interested in going to jail for tax evasion. How was I supposed to account for the hundreds, maybe thousands of referral micro-payments I was receiving on a daily basis, in a litany of different currencies? I couldn’t expect Binance — a Chinese exchange — to provide me with this information. They don’t even have a report that shows the total of what they’ve paid you, only an estimated earnings… shown in current Bitcoin value.

Not to bore you, but traditional tax regulations would suggest that these referral bonuses be reported on a 1099-MISC form as non-employee compensation. In the case of crypto-currencies, an added component of complexity involves accounting for the USD value of the payment at the time of payment. This total USD value is then taxed as regular income. Now you may be starting to understand why I was getting nervous… I had next to no way of keeping track of this amount of information on a daily basis, let alone an individual transaction level (I do have a regular job after all).

“How hard could it be?”

I knew I had to do something, so I started looking into the Binance API to see if there was a way I could pull this information out myself since they weren’t going to give it to me. While I was researching, I came across a GitHub repository with a simple Python client that I could use to download my account balances and current market prices as dictionaries. Now I’m not a programmer in any sense of the word, but I do know the basics, and Google knows everything anyways. How hard could it be… right?

Well it turned out to be pretty freakin hard to say the least. Like I said, I’m not a programmer, so most of what I came up with was a Frankenstein’s monster of other people’s code that I begged for on StackOverflow (seriously, my account almost got banned because I’m so bad at asking questions). In hindsight though, I’ve learned this is basically what all programmers do… so that’s encouraging. If you’re a lucky duck and don’t have a legal obligation to learn how I did this, you may consider ending your read here. But I know some people are actually interested in code, so I detailed my thought process below.

“I could see I had my work cut out for me”

As I mentioned earlier, Toshima’s Binance API packet (or is it a program? A CLI?), allowed me to download my account balances and market prices as handy Python dictionaries, which are kind of like coded versions of Excel spreadsheets. Having a finance education, I know my way around a good ol’ fashioned spreadsheet, so the way I thought through this was by working backwards from what I wanted to end up with as a spreadsheet at the end of each day. I came up with 4 key data points I wanted for each asset:

My balance of the asset The current Asset/BTC trading price The total BTC equivalent value (this is just balance x the trading price) The total USD value

It sounded simple enough, but after I made my first few API calls I could see I had my work cut out for me.

The Challenges

The Battle with Balances

There were three main challenges I faced with these dictionaries. The first was my balance was split into two types: Locked and Free. Since the IRS doesn’t really care what state your money is in, I needed to combine these two values together. Below is an example of what the data looks like (balances not real because duh).

{u'FUEL': {'locked': u'0.00000000', 'free': u'67.98871'}, u'ARK': {'locked': u'0.00000000', 'free': u'1.70423640'}, u'QLC': {'locked': u'0.00000000', 'free': u'1.28060000'}, u'ARN': {'locked': u'0.00000000', 'free': u'6.75792000'}}

Now you can see the extent of noob that I am, I had no idea where to start with this. Through diligent Googling though, I came across something called Dictionary Comprehension. This is basically a way to create or modify a dictionary by iterating over keys and values (I’m sure there is a lot more to this, but if you want a formal education in Python this is not the place to get it). I’m not going to bore you with the entire revision process it took for me to actually make this work, but I ended up with this code, which combined the two values together:

simp_bal = {k: {“balance” : float(v[“free”]) + float(v[“locked”])} for k, v in bal.items()}

Now I won’t bore you with the entirety of my trial and error process to get all the values I wanted… but it took ages for me to really understand what was going on here.

The Price Problem

Price initially seemed like it wouldn’t be a big deal. At this point I hadn’t looked at the actual output of the price call, so I gave it a shot to see what I was up against.

{u'MCOBNB': u'0.42111000', u'LTCBNB': u'9.46000000', u'SALTBTC': u'0.00028120', u'DGDBTC': u'0.03092200', u'ICNETH': u'0.00217280', u'AEETH': u'0.00358100'}

This complicated things a lot for me. First of all, the key values were set up in trading pairs, and Binance has several “key currencies” that you can trade in. From the sample above, you can see that there were BNB pairs, ETH pairs, and BTC pairs. The first challenge was simply finding the pairs I needed — BTC pairs. The following code pulled this out nicely for me (thanks dictionary comprehension).

btc = {k: {"btc_price" : float(v)} for k, v in price.items() if "BTC" in k}

After I had that done, I needed a way to get rid of the “BTC” part of each key, so the keys of my price dictionary would match those of my balance dictionary. Again, dictionary comprehension came to my rescue…

c_price = { key.replace('BTC', ''): btc[key] for key in btc.keys() }

Once I simplified the balances I found a few other problems that would need to be addressed. First off, the BTC/USDT price had been reversed, and was showing the USD value of BTC instead of the fraction. I stored this number for later use though, as I would make calculating the USD value much easier. Furthermore, there wasn’t an entry for BTC/BTC, so this had to be added to the list along with the corrected USDT price. At this point I was starting to get the hang of dictionaries, so it was relatively painless:

c_price["USDT"]["btc_price"] = 1/c_price["USDT"]["btc_price"] c_price["BTC"] = {"btc_price" : 1}

The Combination Conundrum

This next part is what almost got me banned from StackOverflow. Now that I had nice, normalized keys… how was I supposed to combine them together? I couldn’t come up with the right way to ask the question, and real programmers were having none of my uninformed shenanigans. One user was my saving grace though, and they provided the solution for me in the end.

First they recommended I create a list with the keys I wanted:

keyset = set(simp_bal) & set(c_price)

Then I could use dictionary comprehension once again to iterate, and use the keyset list to input the key values:

combined = {key : {"balance" : simp_bal[key]["balance"], "btc_price" : c_price[key]["btc_price"]} for key in keyset}

Viola! I had combined everything together into a nice data structure that I could finally use to get my numbers. A simple for loop did the job nicely:

for key in combined:

combined[key]["btc_value"] = combined[key]["balance"]*combined[key]["btc_price"]

combined[key]["usd_value"] = combined[key]["btc_value"]*btcusd

The End?

Now as all software seems to be, once I had “finished” I realized I still had lots of work to do. Sure this would get me what I needed on one particular run, but I still would need to manually copy this data into a spreadsheet and figure out my opening and closing balances on a daily basis. Was I going to have to run this every day, or could I schedule it to run and populate a spreadsheet for me? Could I do this once every hour instead of every day (after all more data is always better right)? Of course the answer to all of this yes absolutely, but it also entails more programming... One day I’ll work out how to schedule this and pump out the data for me, but for now I’m just glad I can accurately pay my taxes.