require(tidyverse)
require(tidyquant)
require(fPortfolio)
require(PerformanceAnalytics)
require(tbl2xts)
require(ggthemes)
require(timetk)
require(PortfolioAnalytics)
require(kableExtra)
require(jtools)
require(FinTS)
require(rugarch)
require(readxl)





Crypto MPT

Using Modern Portfolio Theory for Cryptocurrencies


By: Mike Margolis







Intro

In this project we will be applying Modern Portfolio Theory to cryptocurrencies. We will be using the Markowitz Optimal Portfolio solution to determine portfolio weights for various cryptocurrencies. These portfolios will take returns and risk into consideration. We read in the data from a Kagel Dataset. The data for each of the coins used in this research can be downloaded here link

BTC_ETH <- read_excel("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/BTC-ETH.xlsx")

To simplify the Markowitz optimal portfolio solution we will look at two coins Bitcoin (BTC) and Ethereum (ETH) to start. We first will observe the mean and standard deviation for each coins monthly returns, using the logged closed price for each coin. We will then calculate the correlation matrix between the two coins to see how they are correlated.

BE_returns <- BTC_ETH %>%
  group_by(Symbol) %>%
  tq_transmute(
    select = Close,
    mutate_fun = periodReturn,
    period = "monthly",
    type = "log",
    col_rename = "monthly.returns"
  )
BE_returns %>%
  group_by(Symbol) %>%
  summarise(mean = mean(monthly.returns),
            st.dev = sd(monthly.returns)) %>%
  kable(format = "html",
        table.attr = "style='width:30%;'",
        caption = "Mean and standard deviation of returns") %>%
  kableExtra::kable_styling()
Mean and standard deviation of returns
Symbol mean st.dev
BTC 0.0677292 0.2173964
ETH 0.1115916 0.3853444
BE_Crypto <- BE_returns %>%
  tbl_xts(cols_to_xts = monthly.returns, spread_by = Symbol)

round(cor(BE_Crypto,BE_Crypto),digits=3) %>%
  kable(format= "html",
        table.attr = "style='width:30%;'",
        caption = "Correlation matrix bewtween BTC and ETH") %>%
  kableExtra::kable_styling()
Correlation matrix bewtween BTC and ETH
BTC ETH
BTC 1.000 0.455
ETH 0.455 1.000

Markowitz Frontier

Now we plot the Markowitz frontier for these two assets where we have assumed that the annualized 1-month risk-free rate is 0.05%. In both plots, the minimum variance portfolio is shown as the red dot. The optimal portfolio in each plot has the highest expected excess return per unit of risk that we can obtain.

In the first plot, BTC is the dark blue diamond, ETH is the cyan diamond, and the optimal portfolio is the blue triangle. All of the Monte Carlo generated portfolios with \(w \in [0,1]\) lie on the frontier.

BE_Return <- as.timeSeries(BE_Crypto)
tgSpec <- portfolioSpec()
setRiskFreeRate(tgSpec) <- .05 / 1200
tgPortfolio <- tangencyPortfolio(data = BE_Return,
                                 spec = tgSpec,
                                 constraints = "LongOnly")
print(tgPortfolio)
## 
## Title:
##  MV Tangency Portfolio 
##  Estimator:         covEstimator 
##  Solver:            solveRquadprog 
##  Optimize:          minRisk 
##  Constraints:       LongOnly 
## 
## Portfolio Weights:
##   BTC   ETH 
## 0.683 0.317 
## 
## Covariance Risk Budgets:
##    BTC    ETH 
## 0.5666 0.4334 
## 
## Target Returns and Risks:
##   mean    Cov   CVaR    VaR 
## 0.0816 0.2313 0.4279 0.3047 
## 
## Description:
##  Wed Aug 10 19:09:46 2022 by user: mikem
plot(frontier, which = c(1, 2, 3, 4, 7)) # select 1 and 3

In this plot we allow for short-selling in our portfolio. We can not hedge one coin for the other. IN this plot BTC is the solid red dot, and ETH is the open yellow dot, and the optimal portfolio is the open cyan dot.

shortSpec <- portfolioSpec()
setNFrontierPoints(shortSpec) <- 20
setSolver(shortSpec) <- "solveRshortExact"
shortFrontier <- portfolioFrontier(data = BE_Return,
                                   spec = shortSpec,
                                   constraints = "Short")
