How to Construct an Efficient Portfolio Using The Modern Portfolio Theory in Python?

Saad Ahmed
Towards Data Science
3 min readOct 17, 2018

--

In my last post, we discussed constructing an optimal portfolio of stocks using Harry Markowitz mean-variance analysis. In this post, we are going to construct an efficient frontier by generating random portfolios for a combination of five stocks.

So what is an efficient frontier?

In simple term its that combination of weights(share of wealth) that provides the best portfolio return for a given level of risk.

For example look at the figure below it depicts thousands of random portfolio returns and volatility generated using random weights. Notice the black marks? The one with a higher return is on the efficient side of the curve as it offers more return for the same level of risk.

Random Portfolios

So now we know what an efficient frontier is and therefore we will start coding it in Python. The data used for this blog post is available here.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# loading the returns data
daily_returns = pd.read_csv("Returns.csv", index_col ="Date")
mean_ret = daily_returns.mean().reshape(4,1)
#Generating a random matrix of 1000 rows and 4 Columns
matrix = np.random.rand(1000,4)
#Converting to a data frame
matrix_df = pd.DataFrame(matrix, columns = daily_returns.columns)
matrix_sum = matrix_df.sum(axis = 1)#Calculating portfolio weights
weights = matrix_df.divide(matrix_sum , axis ="rows")
#transpose
weights_t= np.transpose(weights)
#Using the portfolio return formula
portfolio_return = np.dot(weights, mean_ret)

To generate an efficient frontier we need random portfolios and for random portfolio we need random weights to be multiplied by their mean return respectively to get the portfolio return. The above code block does whats required.

We also need the portfolio risk for the efficient frontier which is calculated from the following code.

#Variance covariance
cov_mat = daily_returns.cov()
portfolio_risk = []
for one_port in range(weights.shape[0]):

risk = np.sqrt(np.dot(weights.iloc[one_port,:],np.dot(cov_mat,weights_t.iloc[:,one_port])))

portfolio_risk.append(risk)

Now we have everything ready to plot the portfolios. The code below plots a simple scatter plot of portfolio returns vs portfolio risk.

plt.figure(figsize = (10,8))
plt.scatter(portfolio_risk, portfolio_return)
plt.xlabel("Portfolio Risk - Standard Deviation")
plt.ylabel("Portfolio Return")
plt.show()

And that’s how easy it was. Since I am not comfortable with plotting in Python so I decided to plot it with Tableau as well to come up with a better and interactive visualization.

#converting to a csv file
portfolio_risk = pd.DataFrame(portfolio_risk, columns = ["portfolio risk"])
portfolio_return = pd.DataFrame(portfolio_return, columns = ["portfolio return"])random_portfolio = pd.concat([portfolio_return, portfolio_risk, weights], axis =1)random_portfolio.to_csv("Random_Portfolios.csv")

Next I will be posting about how we can apply different machine learning in portfolio optimization as well as other areas of finance instead of just going for price prediction which in reality have little to no practicaal importance.

References:

https://towardsdatascience.com/efficient-frontier-portfolio-optimisation-in-python-e7844051e7f

https://medium.com/python-data/effient-frontier-in-python-34b0c3043314

--

--