FMP
Sep 11, 2023 6:40 PM - Rajnish Katharotiya
Image credit: Scott Graham
Portfolio optimization is the process to identify the best possible portfolio from a set of portfolios. But how do we define the best portfolio?
The answer depends on the investor profile. We may have investors pursuing different objectives when optimizing their portfolio. For example, young investors may prefer to find portfolios maximizing expected return. While older investors could aim to find portfolio minimizing the risk.
Photo by Pixabay on Pexels
One of the most relevant theories on portfolio optimization was developed by Harry Markowitz. His theory, known as modern portfolio theory, states that investors can build portfolios which maximize expected return given a predefine level of risk.
The goal according to this theory is to select a level of risk that an investor is comfortable with. Then find a portfolio that maximizes returns based on the selected risk level.
Another approach to find the best possible portfolio is to use the Sharpe Ratio. The Sharpe ratio of a portfolio helps investors to understand the return of a portfolio based on the level of risk taken.
Below is the Sharpe ratio formula where Rp is the return of the portfolio. Rf is the risk free rate and Op is the standard deviation (i.e. portfolio risk) of the portfolio.
Sharpe Ratio = (Rp - Rf) / Op
The last element in the Sharpe Ratio is the Risk free rate (Rf). A common proxy for the risk free rate is to use Treasury Bill yields.
The higher the Sharpe Ratio, the better a portfolio returns have been relative to the taken risk. If we could choose between multiple portfolio options with similar characteristics, we should select the portfolio with the highest Sharpe Ratio.
In the next section we are going to calculate the Sharpe Ratio for multiple random generated portfolios.
Now that we know a bit more about portfolio optimization lets find out how to optimize a portfolio using Python.
To keep things consistent, I will follow the same methodology that we applied in my previous post in order to calculate portfolio returns and portfolio risk. Therefore, I will not go into the details on how to do this part.
See below a summary of the Python portfolio optimization process that we will follow:
NVS, AAPL, MSFT and GOOG.
We will generate 2000 random portfolios. That is 2000 portfolios containing our 4 stocks with different weights. We will calculate portfolio returns, portfolio risk and the Sharpe Ratio for each of the random generated portfolios.
Then, we will visualize the portfolio returns, risks and Sharpe Ratio using Matplotlib.
Finally, we will find out what is the portfolio with the highest return, lowest risk and highest Sharpe Ratio.
So let's start coding.
import requests
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
stocks = ['NVS','AAPL','MSFT','GOOG']
empresas = {}
api_key = 'your api key'
#Get all prices into a dataframe
for stock in stocks:
prices = requests.get(f'https://financialmodelingprep.com/api/v3/historical-price-full/{stock}?serietype=line&apikey={api_key}').json()
prices = prices['historical'][-900:]
prices = pd.DataFrame(prices)
empresas[stock] = prices.set_index('date')
empresas[stock] = empresas[stock]['close']
portfolio = pd.concat(empresas, axis=1)
return_stocks = portfolio.pct_change()
return_stocks
Next, we are going to generate 2000 random portfolios (i.e. random weights) and calculate the returns, risk and Sharpe Ratio for each of them.
We start by defining empty lists where we will append the calculated portfolio returns, risk and Sharpe Ratio for each of the random portfolios. The calculation will happen in a for loop. Note that we use Numpy to generate random arrays containing each of the portfolio weights.
number_of_portfolios = 2000
RF = 0
portfolio_returns = []
portfolio_risk = []
sharpe_ratio_port = []
portfolio_weights = []
for portfolio in range (number_of_portfolios):
weights = np.random.random_sample((len(stocks)))
print(type(weights))
print(weights)
#below line ensures that the sum of our weights is 1
weights = weights / np.sum(weights)
#outcome
[0.78253875 0.43725429 0.11399585 0.44219616]
For simplicity reasons we have assumed a Risk free rate of 0. Having our portfolio weights, we can move on to calculate the annualised portfolio returns, risk and Sharpe Ratio. If you are unfamiliar with the calculation, feel free to have a look at my previous post where portfolio risk calculation is explained in details.
annualize_return = np.sum((return_stocks.mean() * weights) * 252)
portfolio_returns.append(annualize_return)
#variance
matrix_covariance_portfolio = (return_stocks.cov())*252
portfolio_variance = np.dot(weights.T,np.dot(matrix_covariance_portfolio, weights))
portfolio_standard_deviation= np.sqrt(portfolio_variance)
portfolio_risk.append(portfolio_standard_deviation)
#sharpe_ratio
sharpe_ratio = ((annualize_return- RF)/portfolio_standard_deviation)
sharpe_ratio_port.append(sharpe_ratio)
#keep weights as well to find out later the weights from the optimized portfolio
portfolio_weights.append(weights)
Finally, we convert our list into Numpy arrays:
#convert to arrays
portfolio_risk = np.array(portfolio_risk)
portfolio_returns = np.array(portfolio_returns)
sharpe_ratio_port = np.array(sharpe_ratio_port)
Now that we have created 2000 random portfolios, we can visualize them using a Scatter plot in Matplotlib:
plt.figure(figsize=(10, 5))
plt.scatter(portfolio_risk, portfolio_returns, c=portfolio_returns / portfolio_risk)
plt.xlabel('volatility')
plt.ylabel('returns')
plt.colorbar(label='Sharpe ratio')
In the output graph, each point represents a portfolio. We see that portfolios with the higher Sharpe Ratio are shown as yellow. Yellow coloured portfolios are preferable since they offer better risk adjusted returns.
But how can we identify which portfolio (i.e. portfolio weights) has the highest Sharpe Ratio? And what about the portfolio with the highest return? And lowest risk?
We can find the answer to that questions by transforming our data into a Pandas DataFrame and performing some basic queries.
porfolio_metrics = [portfolio_returns,portfolio_risk,sharpe_ratio_port, portfolio_weights]
#from Python list we create a Pandas DataFrame
portfolio_dfs = pd.DataFrame(porfolio_metrics)
portfolio_dfs = portfolio_dfs.T
#Rename the columns:
portfolio_dfs.columns = ['Port Returns','Port Risk','Sharpe Ratio','Portfolio Weights']
#convert from object to float the first three columns.
for col in ['Port Returns', 'Port Risk', 'Sharpe Ratio']:
portfolio_dfs[col] = portfolio_dfs[col].astype(float)
portfolio_dfs
By looking into the DataFrame, we see that each row represents a different portfolio. For example, row 1 contains a portfolio with 18% weight in NVS, 45% in AAPL, etc.
Now, we are ready to use Pandas methods such asidmax and idmin. They will allow us to find out which portfolio has the highest returns and Sharpe Ratio and minimum risk:
#portfolio with the highest Sharpe Ratio
Highest_sharpe_port = portfolio_dfs.iloc[portfolio_dfs['Sharpe Ratio'].idxmax()]
#portfolio with the minimum risk
min_risk = portfolio_dfs.iloc[portfolio_dfs['Port Risk'].idxmin()]
print(Highest_sharpe_port)
print(min_risk)
#Highest Sharpe Ratio
Port Returns 0.342024
Port Risk 0.26507
Sharpe Ratio 1.29032
Portfolio Weights [0.055480947132996186, 0.20213618958420174, 0....
#Minimum Risk
Port Returns 0.114196
Port Risk 0.195615
Sharpe Ratio 0.58378
Portfolio Weights [0.7672050820919301, 0.00958106941668406, 0.02...
Within seconds, our Python code returns the portfolio with the highest Sharpe Ratio as well as the portfolio with the minimum risk.
By altering the variables a bit, you should be able to reuse the code to find the best portfolio using your favourite stocks.
May 14, 2024 11:41 AM - Sanzhi Kobzhan
A stock's target price, also known as its fair value, is an indication of what a share can cost based on the company’s forecasted financial statements. It is important to know a stock's fair value to find undervalued stocks with great growth potential. Let's consider how investment analysts calculat...
May 24, 2024 9:30 AM - Rajnish Katharotiya
Earnings call transcripts are invaluable resources for investors, analysts, and financial enthusiasts. They provide insights into a company's performance, strategy, and future outlook, making them essential for making informed investment decisions. With Financial Modeling Prep, Earnings Call Transcr...
May 27, 2024 3:30 PM - Rajnish Katharotiya
In the ever-evolving world of technology, certain sectors have consistently demonstrated exceptional growth and innovation. The graphics processing units (GPUs) industry is one such sector, offering investors a golden opportunity for potentially high returns. In this blog, we'll delve into why inves...