print(shortFrontier)
## 
## Title:
##  MV Portfolio Frontier 
##  Estimator:         covEstimator 
##  Solver:            solveRshortExact 
##  Optimize:          minRisk 
##  Constraints:       Short 
##  Portfolio Points:  5 of 20 
## 
## Portfolio Weights:
##       BTC    ETH
## 1  1.0000 0.0000
## 5  0.7895 0.2105
## 10 0.5263 0.4737
## 15 0.2632 0.7368
## 20 0.0000 1.0000
## 
## Covariance Risk Budgets:
##       BTC    ETH
## 1  1.0000 0.0000
## 5  0.7348 0.2652
## 10 0.3454 0.6546
## 15 0.1081 0.8919
## 20 0.0000 1.0000
## 
## Target Returns and Risks:
##      mean    Cov   CVaR    VaR
## 1  0.0677 0.2174 0.4122 0.3257
## 5  0.0770 0.2207 0.4168 0.3333
## 10 0.0885 0.2558 0.4526 0.2750
## 15 0.1000 0.3141 0.5303 0.4421
## 20 0.1116 0.3853 0.6203 0.4981
## 
## Description:
##  Wed Aug 10 19:09:47 2022 by user: mikem
tailoredFrontierPlot(object = shortFrontier,
                     mText = "MV Portfolio - Short Constraints",
                     risk = "Cov")

The optimal portfolio weights are:
getWeights(tp_BE)  %>%
  kable(format= "html",
        table.attr = "style='width:30%;'",
        caption = "Optimal Portflio Weights") %>%
  kableExtra::kable_styling()
Optimal Portflio Weights
x
BTC 0.6829908
ETH 0.3170092

From the first graph we find interesting results. If we go all in on BTC (dark blue diamond), the return is lower than the minimum variance portfolio (red dot), but the risk is only slightly higher. Where as going all in on ETH is 10-20 percentage points more risky and the returns are only .4 percentage points higher. The blue triangle is the optimal portfolio it says go about 70% in BTC and about 30% in ETH. This is daily data and the returns are calculated monthly, the data we have is form January 2018 to now. Due to the volatility of cryptocurrencies results from this analysis changes slightly after each iteration.


Analyzing Multiple Coins: Optimal Portfolio Weights

Lets see what an optimal portfolio would look like with a lot of coins. Some popular coins such as (Solana (SOL), or Polkadot (DOT)) don’t have a lot of historical data from this Kaggle dataset. We have 9 coins in the analysis and the descriptions of each coin or below. We have daily data for these coins from January 2018 to now. We will use the given close price of each coin for the analysis.

BNB <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx", sheet = 1)
ADA <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =2)
LINK <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =3)
LTC <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =4)
XRP <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =5)
XLM <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =6)
TRX <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =7)
BTC <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =8)
ETH <- read_xlsx("C:/Users/mikem/OneDrive/Desktop/Crypto RMD/ALT_coins.xlsx",sheet =9)
Alt_Coins <-BTC %>% full_join(BNB)
Alt_Coins <-Alt_Coins %>% full_join(ADA)
Alt_Coins <-Alt_Coins %>% full_join(LINK)
Alt_Coins <-Alt_Coins %>% full_join(LTC)
Alt_Coins <-Alt_Coins %>% full_join(XRP)
Alt_Coins <-Alt_Coins %>% full_join(XLM)
Alt_Coins <-Alt_Coins %>% full_join(TRX)
Alt_Coins <-Alt_Coins %>% full_join(ETH)

Alt_Coins <- subset(Alt_Coins, Date > "2018-02-02")

What are these coins and what are they used for?

Descriptions and Definitions are pulled in-part from Investopedia
ADA
  • The native token of Cardano. Cardano’s main applications are in identity management and trace-ability. The former application can be used to streamline and simplify processes that require the collection of data from multiple sources. The latter application can be used to track and audit a product’s manufacturing processes from provenance to finished goods and, potentially, eliminate the market for counterfeit goods.
BNB
  • The native token of the Binance block chain, initally based on the Ethereum network. Binance was created as a utility token for discounted trading fees in 2017, but its uses have expanded to numerous applications, including payments for transaction fees (on the Binance Chain), travel bookings accommodations (at sites such as TravelbyBit, Trip.io, and Travala.com), entertainment purposes (virtual gifts, card packs, lotteries), online services, and financial services (take out a loan at ETHLend or make investments at Moeda).
BTC
  • BitCoin is Bitcoin.
ETH
  • Ethereum is Ethereum. Ethereum enables the deployment of smart contracts and decentralized applications (dApps) to be built and run without any downtime, fraud, control, or interference from a third party.7 Ethereum comes complete with its own programming language (Solidity) that runs on a blockchain, enabling developers to build and run distributed applications.
LTC
  • Litecoin (LTC) is a cryptocurrency created from a fork in the Bitcoin blockchain in 2011. It was initially designed to address the developer’s concerns that Bitcoin was becoming too centrally controlled, and to make it more difficult for large scale mining firms to gain the upper hand in mining. While eventually unsuccessful in preventing enterprise miners from taking over the lion’s share of Litecoin mining, the cryptocurrency has reworked itself into a mineable coin and a peer-to-peer payment system. Litecoin has a faster transaction processing time compared to Bitcoin.
