Cryptocurrencies have been a hot topic for years and for good reason. To some, they are a black box, to others they are the inevitable future of Finance. Needless to say, anyone who spends at least some of their time and money investing in stocks and other assets will have thought about investing in this novel asset class in recent years.
In this article, I am going to analyse the impact of including cryptocurrencies in a portfolio of traditional stocks from a mean-variance perspective. The objective of this analysis is not to give investment advice or make predictions for the future but rather to demonstrate why considering including an alternative asset class, such as cryptocurrencies, in a portfolio along with stocks could be a worthwhile exercise, regardless of your opinion of them.
If you are interested in cryptocurrencies, finance theory, Investing or programming using Python, this article is for you. I will dive into the underlying finance theory and explain how to perform mean-variance analysis using Python. While these are complex mathematical topics I will mainly focus on the underlying logic because too many formulas can make anything seem more complex than it needs to be.
The article is structured as follows:
- Brief Finance recap
- Explaining Mean-Variance Analysis
- Applying Mean-Variance Analysis to stocks
- Computing the Efficient Frontier using Python
- Computing the Capital Market Line using Python
- Adding cryptocurrencies to the portfolio and investigating the result
- Comparing the effect of cryptocurrencies to that of other alternative assets
- Concluding comments
Part 1 of the article covers points 1 through 5. You can find the part that introduces cryptocurrencies into the portfolio here:
Some important measures in finance
Two of the most important and commonly used metrics when referring to stock prices (and in general any asset prices) are return and volatility.
By return we usually mean the rate of return, and the most common forms are simple rate of return and logarithmic return. For information on the differences between the two have a look at this blog post. For now, think of returns as the percentage change in the stock price over a given time interval, i.e. if a certain stock price is at $100 today and jumps to $105 tomorrow, the return (simple rate of return) is 5%.
By volatility we refer to the standard deviation of the return, i.e. the square root of the variance of the return. The variance is a measure of how spread out the data set of returns is. Because the variance is calculated using squared deviations it does not have the same unit of measurement as the original observations. Taking the square root, i.e. computing the standard deviation, converts this measure into the same units, thereby making the measure of spread easier to interpret and compare across data sets. More spread means more fluctuations up and down, which is why in finance the standard deviation is often the measure of risk. More on standard deviation here.
Investors often look at average returns and risk to compare stocks and make investment decisions. Stocks, in general, tend to be relatively volatile compared to other assets like bonds and one way to decrease some of the risk of investing in stocks is to invest in more than one stock. This is the practical implementation of the idiom "Don’t put all your eggs in one basket" and is referred to as diversification.
The intuition behind diversifying, or reducing overall portfolio risk by investing in more than one stock, is to choose stocks whose prices, and therefore returns, do not tend to move together. That way, if one goes down, the other likely stays the same or goes up. You can think about this as a sort of "balancing out". Including stocks that historically have not moved together leads to a more balanced portfolio.
When we analyse a portfolio made up of multiple stocks we want to be able to compute the expected return and variance of the overall portfolio rather than that of the individual stocks. In order to do this, we need to know one of two measures about the stocks included in the portfolio, in addition to their average return and standard deviation: their covariance or correlation.
Covariance and correlation are measures of relationship and dependency between two variables. Essentially, correlation is just a standardised version of the covariance, which measures both the strength and direction of the linear relationship between two variables. The possible values for a correlation are between -1 and 1. A positive correlation implies that two variables tend to move in the same direction, a negative correlation implies that two variables tend to move in opposite directions and a correlation of zero implies no relationship between the variables. Hence, for portfolio diversification one would be best advised to combine stocks whose returns have low or negative correlations (think about the "balancing out" analogy).
What calculating the expected return and variance for a portfolio looks like mathematically is beyond the scope of this introduction but this blog post offers a great explanation using a two asset portfolio. All that we need to know for now is that the expected return of the total portfolio is the weighted average of the expected returns of the individual stocks in the portfolio. The expected variance of the portfolio is a bit more complicated but essentially is a product of the variance of the individual stocks, their respective weights in the overall portfolio and the correlation between each pair of stocks.
What is Mean-Variance Analysis?
Mean-Variance Analysis, often referred to as Modern Portfolio Theory (MPT) is a theory about portfolio construction that was first developed by Harry Markowitz in 1952, later earning him the Nobel prize in Economics. The main idea behind the theory is that by tweaking the weights of individual assets in a portfolio it is possible to construct optimal portfolios, which offer the maximum possible expected return for a given level of risk. One of the key insights of MPT is that an individual asset’s return and volatility should not be assessed by itself, but rather by how it contributes to a portfolio’s overall return and volatility.
The optimal portfolios, i.e. the portfolios that maximise the expected return for a given level of risk or minimise the expected volatility for a given level of return, can be plotted on a graph. The line that connects the optimal portfolios will be an upward sloping hyperbola, which is called the Efficient Frontier. It is called "efficient" because the portfolios that lie on it provide the highest expected return for a given level of risk.
Let’s see what applying mean-variance analysis using Python looks like. For the following section a basic understanding of Python is assumed but even without it the underlying logic and conclusions will be clear (I highly recommend googling unknown Python terms for those that really want to follow along).
Applying Mean-Variance Analysis to stocks
Before we can start the analysis, we need to import stock price data into Python. Thankfully, Pandas has a sub package called pandas-datareader that allows easy extraction of data from a wide range of Internet sources into a pandas DataFrame. I will extract stock price data from Yahoo Finance. But how do we decide what stock price data to extract?
In this example I focused on 30 stocks included in the S&P 500. For simplicity, I pretended to be an amateur investor who knows that in order to have a well-diversified portfolio it is recommended to have between 15 and 30 stocks in the portfolio. Because I also know that stocks from different industries tend to be less correlated than stocks from the same industry I tried to construct the portfolio so that the stocks included in it are from many different industries. Because I am a bit lazy, I just looked up the components of the S&P 500, found a list that is sorted by weight, went through the list and picked stocks from different industries until I had a list of 30. That is by no means a good strategy for selecting stocks and inherently leads to survivorship bias in our sample but for simplicity’s sake it is good enough (it also resembles what a lot of people would consider a decently diversified portfolio).
In what follows I will include the most important blocks of code and visualisations. The full notebook can be found here.
Here is the code that extracts the stock price data from Yahoo Finance:
This extraction provides almost five years of stock price data. The reason why I chose August 6, 2015 as the start date will become clear later in the analysis. Before I move on to Mean-Variance Analysis let’s briefly look at the evolution of the stock prices included in this analysis. Plotting the time series stock price data in a normalised fashion results in the following plot:
As the time series shows, some stocks such as Amazon have made impressive gains over the five-year period. It also appears as though the spread of COVID-19 led to drastic drops in all of the stock prices in early 2020. Another observation is that despite having different trajectories the stock prices tend to move together, implying that they are positively correlated. More on this later.
As I mentioned previously, the main idea in MPT revolves around finding the weights of the stocks in a portfolio that lead to the highest possible expected return for a given level of volatility. But how do we figure out what these "optimal" weights are?
Before I continue I want to introduce two formulas that will be fundamental for the analysis (I know I said I would mainly focus on the underlying logic but these formulas are essential for understanding the code that follows). For both of these formulas and for all computations that follow we assume that only long positions are allowed (i.e. only buying stocks, not selling them) and that the positions add up to 100% (i.e. weights add up to 1). The first one is the formula for the expected return of a portfolio:
In the above formula, historical mean returns are assumed to be the best estimator for expected returns and are assumed to be normally distributed. The final equation is the mathematical representation of the fact that the expected return of the portfolio is the weighted average of the expected return of the individual assets, in form of vector multiplication.
The second essential formula is that of the expected variance of a portfolio:
The final equation in the above formula is simply the transpose of the vector of the asset weights multiplied by the product of the covariance matrix and the vector of asset weights.
Translated into Python, both of these formulas boil down to one line of code which I will show shortly. Back to the weights of the assets.
Because at the moment we do not know what the "optimal" asset weights are, a good place to start is to run a Monte Carlo simulation in which we randomly assign weights between 0 and 1 (in a way that the weights add up to 1). We then compute the expected return and variance of the resulting portfolio, repeat these steps however many times we deem necessary and plot the results.
I defined a function that takes as its inputs a DataFrame of daily returns and a number N, which tells the function how many simulations to run. It is important to note that the "annualisation" of returns and (co-)variances are computed under the assumption that returns are independent of each other and identically distributed:
When calling that function with the daily log returns of the 30 stocks and 5,000 simulations and plotting the results, we get the following scatter plot:
In the scatter plot, I coloured the points according to their Sharpe ratio. The Sharpe ratio is one of the most common risk-return measures in finance. It is defined as the excess return (i.e. return in excess of the risk-free rate) of an investment divided by the volatility of that investment. Computing the Sharpe ratio makes it easy to compare investments with different risk-return profiles. Generally speaking, the higher the Sharpe ratio the better. In this project, I assume a risk-free rate of 1%.
In the next section I will explain how we get from a scatter of randomly generated portfolios to computing the efficient frontier.
Computing the Efficient Frontier using Python
As I mentioned earlier, the efficient frontier is comprised of all optimal portfolios that can be formed given the stocks available to form those portfolios. As the name "optimal portfolio" suggests, finding the weights that make up these portfolios boils down to an optimisation problem. But what do we optimise?
Let’s think about that for a second. We want to find the portfolios with the maximum expected return for a given level of risk. Because of the way the optimisation function in Python’s SciPy library is set up we have to reframe this into a minimisation problem. Finding the portfolios with the maximum expected return for a given level of risk is equivalent to finding the portfolios with the minimum level of risk for a given expected return.
What we need to do is define a function that returns the important portfolio statistics: expected return, volatility and Sharpe ratio. After setting up some constraints and initial starting weights to be used in the minimisation function we can call the function and generate a predefined number of optimal portfolios that we can plot and use for further analysis. The following code does just that:
Calling the Efficient Frontier function with the 30 US stocks and plotting it on top of the scatter plot of randomly generated portfolios results in the following plot:
In the above visualisation, I included three stars.
The blue star represents the minimum variance portfolio. Every "x" that lies above and to the right of that star makes up the Efficient Frontier. The "x"s that lie below and to the right of the blue star are not efficient because there clearly are portfolios with the same expected volatility (x-axis value) that have higher expected returns (y-axis value).
The red star represents the maximum Sharpe ratio portfolio and the white star represents one of the 5,000 randomly generated portfolios.
To some people, especially those that have seen visualisations of efficient frontiers at university or elsewhere, it may be confusing why the "x"s that lie on the efficient frontier are so far away from the cluster of randomly generated portfolios. The reason for this is that in the portfolios along the efficient frontier a lot of stocks are assigned a weight of zero because that is what lead to the maximum return for a given volatility. In the Monte Carlo simulation, every stock is assigned some weight between 0 and 1, which, due to the risk-return and covariance profiles of the stocks included, does not lead to an optimal portfolio allocation. Here is a comparison of the allocation of the maximum Sharpe ratio portfolio to that of the portfolio represented by the white star:
The weight comparison shows that the randomly selected portfolio over allocates to less "valuable" stocks (valuable here is meant in the sense of adding to diversification of the portfolio while also contributing to expected return) and under allocates to more "valuable" stocks.
But why does the optimal portfolio only allocate capital to a portion of the stocks available? Why, for example does Amazon make up more than 50% of the portfolio? And why is there no investment in Google but McDonald’s gets roughly 10% of capital allocated to it?
By having a look at the correlation matrix of the stocks and keeping in mind the expected annual returns shown in the table above I will provide a simplified explanation of the underlying logic. The entire correlation matrix is too large to be included here but can be found in the notebook.
The reason that Amazon makes up such a big chunk of the maximum Sharpe ratio portfolio is simply because it has by far the highest expected return with 35.5% annually. Furthermore, if you take into account Amazon’s expected volatility its attractiveness becomes even more clear. Despite having the highest expected return, it only has the seventh highest volatility of all stocks. In fact, Amazon’s expected volatility is very close to that of J.P. Morgan, which has an expected annual return of 9.2%.
The reason why Google’s weight in the maximum Sharpe ratio portfolio is zero is because it is the stock whose returns have the highest correlation to those of Amazon. Because Amazon already makes up such a big part of the portfolio in order to diversify, and thereby decrease overall portfolio risk, the remaining weight needs to be allocated to stocks whose returns have lower correlations to that of Amazon.
That is where McDonald’s comes in. Its stock returns have one of the lowest correlations with those of Amazon’s stock, which is why, despite having average returns, adding it to the portfolio is valuable from a portfolio-wide point of view.
Simplified statements like these have to be made with caution because in a portfolio allocation one cannot conclude anything by just looking at the risk-return profiles of two stocks and the correlation between them but rather always needs to look at the portfolio as a whole. That being said, I think the example using Amazon, Google and McDonald’s is a good starting point to understand the underlying logic.
After a brief diversion let’s get back to the efficient frontier. At this point, the visualisation of the efficient frontier only consists of individual points but in order for it to be a proper frontier we would like it to be continuous line. To create a continuous line using the existing points that make up the efficient frontier we can interpolate a B-spline representation of the data points. Sounds confusing, and the math is quite advanced, but essentially what the B-spline interpolation does is it fits (i.e. approximates) a curve to a set of points. That enables us to plot the efficient frontier as a continuous line but it also gives us a continuous function of the efficient frontier, which will come in handy in the next section.
The resulting continuous curve looks like this:
Now that we have the Efficient Frontier as a continuous function we can compute the Capital Market Line.
Computing the Capital Market Line using Python
So far, I have only considered a portfolio made up of risky assets (stocks in this case) but what if we consider a risk-free investment (usually a cash account with a large bank) in combination with the risky investment?
As it turns out that is the basic idea behind the Capital Market Line (CML). Essentially, the theory suggests that investors first determine an efficient portfolio of risky assets (as we have done) and then add a risk-free asset into the mix. As I will show shortly, combining a risk-free investment with an efficient portfolio considerably enhances the efficient investment opportunity set for investors.
The efficient portfolio that we choose to combine with the risk-free investment is the one where the tangent line of the efficient frontier exactly crosses through the return of the risk-free investment on the y-axis of the graph that plots the efficient frontier. For a risk-free investment with an interest rate of 1% (i.e. its return) that point on the y-axis would be (0, 0.01).
As some of you may remember from Calculus class (here is a link for those that do not) we can use the first derivative of a function to find the tangent line to the curve defined by that function at a specific point. This is where the fact that the B-spline interpolation gives us a continuous (differentiable) function comes in very handy. Using that continuous function and its first derivative in combination with a few conditions we can solve for the CML. To find the Capital Market Line we use SciPy’s fsolve function (which finds the roots of a continuous function) with the following set of conditions:
In words, the first condition means that at x=0 the function has to be equal to the return of the risk-free rate, i.e. the straight-line of the CML has to pass through that point on the y-axis. The second condition simply states that for any value of x the function has to satisfy the linear function equation (some may remember this being written as y=mx+b in high school). The third condition states that the first derivative of the function has to be equal to the parameter b, which is the slope.
The code that allows us to solve for the efficient portfolio where the tangent line passes through the return of the risk-free asset on the y-axis is this:
Which results in the following Capital Market Line:
In the above visualisation, the blue star represents the efficient portfolio where the tangent line passes through the risk-free rate. By adding a risk-free investment to the efficient portfolio, at least according to Modern Portfolio Theory, an investor can achieve any risk-return profile that lies on the straight line between the risk-free asset and the efficient portfolio (and through borrowing money even beyond that point) by adjusting the proportion of wealth invested in the risk-free asset. The bigger the proportion invested in the risk-free asset, the closer you are to the origin of the CML and, vice versa, the bigger the proportion of the (risky) efficient portfolio, the closer you are to the blue star.
Here is a zoomed-in version of the above visualisation to make it comparable to previous ones:
With the computation and plotting of the CML, Part 1 of the article is done and we can move on to analysing what impact including cryptocurrencies in the portfolio has. You can find Part 2 of the article here.