Portfolio Optimization with Stocks and Cryptocurrencies

Combined Cryptofolios - What Markowitz (Optimization) would have told us about Cryptocurrencies in 2018

Version 1 - Last Update: 2018-07-18

Easy access to the R code of this tutorial

The ID of this tutorial is 1 - after installing the package financeR and loading it with library(financeR) you may open the appropriate R code by typing financeR::tutorial(1) on the R shell. Please read the introduction for information about how to install the tutorial package.

Click here to browse back to the list of tutorials.

Portfolio Optimization with Stocks and Cryptocurrencies

Combined Cryptofolios - What Markowitz (Optimization) would have told us about Cryptocurrencies in 2018.

This post has been exclusively created for the Interactive Brokers Quant Blog on request. You can find it here on Finance with R in case of updates and for further discussion.


So there’s still a heavy buzz around cryptocurrenices - as with every oppotunity which offers a convenient way to get rich quick. There’s a reason why one of the pressing questions in the Cryptocommunity is: “When Lambo?”. On a more serious note there is the discussion going on to which asset class cryptos belong. Here we use the a set of parsed and pre-processed stock and cryptocurrency data to combine cryptos with data from (almost) all stocks from the S&P 100 index to check whether cryptos are given a chance by a (plain) Markowitz optimization.


First off, we require two libraries, namely quantmod for time series processing and tseries for a basic Markowitz portfolio optimization function.

### Libraries


Next, we load return data of seven cryptocurrencies and nearly all stocks from the S&P 100 index. This data set has been exclusively prepared for this tutorial and contains daily return values from the beginning of 2017 until the end of the first quarter of 2018.

### Data

After loading the data set from Amazon S3 we rename the scenario set appropriately, parse a character vector of all ticker symbols and count the amount of cryptos. Those are sorted alphabetically and ZEC is the last one.

scenario.set <- ib.crypto.stock
symbols <- names(scenario.set)
n_cryptos <- which(symbols == "ZEC")

Let’s check which cryptos are in our asset universe under consideration for a subsequent portfolio optimization:

## [1] "BTC"  "DASH" "ETC"  "ETH"  "LTC"  "XRP"  "ZEC"

Static Portfolio Optimization

Let’s start with computing a basic Markowitz portfolio using all available data from 2017:

### Static Portfolio Optimization
timeframe <- "2017"
portfolio <- round(portfolio.optim(scenario.set[timeframe])$pw, 2)

Now let’s check which assets are in our optimized portfolio, i.e. by extracting all assets whose weights are larger than 0. We do this for all assets as well as solely for cryptos. First we check the ticker symbols and then the weights respectively.

symbols[which(portfolio > 0)]
##  [1] "ETH"  "AAPL" "ABBV" "ABT"  "ALL"  "AMZN" "AXP"  "BA"   "CAT"  "CVX" 
## [11] "FOX"  "HD"   "JNJ"  "KO"   "MCD"  "MO"   "NEE"  "ORCL" "PG"   "RTN" 
## [21] "TWX"  "UNH"  "WMT"
portfolio[which(portfolio > 0)]
##  [1] 0.01 0.03 0.05 0.06 0.05 0.03 0.03 0.09 0.01 0.03 0.01 0.05 0.01 0.05
## [15] 0.08 0.01 0.17 0.01 0.05 0.03 0.03 0.03 0.07
symbols[which(portfolio[1:n_cryptos] > 0)]
## [1] "ETH"
portfolio[which(portfolio[1:n_cryptos] > 0)]
## [1] 0.01

We may also draw a pie chart of the portfolio, but in this case we omit all assets from the portfolio whose weight is lower than a certain \(\varepsilon\) which is set to 3% here.

eps <- 0.03
pie(portfolio[which(portfolio > eps)], 
    labels=symbols[which(portfolio > eps)],
    col=rainbow(length(which(portfolio > eps))))

Many assets in this allocation are well known to everyone who already computed Markowitz-optimal portfolios since the last financial crisis, e.g. KO, MCD, JNJ and the likes. However, it is interesting that a plain Markowitz approach does not exclude cryptos at all but rather includes them at a sensible low level, i.e. at 1%.

Rolling Horizon Portfolio Optimization

So we have already seen that a plain Markowitz optimization allocates only 1% of the budget into cryptos based on data from 2017 - the only one that is selected is ETH. We will expand the analysis to a rolling horizon test over the whole first quarter of 2018. The window size is set to one year.

### Rolling Horizon Portfolio Optimization
n_total <- nrow(scenario.set)
n_2017 <- nrow(scenario.set["2017"])

crypto_sum <- numeric()
portfolios <- matrix(ncol=n_cryptos, nrow=0)
for(current.pos in (n_2017+1):(n_total-1)) {
  portfolio <- round(portfolio.optim(scenario.set[(current.pos-n_2017):(current.pos), ])$pw, 2)
  portfolios <- rbind(portfolios, portfolio[1:n_cryptos])
  crypto_sum <- c(crypto_sum, sum(portfolio[1:n_cryptos]))

From this rolling horizon we store two different data sets for closer inspection. First, we store the cryptocurrency allocation into a matrix portfolios which we will convert to a data frame below - along with an initial inspection:

df.crypto.portfolio <- data.frame(portfolios)
names(df.crypto.portfolio) <- names(scenario.set[,1:n_cryptos])
## 1   0    0   0 0.01   0   0   0
## 2   0    0   0 0.01   0   0   0
## 3   0    0   0 0.01   0   0   0
## 4   0    0   0 0.01   0   0   0
## 5   0    0   0 0.01   0   0   0
## 6   0    0   0 0.01   0   0   0

Furthermore we store the sum of the percentage of the allocated budget to cryptos into a vector crypto_sum and plot this value for each day of our rolling horizon test.

plot(xts(crypto_sum, order.by=index(scenario.set[(n_2017+1):(n_total-1)])),
     ylim=c(0,0.03), main="Crypto Weight in Portfolio")

We see that this sensible Markowitz approach invested 1% into cryptos most of the time - only on a few days 2% are allocated to this asset category. The only two cryptos chosen were BTC and ETH. At the beginning of the year 2018 mainly ETH was chosen and towards the end of the quarter ETH was replaced with BTC. On those days were 2% of the budget were allocated to cryptos both ETH and BTC were added to the portfolio with 1% equally.

Final remark

Of course there are lots of possible extensions to this basic framework. Feel free to get back to us any time if you have any questions, comments and/or suggestions.