XRP
  • XRP is a “bridge asset” or an asset that businesses and financial institutions can use as a bridge transfer between two different fiat currencies. In such a scenario, the financial institution can simply purchase an equivalent amount of XRP and send it through Ripple’s network. Ripple refers to it as “third-party liquidity provisioning” and states that it is ideal for banks that do not have a corresponding relationship with each other. XRP is currently facing a lawsuit from the SEC. Personally I believe all data for XRP should have an (*) next to it due to the potential/real value of the coin will be revealed once the lawsuit reaches a conclusion. A situational forecast could help determine the future price, situation 1 Ripple(XRP) wins the suit, the price will probably sky rocket. Situation 2 the SEC wins the lawsuit and XRP’s price will most likely fall tremendously.
XLM
  • The term Stellar cryptocurrency refers to a digital or virtual currency developed by Stellar Development Foundation. The organization’s currency, which is called the lumen, is traded under the symbol XLM on various cryptocurrency exchanges. Lumens can be used by traders on the Stellar network, which is a blockchain-based distributed ledger network that connects banks, payments systems, and people to facilitate low-cost, cross-asset transfers of value, including payments. Stellar’s primary focus is on developing economies in the areas of remittances and bank loans to those who are outside of the scope of the banking services. Stellar doesn’t charge individuals or institutions for using the network. Stellar supports a distributed exchange mode. This allows users to send payments in specific currencies even though they may hold credits in another, while the network automatically performs the forex conversion. The receiver can withdraw their currency equivalent through a partner institute like a bank. As a cross-border transfer and payment system that connects financial entities, Stellar aims to significantly reduce transaction costs and time lags. While Stellar works just like technologies like Bitcoin, its key distinguishing feature is its consensus protocol.
TRX
  • Tron is a blockchain-based decentralized digital platform with its own cryptocurrency, called Tronix or TRX. Founded in 2017 by a Singapore non-profit organization, the Tron Foundation, Tron aims to host a global entertainment system for the cost-effective sharing of digital content.Tron uses the features of the blockchain and peer-to-peer (P2P) network technology to eliminate the middleman and allow content creators to sell their work directly to consumers. Software developers use the Solidity programming language to create apps that are hosted on the Tron platform.

Below is the plot for the daily logged close values for each coin in our analysis.
Alt_Coins %>%
  ggplot(aes(x = Date, y = log(Close), color = Symbol)) +
  geom_line(size = 1) +
  labs(
    title = "Logged Daily Crypto Prices",
    x = "",
    y = "Logged Close Prices",
    color = ""
  ) 

Alt_returns_monthly <- Alt_Coins %>% 
  group_by(Symbol) %>%
  tq_transmute(
    select = Close,
    mutate_fun = periodReturn,
    period = "monthly",
    type = "log",
    col_rename = "Rm"
  ) 

Alt_returns_wide <- Alt_returns_monthly %>% 
  spread(key = Symbol, value = Rm) %>%
  tk_xts(date_var = Date) 

Correlation Matrix for the 9 Coins:
round(cor(Returns_Alt_Coins,Returns_Alt_Coins),digits=3) %>%
  kable(format= "html",
        table.attr = "style='width:30%;'",
        caption = "Correlation Matrix") %>%
  kableExtra::kable_styling()
Correlation Matrix
BTC BNB ADA LINK LTC XRP XLM TRX ETH
BTC 1.000 0.641 0.607 0.646 0.848 0.435 0.625 0.627 0.795
BNB 0.641 1.000 0.654 0.374 0.680 0.378 0.472 0.602 0.573
ADA 0.607 0.654 1.000 0.542 0.659 0.502 0.759 0.617 0.721
LINK 0.646 0.374 0.542 1.000 0.653 0.558 0.618 0.608 0.712
LTC 0.848 0.680 0.659 0.653 1.000 0.559 0.657 0.653 0.815
XRP 0.435 0.378 0.502 0.558 0.559 1.000 0.810 0.592 0.661
XLM 0.625 0.472 0.759 0.618 0.657 0.810 1.000 0.627 0.759
TRX 0.627 0.602 0.617 0.608 0.653 0.592 0.627 1.000 0.678
ETH 0.795 0.573 0.721 0.712 0.815 0.661 0.759 0.678 1.000

Compute Sharpe ratios for each asset with an average risk-free monthly rate of 0.5%
  SharpeRatio(Alt_returns_wide, Rf = .005, p = 0.95, digits = 4, FUN = "StdDev") %>% 
  kable(format = "html", table.attr = "style='width:50%;'",
      caption = "Asset Sharpe Ratios") %>% 
  kableExtra::kable_styling()
Asset Sharpe Ratios
ADA BNB BTC ETH LINK LTC TRX XLM XRP
StdDev Sharpe (Rf=0.5%, p=95%): -0.0121942 0.1600751 0.0477923 -0.0043282 0.1062672 -0.095632 0.0089347 -0.0946198 -0.0661072

