When one goes about constructing their stock portfolio, there are two questions to ask.
The first is what assets to buy?
The second is what should be the weightage allocation of each asset?
This article shows you a practical example of how you can optimize your stock portfolio through asset allocation strategies.
Suppose I have already answered the first question. I want to buy Amazon, Microsoft, Alibaba, Facebook, Tesla, Apple, Google, Disney. There are 8 assets to add to my portfolio.
But which one should I buy more or less so that my portfolio is optimized? And what do we mean my optimized? That’s what this article is all about.
1. How does Portfolio Optimization Works?
Based on the Modern Portfolio Theory, Markowitz argues that all investors are risk-averse. We want to achieve the highest long-term returns without taking extreme short-term volatility. But how do we measure that?
Though there are many ways to optimize your stock portfolio, my favourite one is still the Sharpe Ratio. Sharpe Ratio measures the risk-adjusted returns by taking the average returns divided by the risk. Risk, in this case, refers to the volatility of price fluctuations.
In this example, we are trying to find the weightage and asset allocation for our 8 stocks such that the portfolio gives us the maximum Sharpe ratio. That is the point where returns are the highest and risk is the lowest. I will be doing this in Python, so you can just copy and follow the codes along.
2. Stock Selection – Pick Your Bets
import numpy as np import pandas as pd from pandas_datareader import data as wb import matplotlib.pyplot as plt
assets = ['AMZN', 'MSFT', 'BABA', 'FB', 'TSLA', 'AAPL', 'GOOG', 'DIS'] df = pd.DataFrame() for asset in assets: df[asset] = wb.DataReader(asset, data_source='yahoo', start='2015-1-1')['Adj Close'] df = (df/df.iloc*100)
The first step is to pick your horse bets. Choose what stocks you want to buy and put them inside your asset list. I use AMZN, MSFT, BABA, FB, TSLA, APPL, GOOG and DIS. You can change yours if you want.
The second step is to import in all the daily stock prices for our 8 assets. I used the start date as 2015 because Alibaba listed only around late 2014.
The third step is to normalize the prices so that we can make a fair comparison of returns and volatility.
Here is how the data frame should look now.
3. Calculate Annualized Risk and Return of a Stock
returns = df.pct_change()
Next, we need to calculate what is the stock annualized risk and return.
A new “Returns” table is created to show the daily change in stock prices by %
def annual_riskreturn(returns_df): summary = returns_df.agg(['mean', 'std']).T summary.columns = ['Return', 'Risk'] summary['Return'] = summary['Return'] * 252 summary['Risk'] = summary['Risk'] * np.sqrt(252) return summary
To make this simple, we create a function call “annual_riskreturn”. This function takes in a parameter “returns_df”.
In the function, it is going to first calculate the average mean and standard deviation. Then, it is going to annualised it by multiplying 252 days for return and square root it for standard deviation.
summary = annual_riskreturn(returns)
Finally, just pass in our “Returns” table into the function so that we get a summary of all the 8 stocks.
Here is the summary of the annualized risk and return for our stocks. Do note that this is just data from 2015 till date.
summary.plot(kind='scatter', x='Risk', y='Return', figsize= (13,9), s=50, fontsize=15) for i in summary.index: plt.annotate(i, xy=(summary.loc[i, 'Risk'], summary.loc[i, 'Return']), size=15) plt.xlabel('Annualized Risk', fontsize=15) plt.ylabel('Annualized Return', fontsize=15) xmin, xmax, ymin, ymax = plt.axis() plt.axvline(x=(xmin+xmax)/2, color='r') plt.axhline(y=(ymin+ymax)/2, color='r') plt.show()
We can visualise it on a scatter plot so that it is even more intuitive to understand.
Ideally, you want to hold stocks that are on the top-left and avoid stocks on the lower-right. Not surprisingly, Tesla is all the way on the top-right corner. Bitcoin is even worse than Tesla.
4. Calculating the Sharpe Ratio
summary['Sharpe'] = summary['Return']/summary['Risk'] summary.sort_values('Sharpe', ascending= False)
Next, we need to calculate the Sharpe Ratio for each stock which simply takes their annualized return divided by annualized risk. The actual formula actually includes subtracting risk-free rate, but I excluded it for simplicity sake.
If we were to compare the risk-adjusted returns, Amazon is the clear winner here. A sharpe ratio above 1 is generally good and a sharpe ratio below 1 is sub-optimal.
5. Generating the Sharpe Optimal Portfolio
The sharpe Optimal Portfolio is simply the portfolio that returns us the highest sharpe ratio. To do that, we can create 100,000 portfolio simulations then pick the best from there.
noa = len(returns.columns) nop = 100000 matrix = np.random.random(noa * nop).reshape(nop, noa) weights = matrix/matrix.sum(axis=1, keepdims=True)
noa is the number of assets while nop is the number of portfolio simulations.
What we are trying to do here is to generate 100,000 portfolios, each with different random weights.
You can see the different random weights of each portfolio here. The sum of all the weights will always be equal to 100% as it should be. There are 100,000 different weight combinations now.
6. How to Calculate Portfolio Risk and Return?
portfolio_return = returns.dot(weights.T)
To calculate the overall portfolio returns based on the weightage of each asset, we can take our stock returns table and multiply it with the weightage transposed. The “dot” function in Python is used for matrix multiplication (rows x columns).
portfolio_summary = annual_riskreturn(portfolio_return)
To see the risk and return of our 100,000 portfolio simulations, we can just feed the whole portfolio_return into the “annual_riskreturn” function that we created earlier.
Here is how it looks like in tabular format.
What you see now is 100,000 portfolios, each with a different random weightage combination. Based on the weightage, the annualized risk and returns are different for each portfolio.
plt.figure(figsize=(15,9)) plt.scatter(portfolio_summary.loc[:, 'Risk'], portfolio_summary.loc[:, 'Return'], s=20, color = 'red') plt.xlabel('Annualized Risk', fontsize=15) plt.ylabel('Annualized Return', fontsize=15) plt.show()
If we were to visualise this 100,000 portfolio simulations on a scatter plot, here is how it will look.
This chart shows how asset allocation affects your overall portfolio returns and risks. The same capital of $10,000 can have various portfolio performance, depending on the weightage you put for each stock.
As an investor, we always want the x-axis to be as low as possible and the y-axis to be as high as possible. So a good portfolio should be located somewhere at the top-left corner.
7. Asset Allocation to Optimize Stock Portfolio
Here is the final part. Out of all the 100,000 red dots we saw on the scatter plot, which portfolio is the best? What should be the weightage allocation for each asset?
portfolio_summary['Sharpe'] = portfolio_summary['Return']/portfolio_summary['Risk'] max_sharpe = portfolio_summary.iloc[portfolio_summary['Sharpe'].idxmax()] plt.scatter(max_sharpe, max_sharpe, marker=('X'), color='black', s=300)
First we calculate the Sharpe ratio for each portfolio simulation.
Second, we locate the index position where the Sharpe ratio is the maximum.
Third, we plot it out on the scatter plot using a “X” label.
This is the point where the Sharpe ratio is the highest.
maxsharp_w = weights[portfolio_summary['Sharpe'].idxmax(), :] *100 pd.DataFrame(index = df.columns, columns= ['Weightage'], data = maxsharp_w)
At this point, our annualised return is about 43% and the risk or standard volatilitiy is about 27%. This gives us a Sharpe Ratio of about 1.59.
Finally, the asset allocation weightage can be determined by locating the index position where the Sharpe Ratio is the highest.
This is the answer to our second question; what should be the weightage allocation of each asset.
Let’s say if you have $10,000 and you want a portfolio that has the highest risk-adjusted return, this is the optimal weightage in our portfolio simulation.
$3346 goes to Amazon, $1930 goes to Microsoft, $2334 goes to Tesla, $2081 goes to Apple. But it is asking us not to invest in Facebook, Alibaba, Google and Disney as their allocation is pretty insignificant. Why is that so?
If you think about it, look at the position of Amazon in comparison with Facebook and Alibaba. It is obviously a better pick since it has lower risk but yet higher returns than FB and BABA.
Then if you look at the position of MSFT and Apple in comparison with Google and Facebook, its risk is only slightly higher maybe 3-4%. But their returns are about 25% higher than Disney and 10% higher than Google. From a Sharpe Ratio standpoint, MSFT and Apple is a much better pick as its risk-adjusted returns are higher.
That’s why most of the weightage shifts towards Amazon, Tesla, Apple and Microsoft.
8. Limitations of Sharpe Ratio
There are some flaws and limitations to everything you have seen so far. So I myself wouldn’t rely on the second answer 100%. But it does give me a good sense of how each stock is performing.
The first issue is that even though we run 100,000 simulations, the results would be slightly different each time since the weightage allocation are random. Though the pattern and asset allocation would more or less be the same.
Secondly, if we change the starting date of retrieving stock prices, their annualized returns and volatility might be different and the end results could also differ.
Thirdly, this does not account for future growth or funds cyclical rotation. Example, Alibaba only got listed at a much later date compared to the rest. Its rally has not begun as China is still rising. Or when Vaccine is found, there will be a value rotation of institutional funds from tech into consumer stocks like Disney.
Fourthly, past price performance does not equate future performance. Every company has a lifecycle and the growth story would eventually slow. A stock’s 5-year annualised return of 50% does not mean that it will be the same 50% for the next 5 years. Though none of them seems slowing to me, on the contrary, tech growth is accelerating.
Fifth, some might argue standard deviation is not a function of risk.
Lastly, I am not factoring in covariance between assets in my portfolio. By right, this example should be a mix of cash, bonds, stocks, gold, bitcoin and etc. Or either that, a mix of sectors like consumers, tech, financials, healthcare, energy and etc. But mine is mostly tech companies in one single sector.
9. Should I Optimize my Stock Portfolio Now?
Hopefully, this gives you some ideas or strategies you can think about to optimize your stock portfolio.
One interesting test you can try out is to input in all the stocks you hold in your stock portfolio. Then run the portfolio simulation of different random weights 100,000 times. This will show you all the 100,000 different possibilities based on the stocks you own.
Then look at where your portfolio is on the scatter plot based on your risk and return value. You can do this by running following the code below.
my_weight = np.array([0.2,0.2,0.1,0.1,0.1,0.1,0.1,0.1]).reshape(1,noa) my_return = returns.dot(my_weight.T) my_portfolio = annual_riskreturn(my_return) my_portfolio['Sharpe'] = my_portfolio['Return'] / my_portfolio['Risk'] my_portfolio
Let’s say my capital allocation is 20%, 20%, 10%, 10%, 10%, 10%, 10%, 10%. I can determine my portfolio return, risk and Sharpe ratio by multiplying the stock returns with the weightage.
Is your portfolio on the lower-right, lower-left, upper-right or upper-left? And how far are you from the Sharpe Optimal Portfolio?
If you are on the upper-right, you might want to ask if your portfolio is too volatile? Can I rebalance it to reduce the risks more without sacrificing too much of the returns?
If you are on the lower-left, you might think is my portfolio returns too low? Am I playing it too conservatively? Can I allocate more capital into the alpha growth stocks without increasing my risk too much?
If you are on the upper-left, your portfolio is probably doing quite decently from a risk-adjusted return standpoint.
If you are on the lower-right, you have a high-risk, low-return portfolio. The allocation is not optimal and it probably is time to optimize your stock portfolio.