-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsp500_pca_analysis.py
More file actions
executable file
·89 lines (79 loc) · 2.81 KB
/
Copy pathsp500_pca_analysis.py
File metadata and controls
executable file
·89 lines (79 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# Import necessary libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import yfinance as yf
from yahoo_fin import stock_info as si
from sklearn.decomposition import PCA
from pandas_datareader import data as pdr
from pylab import rcParams
yf.pdr_override()
# Set parameters
num_of_years = 1
start_date = datetime.date.today() - datetime.timedelta(days=int(365.25*num_of_years))
end_date = datetime.date.today()
# Get Tickers
tickers = si.tickers_sp500()
tickers = [item.replace('.', '-') for item in tickers]
# Get Market Data
index = '^GSPC'
market_prices = pdr.get_data_yahoo(index, start_date, end_date)['Adj Close']
# Calculate the log differences of prices
market_rs = market_prices.apply(np.log).diff(1)
# Read in stock data and collect returns
stock_prices = pdr.get_data_yahoo(tickers, start_date, end_date)['Adj Close']
# Calculate the log differences of prices
rs = stock_prices.apply(np.log).diff(1)
# Set the size of the plot
rcParams['figure.figsize'] = 15, 10
# Plot the daily returns of the stocks in the S&P500
plt.plot(rs)
plt.title('Daily Returns of the Stocks in the S&P500')
plt.show()
# Calculate the cumulative returns of the stocks in the S&P500
crs = rs.cumsum().apply(np.exp)
# Set the size of the plot
rcParams['figure.figsize'] = 15, 10
plt.subplots()
# Plot the cumulative returns of the stocks in the S&P500
plt.plot(crs)
plt.title('Cumulative Returns of the Stocks in the S&P500')
plt.show()
# Perform PCA on the stock returns data
pca = PCA(1).fit(rs.fillna(0))
pc1 = pd.Series(index=rs.columns, data=pca.components_[0])
# Set the size of the plot
rcParams['figure.figsize'] = 15, 10
plt.subplots()
# Plot the first principal component of the S&P500
plt.plot(pc1)
plt.title('First Principal Component of the S&P500')
plt.show()
# Find the weights of each stock that comprise the PCA portfolio
weights = abs(pc1)/sum(abs(pc1)) # l1 norm = 1
myrs = (weights*rs).sum(1)
rs_df = pd.concat([myrs, market_rs], 1)
rs_df.columns = ["PCA Portfolio", "S&P500"]
crs_df = rs_df.cumsum().apply(np.exp)
# Set the size of the plot
rcParams['figure.figsize'] = 15, 10
plt.subplots()
# Plot the PCA portfolio vs. the S&P500
plt.plot(crs_df)
plt.title('PCA Portfolio vs. S&P 500')
plt.show()
# Plot the stocks with the most and least negative PCA weights
fig, ax = plt.subplots(2, 1)
rcParams['figure.figsize'] = 15, 10
pc1.nsmallest(10).plot.bar(ax=ax[0], color='red', grid=True, title='Stocks with Most and Least Negative PCA Weights')
pc1.nlargest(10).plot.bar(ax=ax[1], color='green', grid=True)
# Plot best PCA Porfolio vs. S&P 500
myrs = rs[pc1.nlargest(10).index].mean(1)
mycrs = myrs.cumsum().apply(np.exp)
market_crs = market_rs.cumsum().apply(np.exp)
rcParams['figure.figsize'] = 15, 10
plt.subplots()
plt.plot(mycrs)
plt.plot(market_crs)
plt.title('PCA Selection vs. S&P500')
plt.legend(['PCA Selection', 'S&P500'])