Very interesting Sharp Ratios. Binance Coin and ChainLink stands out.


Plot of the Markowitz Optimal Portfolio

# get optimal portfolio
rm(opt,port_spec)
data <- Alt_returns_wide
port_spec <- portfolio.spec(colnames(data))
port_spec <- add.constraint(portfolio = port_spec, type= "long_only")
port_spec <- add.constraint(portfolio = port_spec, type= "full_investment")
port_spec <- add.objective(portfolio = port_spec,
                           type = "risk",
                           name = "StdDev")
port_spec <- add.objective(portfolio = port_spec,
                           type = "return",
                           name = "mean")
opt <- optimize.portfolio(data, portfolio = port_spec,
                          optimize_method = "random",
                          search_size = 10000,
                          trace=TRUE)
chart.RiskReward(opt, risk.col = "StdDev", return.col = "mean",
                 chart.assets = TRUE)

extractWeights(opt) %>% 
  kable(format = "html", table.attr = "style='width:30%;'",
      caption = "Optimal Long-Only Portfolio Weights") %>% 
  kableExtra::kable_styling()
Optimal Long-Only Portfolio Weights
x
ADA 0.020
BNB 0.166
BTC 0.752
ETH 0.000
LINK 0.002
LTC 0.002
TRX 0.050
XLM 0.000
XRP 0.008

Right off the bat the interpretation of this output is, regardless of investment amount: put ~69% in BTC, 16% in BNB, 10% in ETH, etc.

A lack of ETH in the portfolio doesn’t surprise me. The coins are the two leaders in the market and their returns and risks are definitely correlated/coupled. The program chooses one or the other and the lower risk of BTC with higher predicted returns (marginally higher Sharpe Ratio) says if you have to chose one (and apparently you should) chose BTC. If you place equal weight in each coin a crash in one coin will lead to a crash in the other. Markowitz theorized that we should be off-setting risk with other assets that are not correlated with the returns of other assets in your portfolio. The return may be lower, however, the loss of risk outweighs this issue. Binance is fairly stable so some inclusion is expected but the amount is still shocking. This is probably due to its higher Sharpe Ratio than ETH, however it should be correlated with ETH which is correlated with BTC. But math is math and if we go on the daily data based on “close” prices this is what the optimal portfolio looks like. XRP and ADA show up as well which is interesting since XRP is currently in a lawsuit and ADA is a coin with a lot of “meme” propulsion around it.

Lets see what happens when we leave BTC out of the portfolio. The Sharpe Ratios don’t change but the optimal weights for the portfolio will change.

Alt_Coins_2 <- subset(Alt_Coins, Symbol != "BTC")
CryptoALT_returns_monthly <- Alt_Coins_2 %>%
  group_by(Symbol) %>%
  tq_transmute(
    select = Close,
    mutate_fun = periodReturn,
    period = "monthly",
    type = "log",
    col_rename = "Rm"
  )
CryptoALT_returns_wide <- CryptoALT_returns_monthly %>% 
  spread(key = Symbol, value = Rm) %>%
  tk_xts(date_var = date)
# get optimal portfolio
rm(opt,port_spec)
data <- CryptoALT_returns_wide
port_spec <- portfolio.spec(colnames(data))
port_spec <- add.constraint(portfolio = port_spec, type= "long_only")
port_spec <- add.constraint(portfolio = port_spec, type= "full_investment")
port_spec <- add.objective(portfolio = port_spec,
                           type = "risk",
                           name = "StdDev")
port_spec <- add.objective(portfolio = port_spec,
                           type = "return",
                           name = "mean")
optALT <- optimize.portfolio(data, portfolio = port_spec,
                          optimize_method = "random",
                          search_size = 10000,
                          trace=TRUE)
chart.RiskReward(optALT, risk.col = "StdDev", return.col = "mean",
                 chart.assets = TRUE)

extractWeights(optALT) %>% 
  kable(format = "html", table.attr = "style='width:30%;'",
      caption = "Optimal Long-Only Portfolio Weights") %>% 
  kableExtra::kable_styling()
Optimal Long-Only Portfolio Weights
x
ADA 0.012
BNB 0.444
ETH 0.098
LINK 0.104
LTC 0.114
TRX 0.214
XLM 0.010
XRP 0.004

With the behemoth that is BTC out of the way we see other coins start to flourish. Binance Coin (BNB), Ethereum (ETH) and ChainLink (LINK) take the spot light. A optimal Markowitz portfolio will opt to not include two coins that have highly correlated returns due to correlated risk. If two coins move up together they also fall together. We would opt to include coins with lower returns to hedge risk of choosing coins that have correlated risk.The results of this analysis will change slightly as more daily data comes in and the market these coins operate in is highly volatile.