Skip to content

nardew/bci-simulator

Repository files navigation

Bitpanda Crypto Index Simulator


Bitpanda Crypto Index (BCI) is an index product offered by the Austrian crypto broker bitpanda. The index consits of preselected crypto assets based on their actual market capitalization and gets recalculated (rebalanced) monthly to reflect shifts in the market. For full description read the prospectus.

This package serves to simulate BCI calculation, determine its composition and perform monthly rebalancing based on the historical input data in order to calculate yield and compare it with the returns resulting from holding the original assets without any rebalancing. This may help decide whether investing in the index is profitable or at least help compare performance with different parameters. If you are not interested in technical details but rather in overall BCI performance analysis, then read my article On the performance of Bitpanda Crypto Index.

The package tries to simulate BCI rules as much as possible but this cannot be achieved 100% due to certain steps not being explicitly described and bitpanda reserving rights to potentially adjust the rules fully at their sole discretion. Nevertheless, outcome of the simulation still provides valuable insight into mechanics of the index and its evolution over time.

This simulator is highly configurable but it comes with readymade configuration scripts for BCI5 and BCI10 indices (see bci5.sh and bci10.sh).

Calculation is performed based on the historical data provided in JSON format. The repository already contains a sample input file input_data.json which contains prices, market capitalizations and volumes of all cryptocurrencies since 01/01/2015 up to 01/11/2020 as published by CoinGecko.

To summarize the results, given current and past cryptomarket conditions investing into crypto indices at the moment is questionable. Unlike standard assets, crypto currencies are extremely correlated which defeats diversification. Furthermore, fat tail distribution implies that a few leading currencies drive performance of the index all the time. Based on several executions with various parameters you are often better off distributing initial funds into a few top currencies and sticking to them. Also, rebalancing fees are not negligible. More on this in the section with results. The index is advantageous in case of sudden uncorrelated crash of one of the top performers. If this is what you are trying to protect from, then index is the right thing for you.

Disclaimer: I am by no means affiliated with bitpanda (though I have been their customer for a couple of years) and this project was developed for personal purposes.

Results

As already indicated, BCI5 and BCI10's performance depends on the parameters and timeframe used. While it performed well when bought prior to the 2017 bull run, it underperformes when entered later. There are several factors responsible for this, mainly strong correlation between BTC and other leading currencies and dilution of the few top performing coins due to rebalancing despite their price outperforming other assets. In the following paragraphs I provide performance of indices executed with different parameters and comparison with a diverse portfolio without rebalancing. Each simulation starts with $1000 and applies 2% fee. All values are shown without fees.

Start date End date Index type Baseline closing value Index closing value Rebalancing fees
01/01/2015 03/11/2020 BCI5 $22,733.50 $60,169.04 $4,975.04
01/01/2015 03/11/2020 BCI10 $23,195.13 $47,634.00 $4,464.40
01/01/2016 03/11/2020 BCI5 $68,984.27 $78,541.85 $6,468.85
01/01/2016 03/11/2020 BCI10 $69,289.64 $64,954.50 $6,061.99
01/01/2017 03/11/2020 BCI5 $27,187.41 $31,187.39 $2,538.08
01/01/2017 03/11/2020 BCI10 $24,496.33 $27,106.29 $2,496.05
01/01/2018 03/11/2020 BCI5 $496.83 $400.19 $19.55
01/01/2018 03/11/2020 BCI10 $451.55 $352.14 $18.47
01/01/2019 03/11/2020 BCI5 $2,411.43 $2,215.78 $51.35
01/01/2019 03/11/2020 BCI10 $2,292.90 $2,111.58 $47.83
01/01/2020 03/11/2020 BCI5 $2,019.78 $1,971.94 $24.00
01/01/2020 03/11/2020 BCI10 $1,963.38 $1,936.60 $27.07

BCI5 BCI5 BCI5 BCI5 BCI5 BCI5 BCI10 BCI10 BCI10 BCI10 BCI10 BCI10

