Hierachical Clustering for CSMOM¶
In this notebook, you will create long-short CSMOM portfolios based on hierarchical clustering and analyse their performance. This notebook is structered as follows:
- Read Data
- Filter the Stocks
- Create Clusters, Create Portfolios and Rebalance
- Performance Analysis
- Conclusion
Import Libraries¶
Let's start by importing the necessary libraries for data manipulation, implementation of hierarchical clustering and visualisation.
# Import necessary libraries for data manipulation
import pandas as pd # For working with data in dataframe
import numpy as np # For numerical operations
import os
# Import necessary functions for hierarchical clustering analysis
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster
# Import library for plotting graphs
import matplotlib.pyplot as plt # For creating visualisations
#plt.style.use('seaborn-v0_8-whitegrid') # Set the style for the plots
plt.style.use('seaborn-v0_8-darkgrid')
import warnings # For suppressing warning messages during execution
warnings.filterwarnings('ignore') # Ignore any warning messages during execution
#
# Helper functions
import sys
sys.path.append(os.path.abspath("../.."))
#from data_modules.capstone_util_quantra import plot_and_display_metrics_csmom
from Support.advanced_momentum_1_1 import plot_and_display_metrics_csmom
Read Data¶
Import the price and volume data of S&P 500 constituents from the CSV files sp500_prices_2014-01-01_to_2024-01-01 , sp500_volumes_2014-01-01_to_2024-01-01 and store in the dataframes sp500_prices and sp500_volumes. This files can be found in the data_modules folder of the zip file at the end of this section.
# Reading S&P 500 price data from CSV file into 'sp500_prices' DataFrame, setting the first column as the index
#sp500_prices = pd.read_csv(
# '../data_modules/sp500_prices_2014-01-01_to_2024-01-01.csv', index_col=0)
# Reading S&P 500 volume data from CSV file into 'sp500_volume' DataFrame, setting the first column as the index
#sp500_volume = pd.read_csv(
# '../data_modules/sp500_volumes_2014-01-01_to_2024-01-01.csv', index_col=0)
# Displaying the first few rows of the sp500_prices DataFrame
#sp500_prices.head()
import pandas as pd
import yfinance as yf
import requests
from io import StringIO
# --- Get S&P 500 tickers ---
url = "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies"
headers = {
"User-Agent": "Mozilla/5.0"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
sp500 = pd.read_html(StringIO(response.text), header=0)[0]
tickers = sp500["Symbol"].tolist()
tickers = [t.replace(".", "-") for t in tickers]
print("Antal tickers:", len(tickers))
# --- Download data ---
data = yf.download(tickers, start="2010-01-01", auto_adjust=True)
# ✅ IMPORTANT: DO NOT FLATTEN
# Extract correctly from MultiIndex
sp500_prices = data['Close'].copy()
sp500_volume = data['Volume'].copy()
# Save
sp500_prices.to_csv("sp500_prices.csv")
sp500_volume.to_csv("sp500_volume.csv")
#print("✅ Files saved:")
#print("- sp500_prices.csv")
#print("- sp500_volume.csv")
Antal tickers: 503
[*********************100%***********************] 503 of 503 completed
Filter the Stocks¶
Perform the following steps to filter the stocks based on the daily tunover of the last 90 days.
- Multiply price and volume over
nperiods - Take an average or mean of the above product to get average daily turnover
Average daily turnover in the stock market refers to the total value of securities traded during a standard trading day, typically averaged over a specific period, such as a month or a year.
# Calculate the average turnover of each stock by multiplying prices with volume data of the last 90 days
average_turnover = (sp500_prices[:90] * sp500_volume[:90]
).mean()
# Filter the top 100 stocks based on average turnover
filtered_stocks = average_turnover.sort_values(ascending=False).index[:150]
# Prices of filtered stocks
filtered_stocks_prices = sp500_prices[filtered_stocks]
filtered_stocks_prices.index = pd.to_datetime(filtered_stocks_prices.index)
# Print filtered_stocks
filtered_stocks
Index(['AAPL', 'BAC', 'GOOG', 'GOOGL', 'GS', 'C', 'MSFT', 'JPM', 'AMZN', 'GE',
...
'EXC', 'MAR', 'TT', 'AMT', 'TXT', 'ITW', 'ADM', 'NEE', 'ALL', 'LUV'],
dtype='object', name='Ticker', length=150)
The following are the steps to perform sequentially to find the monthly returns of the assets.
- Resample the daily data to monthly data using the
resamplemethod. - After resampling, select the data of the last trading day of the month by using the method
last. - Calculate the monthly returns by calling the method
pct_change
# Resample the filtered prices to monthly frequency and calculate the percentage change from the previous month
monthly_returns = filtered_stocks_prices.resample('1M').last().pct_change()
# Removing the first row to eliminate NaN value resulting from percentage change calculation
monthly_returns = monthly_returns[1:]
# Display the first five rows of the monthly returns dataframe
monthly_returns.head()
| Ticker | AAPL | BAC | GOOG | GOOGL | GS | C | MSFT | JPM | AMZN | GE | ... | EXC | MAR | TT | AMT | TXT | ITW | ADM | NEE | ALL | LUV |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | |||||||||||||||||||||
| 2010-02-28 | 0.065396 | 0.097497 | -0.005925 | -0.005925 | 0.053662 | 0.024096 | 0.022145 | 0.077812 | -0.055897 | 0.004990 | ... | -0.039472 | 0.035076 | -0.014914 | 0.004947 | 0.019969 | 0.044276 | -0.015393 | -0.038746 | 0.044103 | 0.110326 |
| 2010-03-31 | 0.148470 | 0.072080 | 0.076538 | 0.076538 | 0.091332 | 0.191176 | 0.021626 | 0.066238 | 0.146706 | 0.133250 | ... | 0.011779 | 0.162671 | 0.092761 | -0.001172 | 0.066750 | 0.047296 | -0.015667 | 0.042269 | 0.040449 | 0.051288 |
| 2010-04-30 | 0.111021 | -0.001120 | -0.073036 | -0.073036 | -0.149035 | 0.079013 | 0.042676 | -0.047428 | 0.009796 | 0.036264 | ... | -0.005022 | 0.166243 | 0.060510 | -0.042244 | 0.075836 | 0.078970 | -0.033218 | 0.076971 | 0.011142 | -0.003025 |
| 2010-05-31 | -0.016125 | -0.117219 | -0.076222 | -0.076222 | -0.003989 | -0.093821 | -0.151394 | -0.070455 | -0.084902 | -0.133086 | ... | -0.103447 | -0.088981 | 0.008924 | -0.006861 | -0.095009 | -0.091390 | -0.090541 | -0.040730 | -0.056159 | -0.056146 |
| 2010-06-30 | -0.020827 | -0.086448 | -0.083768 | -0.083768 | -0.090046 | -0.050506 | -0.108140 | -0.075038 | -0.129125 | -0.112443 | ... | -0.016321 | -0.104933 | -0.073792 | 0.097952 | -0.178137 | -0.104634 | 0.021765 | -0.013353 | -0.062031 | -0.106541 |
5 rows × 150 columns
Here are the lookback and holding details of the cross-sectional momentum strategy.
- number of lookback months = 24 since the lookback period is two years
- Number of holding months = 1
# Define the number of months for lookback and holding periods
lookback_months = 24
holding_months = 1
Create an empty dataframe stock_monthly_returns to store the monthly returns of the stocks in the portfolio. This empty dataframe will be updated in a loop once a new portfolio is created.
# Create an empty dataframe to store monthly returns for each stock
stock_monthly_returns = pd.DataFrame()
Create Clusters, Create Portfolios and Rebalance¶
Create clusters based on the monthly returns data of 24 month's data to create CSMOM portfolios. Rebalance at the beginning of every month.
# Loop through each month after the lookback period
for i in range(lookback_months, len(monthly_returns)):
# Select the subset of monthly returns for the current lookback period
# Store the historical and holding monthly returns data and store in 'returns'
returns = monthly_returns[i - lookback_months:i + 1]
# Store the historical in 'trailing_returns'
trailing_returns = returns[:lookback_months]
# Extract the starting, ending, and holding months from the subset
starting_month = str(returns.index[0])[:7]
ending_month = str(returns.index[-2])[:7]
#holding_month = str(returns.index[-1])[:7]
holding_month = returns.index[-1]
print('_______________________________________________________')
print(
f" The historical data used to create the clusters is from {starting_month} to {ending_month}")
# Set returns data as the transposed scaled trailing returns
returns_data = trailing_returns.T
# Initialise the number of clusters and maximum number of stocks per cluster
num_clusters = 1
max_stocks_per_cluster = 10
# Perform hierarchical clustering using 'ward' linkage method
linkage_matrix = linkage(trailing_returns.T, method='ward')
# Assign cluster labels to stocks, ensuring each cluster has at most 10 stocks
clusters = fcluster(linkage_matrix, num_clusters, criterion='maxclust')
# Assign the cluster labels to the original returns data
returns_data['Cluster'] = clusters
# Adjust clusters until each cluster meets the constraint
while max(returns_data['Cluster'].value_counts()) > max_stocks_per_cluster:
num_clusters += 1
clusters = fcluster(linkage_matrix, num_clusters, criterion='maxclust')
returns_data['Cluster'] = clusters
# Define the minimum number of stocks in a cluster
minimum_stocks_in_cluster = 2
# Filter out clusters with fewer than the minimum number of stocks
filtered_clusters = returns_data.groupby('Cluster').filter(
lambda x: len(x) >= minimum_stocks_in_cluster)['Cluster'].unique()
# Assign the filtered cluster labels to the original price data
returns_data = returns_data[returns_data['Cluster'].isin(filtered_clusters)]
# Calculate the returns for each cluster and sum across clusters
cluster_returns = returns_data.groupby('Cluster').mean().sum(axis=1)
# Identify stocks to go short and long based on cluster returns
short = np.array(returns_data[returns_data.Cluster ==
cluster_returns.idxmin()].index)
long = np.array(returns_data[returns_data.Cluster ==
cluster_returns.idxmax()].index)
# Extract the returns for holding stocks in the current month
hold_returns = returns.iloc[-1]
# Calculate the average returns for the stocks to go long and short
long_returns = hold_returns[long].mean()
short_returns = -1 * hold_returns[short].mean()
# Calculate the total portfolio returns
portfolio_returns = long_returns + short_returns
# Print the portfolio returns for the current month
print(
f" The portfolio_returns in the month {str(monthly_returns.index[i])[:7]} are {np.round(portfolio_returns, 2)} %")
# Copy monthly returns data for further manipulation
returns_monthly = monthly_returns.copy()
# Select returns correctly (row = date, columns = stocks)
monthly_portfolio_returns = returns_monthly.loc[
holding_month, list(long) + list(short)
].copy()
# ✅ Robust short adjustment
monthly_portfolio_returns[
monthly_portfolio_returns.index.isin(short)
] *= -1
# Identify non-portfolio stocks
columns_to_nan = list(set(returns_monthly.columns) -
set(monthly_portfolio_returns.index))
# Set NaN only for this month
returns_monthly.loc[holding_month, columns_to_nan] = np.nan
# ✅ Replace deprecated append
stock_monthly_returns = pd.concat([
stock_monthly_returns,
returns_monthly.loc[[holding_month]]
])
_______________________________________________________ The historical data used to create the clusters is from 2010-02 to 2012-01 The portfolio_returns in the month 2012-02 are -0.17 % _______________________________________________________ The historical data used to create the clusters is from 2010-03 to 2012-02 The portfolio_returns in the month 2012-03 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2010-04 to 2012-03 The portfolio_returns in the month 2012-04 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2010-05 to 2012-04 The portfolio_returns in the month 2012-05 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2010-06 to 2012-05 The portfolio_returns in the month 2012-06 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2010-07 to 2012-06 The portfolio_returns in the month 2012-07 are -0.07 % _______________________________________________________ The historical data used to create the clusters is from 2010-08 to 2012-07 The portfolio_returns in the month 2012-08 are -0.12 % _______________________________________________________ The historical data used to create the clusters is from 2010-09 to 2012-08 The portfolio_returns in the month 2012-09 are -0.03 % _______________________________________________________ The historical data used to create the clusters is from 2010-10 to 2012-09 The portfolio_returns in the month 2012-10 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2010-11 to 2012-10 The portfolio_returns in the month 2012-11 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2010-12 to 2012-11 The portfolio_returns in the month 2012-12 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2011-01 to 2012-12 The portfolio_returns in the month 2013-01 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2011-02 to 2013-01 The portfolio_returns in the month 2013-02 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2011-03 to 2013-02 The portfolio_returns in the month 2013-03 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2011-04 to 2013-03 The portfolio_returns in the month 2013-04 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2011-05 to 2013-04 The portfolio_returns in the month 2013-05 are -0.03 % _______________________________________________________ The historical data used to create the clusters is from 2011-06 to 2013-05 The portfolio_returns in the month 2013-06 are 0.05 % _______________________________________________________ The historical data used to create the clusters is from 2011-07 to 2013-06 The portfolio_returns in the month 2013-07 are 0.05 % _______________________________________________________ The historical data used to create the clusters is from 2011-08 to 2013-07 The portfolio_returns in the month 2013-08 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2011-09 to 2013-08 The portfolio_returns in the month 2013-09 are 0.12 % _______________________________________________________ The historical data used to create the clusters is from 2011-10 to 2013-09 The portfolio_returns in the month 2013-10 are -0.01 % _______________________________________________________ The historical data used to create the clusters is from 2011-11 to 2013-10 The portfolio_returns in the month 2013-11 are -0.01 % _______________________________________________________ The historical data used to create the clusters is from 2011-12 to 2013-11 The portfolio_returns in the month 2013-12 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2012-01 to 2013-12 The portfolio_returns in the month 2014-01 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2012-02 to 2014-01 The portfolio_returns in the month 2014-02 are 0.07 % _______________________________________________________ The historical data used to create the clusters is from 2012-03 to 2014-02 The portfolio_returns in the month 2014-03 are -0.03 % _______________________________________________________ The historical data used to create the clusters is from 2012-04 to 2014-03 The portfolio_returns in the month 2014-04 are -0.0 % _______________________________________________________ The historical data used to create the clusters is from 2012-05 to 2014-04 The portfolio_returns in the month 2014-05 are -0.05 % _______________________________________________________ The historical data used to create the clusters is from 2012-06 to 2014-05 The portfolio_returns in the month 2014-06 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2012-07 to 2014-06 The portfolio_returns in the month 2014-07 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2012-08 to 2014-07 The portfolio_returns in the month 2014-08 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2012-09 to 2014-08 The portfolio_returns in the month 2014-09 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2012-10 to 2014-09 The portfolio_returns in the month 2014-10 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2012-11 to 2014-10 The portfolio_returns in the month 2014-11 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2012-12 to 2014-11 The portfolio_returns in the month 2014-12 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2013-01 to 2014-12 The portfolio_returns in the month 2015-01 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2013-02 to 2015-01 The portfolio_returns in the month 2015-02 are 0.07 % _______________________________________________________ The historical data used to create the clusters is from 2013-03 to 2015-02 The portfolio_returns in the month 2015-03 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2013-04 to 2015-03 The portfolio_returns in the month 2015-04 are -0.09 % _______________________________________________________ The historical data used to create the clusters is from 2013-05 to 2015-04 The portfolio_returns in the month 2015-05 are 0.08 % _______________________________________________________ The historical data used to create the clusters is from 2013-06 to 2015-05 The portfolio_returns in the month 2015-06 are 0.09 % _______________________________________________________ The historical data used to create the clusters is from 2013-07 to 2015-06 The portfolio_returns in the month 2015-07 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2013-08 to 2015-07 The portfolio_returns in the month 2015-08 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2013-09 to 2015-08 The portfolio_returns in the month 2015-09 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2013-10 to 2015-09 The portfolio_returns in the month 2015-10 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2013-11 to 2015-10 The portfolio_returns in the month 2015-11 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2013-12 to 2015-11 The portfolio_returns in the month 2015-12 are 0.13 % _______________________________________________________ The historical data used to create the clusters is from 2014-01 to 2015-12 The portfolio_returns in the month 2016-01 are 0.16 % _______________________________________________________ The historical data used to create the clusters is from 2014-02 to 2016-01 The portfolio_returns in the month 2016-02 are 0.23 % _______________________________________________________ The historical data used to create the clusters is from 2014-03 to 2016-02 The portfolio_returns in the month 2016-03 are -0.09 % _______________________________________________________ The historical data used to create the clusters is from 2014-04 to 2016-03 The portfolio_returns in the month 2016-04 are -0.13 % _______________________________________________________ The historical data used to create the clusters is from 2014-05 to 2016-04 The portfolio_returns in the month 2016-05 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2014-06 to 2016-05 The portfolio_returns in the month 2016-06 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2014-07 to 2016-06 The portfolio_returns in the month 2016-07 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2014-08 to 2016-07 The portfolio_returns in the month 2016-08 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2014-09 to 2016-08 The portfolio_returns in the month 2016-09 are -0.2 % _______________________________________________________ The historical data used to create the clusters is from 2014-10 to 2016-09 The portfolio_returns in the month 2016-10 are -0.03 % _______________________________________________________ The historical data used to create the clusters is from 2014-11 to 2016-10 The portfolio_returns in the month 2016-11 are -0.16 % _______________________________________________________ The historical data used to create the clusters is from 2014-12 to 2016-11 The portfolio_returns in the month 2016-12 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2015-01 to 2016-12 The portfolio_returns in the month 2017-01 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2015-02 to 2017-01 The portfolio_returns in the month 2017-02 are 0.07 % _______________________________________________________ The historical data used to create the clusters is from 2015-03 to 2017-02 The portfolio_returns in the month 2017-03 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2015-04 to 2017-03 The portfolio_returns in the month 2017-04 are 0.14 % _______________________________________________________ The historical data used to create the clusters is from 2015-05 to 2017-04 The portfolio_returns in the month 2017-05 are 0.09 % _______________________________________________________ The historical data used to create the clusters is from 2015-06 to 2017-05 The portfolio_returns in the month 2017-06 are -0.11 % _______________________________________________________ The historical data used to create the clusters is from 2015-07 to 2017-06 The portfolio_returns in the month 2017-07 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2015-08 to 2017-07 The portfolio_returns in the month 2017-08 are -0.01 % _______________________________________________________ The historical data used to create the clusters is from 2015-09 to 2017-08 The portfolio_returns in the month 2017-09 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2015-10 to 2017-09 The portfolio_returns in the month 2017-10 are 0.07 % _______________________________________________________ The historical data used to create the clusters is from 2015-11 to 2017-10 The portfolio_returns in the month 2017-11 are -0.13 % _______________________________________________________ The historical data used to create the clusters is from 2015-12 to 2017-11 The portfolio_returns in the month 2017-12 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2016-01 to 2017-12 The portfolio_returns in the month 2018-01 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2016-02 to 2018-01 The portfolio_returns in the month 2018-02 are 0.14 % _______________________________________________________ The historical data used to create the clusters is from 2016-03 to 2018-02 The portfolio_returns in the month 2018-03 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2016-04 to 2018-03 The portfolio_returns in the month 2018-04 are -0.07 % _______________________________________________________ The historical data used to create the clusters is from 2016-05 to 2018-04 The portfolio_returns in the month 2018-05 are 0.08 % _______________________________________________________ The historical data used to create the clusters is from 2016-06 to 2018-05 The portfolio_returns in the month 2018-06 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2016-07 to 2018-06 The portfolio_returns in the month 2018-07 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2016-08 to 2018-07 The portfolio_returns in the month 2018-08 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2016-09 to 2018-08 The portfolio_returns in the month 2018-09 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2016-10 to 2018-09 The portfolio_returns in the month 2018-10 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2016-11 to 2018-10 The portfolio_returns in the month 2018-11 are 0.15 % _______________________________________________________ The historical data used to create the clusters is from 2016-12 to 2018-11 The portfolio_returns in the month 2018-12 are 0.09 % _______________________________________________________ The historical data used to create the clusters is from 2017-01 to 2018-12 The portfolio_returns in the month 2019-01 are -0.12 % _______________________________________________________ The historical data used to create the clusters is from 2017-02 to 2019-01 The portfolio_returns in the month 2019-02 are 0.09 % _______________________________________________________ The historical data used to create the clusters is from 2017-03 to 2019-02 The portfolio_returns in the month 2019-03 are 0.05 % _______________________________________________________ The historical data used to create the clusters is from 2017-04 to 2019-03 The portfolio_returns in the month 2019-04 are 0.07 % _______________________________________________________ The historical data used to create the clusters is from 2017-05 to 2019-04 The portfolio_returns in the month 2019-05 are 0.17 % _______________________________________________________ The historical data used to create the clusters is from 2017-06 to 2019-05 The portfolio_returns in the month 2019-06 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2017-07 to 2019-06 The portfolio_returns in the month 2019-07 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2017-08 to 2019-07 The portfolio_returns in the month 2019-08 are 0.2 % _______________________________________________________ The historical data used to create the clusters is from 2017-09 to 2019-08 The portfolio_returns in the month 2019-09 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2017-10 to 2019-09 The portfolio_returns in the month 2019-10 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2017-11 to 2019-10 The portfolio_returns in the month 2019-11 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2017-12 to 2019-11 The portfolio_returns in the month 2019-12 are -0.12 % _______________________________________________________ The historical data used to create the clusters is from 2018-01 to 2019-12 The portfolio_returns in the month 2020-01 are 0.18 % _______________________________________________________ The historical data used to create the clusters is from 2018-02 to 2020-01 The portfolio_returns in the month 2020-02 are 0.15 % _______________________________________________________ The historical data used to create the clusters is from 2018-03 to 2020-02 The portfolio_returns in the month 2020-03 are 0.46 % _______________________________________________________ The historical data used to create the clusters is from 2018-04 to 2020-03 The portfolio_returns in the month 2020-04 are -0.3 % _______________________________________________________ The historical data used to create the clusters is from 2018-05 to 2020-04 The portfolio_returns in the month 2020-05 are 0.05 % _______________________________________________________ The historical data used to create the clusters is from 2018-06 to 2020-05 The portfolio_returns in the month 2020-06 are -0.2 % _______________________________________________________ The historical data used to create the clusters is from 2018-07 to 2020-06 The portfolio_returns in the month 2020-07 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2018-08 to 2020-07 The portfolio_returns in the month 2020-08 are 0.08 % _______________________________________________________ The historical data used to create the clusters is from 2018-09 to 2020-08 The portfolio_returns in the month 2020-09 are 0.2 % _______________________________________________________ The historical data used to create the clusters is from 2018-10 to 2020-09 The portfolio_returns in the month 2020-10 are 0.09 % _______________________________________________________ The historical data used to create the clusters is from 2018-11 to 2020-10 The portfolio_returns in the month 2020-11 are -0.3 % _______________________________________________________ The historical data used to create the clusters is from 2018-12 to 2020-11 The portfolio_returns in the month 2020-12 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2019-01 to 2020-12 The portfolio_returns in the month 2021-01 are 0.1 % _______________________________________________________ The historical data used to create the clusters is from 2019-02 to 2021-01 The portfolio_returns in the month 2021-02 are -0.3 % _______________________________________________________ The historical data used to create the clusters is from 2019-03 to 2021-02 The portfolio_returns in the month 2021-03 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2019-04 to 2021-03 The portfolio_returns in the month 2021-04 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2019-05 to 2021-04 The portfolio_returns in the month 2021-05 are -0.08 % _______________________________________________________ The historical data used to create the clusters is from 2019-06 to 2021-05 The portfolio_returns in the month 2021-06 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2019-07 to 2021-06 The portfolio_returns in the month 2021-07 are 0.03 % _______________________________________________________ The historical data used to create the clusters is from 2019-08 to 2021-07 The portfolio_returns in the month 2021-08 are 0.01 % _______________________________________________________ The historical data used to create the clusters is from 2019-09 to 2021-08 The portfolio_returns in the month 2021-09 are -0.13 % _______________________________________________________ The historical data used to create the clusters is from 2019-10 to 2021-09 The portfolio_returns in the month 2021-10 are 0.1 % _______________________________________________________ The historical data used to create the clusters is from 2019-11 to 2021-10 The portfolio_returns in the month 2021-11 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2019-12 to 2021-11 The portfolio_returns in the month 2021-12 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2020-01 to 2021-12 The portfolio_returns in the month 2022-01 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2020-02 to 2022-01 The portfolio_returns in the month 2022-02 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2020-03 to 2022-02 The portfolio_returns in the month 2022-03 are 0.08 % _______________________________________________________ The historical data used to create the clusters is from 2020-04 to 2022-03 The portfolio_returns in the month 2022-04 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2020-05 to 2022-04 The portfolio_returns in the month 2022-05 are 0.1 % _______________________________________________________ The historical data used to create the clusters is from 2020-06 to 2022-05 The portfolio_returns in the month 2022-06 are -0.08 % _______________________________________________________ The historical data used to create the clusters is from 2020-07 to 2022-06 The portfolio_returns in the month 2022-07 are -0.13 % _______________________________________________________ The historical data used to create the clusters is from 2020-08 to 2022-07 The portfolio_returns in the month 2022-08 are 0.14 % _______________________________________________________ The historical data used to create the clusters is from 2020-09 to 2022-08 The portfolio_returns in the month 2022-09 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2020-10 to 2022-09 The portfolio_returns in the month 2022-10 are 0.18 % _______________________________________________________ The historical data used to create the clusters is from 2020-11 to 2022-10 The portfolio_returns in the month 2022-11 are -0.06 % _______________________________________________________ The historical data used to create the clusters is from 2020-12 to 2022-11 The portfolio_returns in the month 2022-12 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2021-01 to 2022-12 The portfolio_returns in the month 2023-01 are -0.27 % _______________________________________________________ The historical data used to create the clusters is from 2021-02 to 2023-01 The portfolio_returns in the month 2023-02 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2021-03 to 2023-02 The portfolio_returns in the month 2023-03 are -0.15 % _______________________________________________________ The historical data used to create the clusters is from 2021-04 to 2023-03 The portfolio_returns in the month 2023-04 are 0.04 % _______________________________________________________ The historical data used to create the clusters is from 2021-05 to 2023-04 The portfolio_returns in the month 2023-05 are -0.05 % _______________________________________________________ The historical data used to create the clusters is from 2021-06 to 2023-05 The portfolio_returns in the month 2023-06 are -0.03 % _______________________________________________________ The historical data used to create the clusters is from 2021-07 to 2023-06 The portfolio_returns in the month 2023-07 are 0.05 % _______________________________________________________ The historical data used to create the clusters is from 2021-08 to 2023-07 The portfolio_returns in the month 2023-08 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2021-09 to 2023-08 The portfolio_returns in the month 2023-09 are 0.13 % _______________________________________________________ The historical data used to create the clusters is from 2021-10 to 2023-09 The portfolio_returns in the month 2023-10 are -0.05 % _______________________________________________________ The historical data used to create the clusters is from 2021-11 to 2023-10 The portfolio_returns in the month 2023-11 are -0.22 % _______________________________________________________ The historical data used to create the clusters is from 2021-12 to 2023-11 The portfolio_returns in the month 2023-12 are -0.1 % _______________________________________________________ The historical data used to create the clusters is from 2022-01 to 2023-12 The portfolio_returns in the month 2024-01 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2022-02 to 2024-01 The portfolio_returns in the month 2024-02 are 0.2 % _______________________________________________________ The historical data used to create the clusters is from 2022-03 to 2024-02 The portfolio_returns in the month 2024-03 are -0.02 % _______________________________________________________ The historical data used to create the clusters is from 2022-04 to 2024-03 The portfolio_returns in the month 2024-04 are 0.05 % _______________________________________________________ The historical data used to create the clusters is from 2022-05 to 2024-04 The portfolio_returns in the month 2024-05 are -0.01 % _______________________________________________________ The historical data used to create the clusters is from 2022-06 to 2024-05 The portfolio_returns in the month 2024-06 are 0.2 % _______________________________________________________ The historical data used to create the clusters is from 2022-07 to 2024-06 The portfolio_returns in the month 2024-07 are -0.1 % _______________________________________________________ The historical data used to create the clusters is from 2022-08 to 2024-07 The portfolio_returns in the month 2024-08 are -0.04 % _______________________________________________________ The historical data used to create the clusters is from 2022-09 to 2024-08 The portfolio_returns in the month 2024-09 are 0.07 % _______________________________________________________ The historical data used to create the clusters is from 2022-10 to 2024-09 The portfolio_returns in the month 2024-10 are 0.08 % _______________________________________________________ The historical data used to create the clusters is from 2022-11 to 2024-10 The portfolio_returns in the month 2024-11 are 0.09 % _______________________________________________________ The historical data used to create the clusters is from 2022-12 to 2024-11 The portfolio_returns in the month 2024-12 are -0.07 % _______________________________________________________ The historical data used to create the clusters is from 2023-01 to 2024-12 The portfolio_returns in the month 2025-01 are 0.07 % _______________________________________________________ The historical data used to create the clusters is from 2023-02 to 2025-01 The portfolio_returns in the month 2025-02 are -0.16 % _______________________________________________________ The historical data used to create the clusters is from 2023-03 to 2025-02 The portfolio_returns in the month 2025-03 are -0.09 % _______________________________________________________ The historical data used to create the clusters is from 2023-04 to 2025-03 The portfolio_returns in the month 2025-04 are 0.11 % _______________________________________________________ The historical data used to create the clusters is from 2023-05 to 2025-04 The portfolio_returns in the month 2025-05 are 0.15 % _______________________________________________________ The historical data used to create the clusters is from 2023-06 to 2025-05 The portfolio_returns in the month 2025-06 are -0.12 % _______________________________________________________ The historical data used to create the clusters is from 2023-07 to 2025-06 The portfolio_returns in the month 2025-07 are 0.12 % _______________________________________________________ The historical data used to create the clusters is from 2023-08 to 2025-07 The portfolio_returns in the month 2025-08 are -0.08 % _______________________________________________________ The historical data used to create the clusters is from 2023-09 to 2025-08 The portfolio_returns in the month 2025-09 are 0.46 % _______________________________________________________ The historical data used to create the clusters is from 2023-10 to 2025-09 The portfolio_returns in the month 2025-10 are 0.22 % _______________________________________________________ The historical data used to create the clusters is from 2023-11 to 2025-10 The portfolio_returns in the month 2025-11 are -0.01 % _______________________________________________________ The historical data used to create the clusters is from 2023-12 to 2025-11 The portfolio_returns in the month 2025-12 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2024-01 to 2025-12 The portfolio_returns in the month 2026-01 are 0.09 % _______________________________________________________ The historical data used to create the clusters is from 2024-02 to 2026-01 The portfolio_returns in the month 2026-02 are 0.06 % _______________________________________________________ The historical data used to create the clusters is from 2024-03 to 2026-02 The portfolio_returns in the month 2026-03 are 0.02 % _______________________________________________________ The historical data used to create the clusters is from 2024-04 to 2026-03 The portfolio_returns in the month 2026-04 are 0.68 % _______________________________________________________ The historical data used to create the clusters is from 2024-05 to 2026-04 The portfolio_returns in the month 2026-05 are 0.17 %
Performance Analysis¶
Pass the stock_monthly_returns data to the function plot_and_display_metrics_csmom to generate the performance metrics and related plots.
# Plot and display metrics for the given monthly returns of stocks in a portfolio
plot_and_display_metrics_csmom(stock_monthly_returns)
Performance Metrics:
| Metric | Value | |
|---|---|---|
| 0 | Sharpe Ratio | 0.8 |
| 1 | Maximum Drawdown Date | 2022-09-30 |
| 2 | Maximum Drawdown Value | -0.29 |
Conclusion¶
The CSMOM portfolio created based on clusters formed using monthly returns data of past 24 months and held for a month generated cumulative returns close to 10 times the initial capital with a Sharpe ratio of 0.8 and maximum drawdown of 29%.