Asset allocation is the most important decision that any investor needs to face. They need to decide how to spread their total capital over certain assets (in this case, stocks). When considering the allocation, the investor wants to balance the risk and the potential reward. At the same time, the allocation depends on factors such as individual goals, risk tolerance, and the investment horizon.
The key framework used in asset allocation is the Modern Portfolio Theory (MPT), which was introduced by the Nobel Prize winner Harry Markowitz. MPT describes how investors can construct portfolios to maximize their expected returns for a given level of risk or, conversely, minimize risk for a given level of expected return. The mathematical framework used to achieve this is called mean-variance optimization.
The main insight from MPT is that investors should not evaluate an asset’s performance alone. Instead, they should evaluate how it would impact the performance of a portfolio of assets. Another important takeaway is the concept of diversification, which means that owning different kinds of assets reduces risk. That is because the loss or gain of a particular security has less impact on the overall portfolio’s performance.
Your task
In the dynamic realm of finance, data scientists/analysts are often tasked with finding optimal investment strategies. Imagine you're one such analyst, and you were asked to build an effective portfolio comprising FAANG stocks – Facebook (Meta), Apple, Amazon, Netflix, and Google. Your goal is to maximize returns while mitigating risk.
In this project, you are tasked to find the optimal allocation to the FAANG stocks based on historical stock price data spanning the years 2020-2023. The dataset is stored in the faang_stocks.csv
file. For each trading day, it contains the close prices of the five tech companies.
# Importing libraries
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
# Setting the plotting style to be colorblind-friendly
plt.style.use("seaborn-colorblind")
# Loading data
stock_prices_df = pd.read_csv("faang_stocks.csv", index_col="Date")
# Changing the index to a datetime type allows for easier filtering and plotting.
stock_prices_df.index = pd.to_datetime(stock_prices_df.index)
stock_prices_df
# Plotting the stock prices
stock_prices_df.plot(title="FAANG stock prices from years 2020-2023");
# Use however many cells you need to complete this exercise.
# Please remember to store the requested outputs in the correct objects!
# Calculate returns
returns_df = stock_prices_df.pct_change().dropna()
# Calculate the 1/n portfolio weights
portfolio_weights = 5 * [0.2]
# Calculate the portfolio returns of the 1/n portfolio
portfolio_returns = returns_df.dot(portfolio_weights)
# Calculate the expected portfolio return
benchmark_exp_return = portfolio_returns.mean()
# Calculate the portfolio's Sharpe ratio
benchmark_sharpe_ratio = (
portfolio_returns.mean() / portfolio_returns.std() * np.sqrt(252)
)
# Calculate the annualized expected returns and the covariance matrix
avg_returns = returns_df.mean() * 252
cov_mat = returns_df.cov() * 252
# Instantiate the EfficientFrontier object
ef = EfficientFrontier(avg_returns, cov_mat)
# Find the weights that maximize the Sharpe ratio
weights = ef.min_volatility()
mv_portfolio = pd.Series(weights)
# Find the minimized volatility
mv_portfolio_vol = ef.portfolio_performance(risk_free_rate=0)[1]
# Alternative approach to get the expected returns and the covariance matrix
# avg_returns = expected_returns.mean_historical_return(stock_prices_df, compounding=False)
# cov_mat = risk_models.sample_cov(stock_prices_df)
# Instantiate the EfficientFrontier object
ef = EfficientFrontier(avg_returns, cov_mat)
# Find the weights that maximize the Sharpe ratio
weights = ef.max_sharpe(risk_free_rate=0)
ms_portfolio = pd.Series(weights)
# Find the maximized Sharpe ratio
ms_portfolio_sharpe = ef.portfolio_performance(risk_free_rate=0)[2]