Example

I will demonstrate BCI5 simulation by executing bci5.sh for a period of two months with a single rebalancing and explain the output. Numbers are rounded for sake of readibility.

bci-simulator$ ./bci5.sh 
Bitpanda Crypto Index Simulator

Simulation period: 2020-10-01 - 2020-11-01

Initializing portfolio for $1000.0... // <= first the initial composition of index is calculated based on the available funds
	Top 5 assets: // <= returns top 5 cryptocurrencies according to their current capitalization
		('BTC', {'price': 10770.8813, 'cap': 196617081790.51, 'volume': 18558607662.68, 'volume_avg': 618620255.42})
		('ETH', {'price': 359.5989, 'cap': 39782583382.89, 'volume': 8037484324.98, 'volume_avg': 267916144.16})
		('XRP', {'price': 0.2413, 'cap': 10899063751.06, 'volume': 1349173492.01, 'volume_avg': 44972449.73})
		('BCH', {'price': 227.4442, 'cap': 4214806111.92, 'volume': 1951827124.33, 'volume_avg': 65060904.14})
		('DOT', {'price': 4.3471, 'cap': 3998481295.79, 'volume': 131549097.16, 'volume_avg': 4384969.90})
	Percentage allocation according to capitalization: // <= calculate weight for each currency based on their capitalization
		['BTC', 0.76]
		['ETH', 0.15]
		['XRP', 0.04]
		['BCH', 0.01]
		['DOT', 0.01]
	Capped percentage allocation: // <= cap allocation at 35% per currency
		['BTC', 0.35]
		['ETH', 0.35]
		['XRP', 0.17]
		['BCH', 0.06]
		['DOT', 0.06]
Portfolio allocation: {'BTC': 0.032495019554024604, 'ETH': 0.9733064186554691, 'XRP': 708.8565070308487, 'BCH': 0.29087729992403616, 'DOT': 14.437528683013289}

Rebalancing 2020-11-01 // <= rebalancing occurs (there is only one in this example)
	Primary filtering: // <= first filter out coins from the index if average running volume is less than $600k
		BTC: value $: 10,421,794,299,498.24 (average volume: 756373349.31, price: 13778.6376)
		ETH: value $: 115,873,709,651.78 (average volume: 300311869.12, price: 385.8445)
		XRP: value $: 10,692,339.96 (average volume: 44616541.87, price: 0.2396)
		BCH: value $: 17,892,998,542.04 (average volume: 68397980.41, price: 261.6012)
		DOT: value $: 12,692,380.64 (average volume: 3037895.39, price: 4.1780)
		Preserved coins: ['BTC', 'ETH', 'XRP', 'BCH', 'DOT']
	Secondary filtering: // <= perform another filtering for rest of the coins and limit $1M
		LINK: value $: 349,656,122.95 (average volume: 31148194.07, price: 11.2255)
		LTC: value $: 3,659,559,609.50 (average volume: 65691484.73, price: 55.7082)
		ADA: value $: 1,138,191.11 (average volume: 12255799.57, price: 0.0928)
		EOS: value $: 117,559,867.06 (average volume: 46529621.35, price: 2.5265)
		XMR: value $: 1,439,447,767.04 (average volume: 11403045.21, price: 126.2336)
	Candidate list: ['BTC', 'ETH', 'XRP', 'BCH', 'DOT', 'LINK', 'LTC', 'ADA', 'EOS', 'XMR']
	Sorted candidate list: // <= resulting list of candidates and their capitalizations
		BTC:	254,260,250,527.50
		ETH:	44,687,833,549.98
		XRP:	10,856,481,131.01
		BCH:	4,864,602,893.16
		LINK:	4,386,318,369.52
		DOT:	3,874,741,303.68
		LTC:	3,645,413,637.96
		ADA:	2,891,746,978.33
		EOS:	2,392,706,148.82
		XMR:	2,247,877,179.83
	Index composition: ['BTC', 'ETH', 'XRP', 'BCH', 'DOT'] // <= final set of currencies being part of the new index
	Percentage allocation according to capitalization:
		['BTC', 0.79]
		['ETH', 0.14]
		['XRP', 0.03]
		['BCH', 0.01]
		['DOT', 0.01]
	Capped percentage allocation:
		['BTC', 0.35]
		['ETH', 0.35]
		['XRP', 0.16]
		['BCH', 0.07]
		['DOT', 0.05]
	New portfolio allocation: {'BTC': 0.02869301922003787, 'ETH': 1.0246371882920944, 'XRP': 783.4015168786901, 'BCH': 0.3215731090962748, 'DOT': 16.03779352929636}
	Portfolio value: 1,129.57
	Portfolio updates: {'BTC': -0.003802000333986734, 'ETH': 0.051330769636625306, 'XRP': 74.54500984784147, 'BCH': 0.03069580917223863, 'DOT': 1.6002648462830695} // <= rebalancing BUY/SELL transactions
	Fee: 2.09 USD
	Original portfolio value: 1,129.57 // <= portfolio value for holding the original index without rebalancing (in case of a single rebalancing the values are naturally the same)

