top of page
learn_data_science.jpg

Data Scientist Program

 

Free Online Data Science Training for Complete Beginners.
 


No prior coding knowledge required!

Portfolio Efficient Frontier in Python


Introduction

Investors often aim at maximizing returns on investment for a given level of risk. This can be achieved by selecting a number of assets in which to invest in so as to minimize the risk and at the same time maximize the returns on investment. An efficient frontier represents a set of optimal portfolios that offer the highest expected returns for a defined level of risk (https://www.investopedia.com/terms/e/efficientfrontier.asp).


In this tutorial, we will demonstrate how to construct an efficient portfolio of a two-asset portfolio based on the different weight combinations of the assets. The assets we will use for this demonstration are two S&P 500 Exchange Traded Funds (ETFs) of XLE and XLI. . We then proceed to select a suitable portfolio combination on the efficient frontier based on the risk tolerance and the required expected returns.

Import Required Packages


import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt

Load the Data

We will use the daily closing prices for the two assets for a one year period from 27 November, 2017 to 26 November, 2018 . The data is downloaded from Yahoo Finance and loaded into a Data frame.


#specifying the assets
tickers = ['XLE','XLI']

#specifying the start and end dates
start = "2017-11-27"
end = "2018-11-27"

#downloading price data for the assets
data = pd.DataFrame()
for ticker in tickers:
 data[ticker] = yf.download(ticker, start, end)['Close']

Plot of the Daily Close Prices


plt.figure(figsize=(8,5))

plt.plot(data.index, data['XLE'], label='XLE Close')
plt.plot(data.index, data['XLI'], label='XLI Close')
plt.title('Plot of Close Prices', fontsize=16)
plt.xlabel('Date', fontsize=12)
plt.ylabel('Close Prices', fontsize=12)
plt.legend()
plt.show()

ree

Calculate the Daily Log Returns

The portfolio of the two assets is constructed using the daily returns of each of the assets. We calculate the daily returns of each of the assets using the daily log returns.

ree
ree

#create empty Data Frame for returns
returns = pd.DataFrame()

#calculate daily log returns
for ticker in tickers:
    returns[ticker] = 
    np.log(data[ticker]/data[ticker].shift(1))

#drop rows with NaN
returns = returns.dropna()
returns.head() 

ree


Daily and Annualized Standard Deviation of Returns

In constructing the portfolio, we will use the annualized standard deviations of each asset returns.



#daily standard deviations
daily_std = returns.std()
daily_std
ree



#annualized standard deviations
annualized_std = daily_std * np.sqrt(252)
annualized_std
ree


Correlation of Returns

We get the correlation of the two asset returns


ret_corr = returns[['XLE', 'XLI']].corr()
ret_corr
ree




corr_value = np.round(ret_corr['XLE'][1],3)
print('The Correlation between the two assets is:', corr_value)

The Correlation between the two assets is: 0.66

Construction of an Efficient Frontier

We construct an efficient frontier of portfolio based on the different weight combinations of the two ETFs. Using these weight combinations, we calculate the portfolio expected returns and volatility for each.

The portfolio expected return is given by the sum of the weighted individual ETF’s returns.


ree

ree

ree

The Portfolio Volatility is computed using the formula for the Two-Asset Portfolio Volatility as shown below:


ree
ree
ree

ree


Portfolio Weights

We define the weights for the various portfolio combinations.


# define weights for the two ETFs
w1=np.linspace(0,1,11)
w2=np.linspace(1,0,11)

#construct a dataframe of weights
weights_df = pd.DataFrame()
weights_df['XLE Weight'] = w1
weights_df['XLI Weight'] = w2

weights_df

ree







Portfolio Returns and Volatilities


#volatilities
xle_vol = annualized_std[0]
xli_vol = annualized_std[1]

xle_vol, xli_vol
(0.20335309806894042, 0.1710067876397469)

#correlation
cor=corr_value
cor
0.66

Expected Returns using Capital Asset Pricing Model (CAPM)

The Expected return for each asset using the CAPM is calculated as follows:


ree

Where:


ree
# Define Variables
beta_xle = 1.07 #Beta Value of XLE
beta_xli = 1.06 #Beta Value of XLI
risk_free_rate = 0.0225 # Risk Free Rate
market_return = 0.09 #Market Return
market_std = 0.15 #Market Standard Deviation
# Expected Return of XLE
ret_xle = risk_free_rate + beta_xle * (market_return - risk_free_rate)

# Expected Return of XLIret_xli = risk_free_rate + beta_xli * (market_return - risk_free_rate)
xle_ret=ret_xle
xli_ret=ret_xli

xle_ret, xli_ret
(0.094725, 0.09405)
#Compute Returns and Volatility for each combination
portfolio = weights_df.copy()

#portfolio Returns
portfolio['Portfolio Returns'] = ((portfolio['XLE Weight']*xle_ret) + (portfolio['XLI Weight']*xli_ret))

#portfolio volatility
portfolio['Volatility'] = np.sqrt(((portfolio['XLE Weight'])**2 * xle_vol**2) +((portfolio['XLI Weight'])**2 * xli_vol**2) +(2 * (portfolio['XLE Weight']) * xle_vol *(portfolio['XLI Weight']) * xli_vol) * cor)

portfolio

ree














Portfolio Efficient Frontier

From the above table, we construct the Efficient Frontier for each portfolio weights combination. The figure below shows the scatter plot for the constructed Efficient Frontier of the portfolios

## Plot of the Portfolio Efficient Frontier
plt.figure(figsize= (8,6))

plt.title('Portfolio Efficient Frontier', fontsize=16)
plt.scatter(portfolio['Volatility'],portfolio['Portfolio Returns'],color='r', alpha=0.6)

plt.xlabel('Portfolio Volatility', fontsize=12)
plt.ylabel('Portfolio Returns', fontsize=12)

plt.show()


ree

Selecting a Portfolio with Defined Constraints

From the constructed Efficient Frontier above, we choose our portfolio with the following constraints:

  • The Return greater than 9.43% and

  • The Volatility not exceeding 16.8%. We achieve this by constructing the threshold lines for returns and volatility on our Efficient Frontier plot as shown below:

#Define the Portfolio Constraints
Vol_threshold = 0.168
return_threshold = 0.0943
n = len(portfolio)

# Data ponts
points = []
for i, j in zip(portfolio['Volatility'], portfolio['Portfolio Returns']):
   points.append((i,j))

# Portfolio Weights, (xle, xli)
w = []
for i, j in zip(portfolio['XLE Weight'], portfolio['XLI Weight']):
   w.append((np.round(i,1), np.round(j,1)))

#Plot of the Portfolio Efficient Frontier with the Constraints

plt.figure(figsize= (8,6))

plt.title('Portfolio Efficient Frontier', fontsize=16)

plt.plot(portfolio['Volatility'], portfolio['Portfolio Returns'],'-or',alpha=0.6, label='Efficient Frontier')

plt.plot(n * [Vol_threshold], portfolio['Portfolio Returns'],label = 'Volatility Threshold')

plt.plot(np.linspace(0.165,0.205,11), n * [return_threshold],label = 'Returns Threshold')

for i, j in zip(points, w):
   plt.text(i[0],i[1],j)

plt.legend()
plt.show()

ree

From the plot above, we want to pick a portfolio with returns greater than 9.43% which lies above the Returns Threshold Line. The portfolio should also have a Volatility not exceeding 16.8% meaning it should lie on the Volatility Threshold line or to the left side of it. We can see from the plot that the only combination which satisfies the above constraints is the portfolio with 40% XLE and 60% XLI.


Github Link

The Notebook for this tutorial can be found on the following Github Link:


https://github.com/Musonda2day/Portfolio-Efficient-Frontier-.git





 
 
 

Comments


COURSES, PROGRAMS & CERTIFICATIONS

 

Advanced Business Analytics Specialization

Applied Data Science with Python (University of Michigan)

Data Analyst Professional Certificate (IBM)

Data Science Professional Certificate (IBM)

Data Science Specialization (John Hopkins University)

Data Science with Python Certification Training 

Data Scientist Career Path

Data Scientist Nano Degree Program

Data Scientist Program

Deep Learning Specialization

Machine Learning Course (Andrew Ng @ Stanford)

Machine Learning, Data Science and Deep Learning

Machine Learning Specialization (University of Washington)

Master Python for Data Science

Mathematics for Machine Learning (Imperial College London)

Programming with Python

Python for Everybody Specialization (University of Michigan)

Python Machine Learning Certification Training

Reinforcement Learning Specialization (University of Alberta)

Join our mailing list

Data Insight participates in affiliate programs and may sometimes get a commission through purchases made through our links without any additional cost to our visitors.

bottom of page