Overall fee: 2.09

Implemented BCI rules

To verify the correct methodology was used to simulate BCI indices, hereunder the implemented rebalancing rules are outlined. In particular, BCI5 is used for illustration.

  • put all currencies from the current index with average daily traded value (volume*price) >= $600,000 over past 30 days into the list of index candidates
  • put remaining currencies ordered by market capitalization with average daily traded value >= $1,000,000 over past 30 days into the list of index candidates
  • put top three currencies from the candidate list into the final index
  • put additional two currencies from the candidate list into the final index such that currencies from the existing index ranked up to the 7th place take priority
  • normalize weights according to the market capitalization
  • cap allocation to 35% and renormalize (the step can be performed multiple times)

Parameters

If you want to try your own simulation with custom parameters, below description of configurable arguments may come in handy.

Parameter Description
--index Size of the index (e.g. 5 for BCI5, 10 for BCI10).
--rebalancing Rebalancing period in days (e.g. 30 for index to get rebalanced every 30 days). If set to 0, then index will be rebalanced on the first day of every month.
--fee Transaction fees applicable to rebalanced amounts.
--max-allocation Maximum percentage allocation of an asset in the index (e.g. 0.35, i.e. 35%, for BCI5).
--volume-period Number of days used to calculate running average daily volume. 30 days by default.
--primary-volume-filter Minimal USD amount (running average volume * price) used to filter out currencies from the existing index when building a new one, e.g. 600000 for BCI5. If overall traded amount of currency from the existing index is less than this limit, it is not proposed for inclusion in the next index.
--secondary-volume-filter Same as --primary-volume-filter but for currencies not being part of the current index, e.g. 1000000 for BCI5.
--candidates Number of top performing currencies considered for the selection into the index (after passing all filtering rules), e.g. 10 for BCI5 .
--primary-candidates Number of top performing currencies from the candidate list which are immediately included in the index, e.g. 3 for BCI5.
--secondary-candidates Maximal position in the sorted candidate list which gives priority to currencies from the current index for inclusion in the next one, e.g. 7 for BCI5.
--funds Initial funds to start with.
--input-file Path to a file with input historical data.
--start-date Starting date of the simulation. If not provided, the first date from the input data is used.
--end-date Ending date of the simulation. If not provided, the last date from the input data is used.
--show-graph Plot graph at the end of simulation.
--save-graph Save graph into the file.

Support

If you like the package and you feel like you want to support its further development, then it will be of great help and most appreciated if you:

  • file bugs, proposals, pull requests, ...
  • spread the word
  • donate an arbitrary tip
    • BTC: 3GJPT6H6WeuTWR2KwDSEN5qyJq95LEErzf
    • ETH: 0xC7d8673Ee1B01f6F10e40aA416a1b0A746eaBe68