Performance Analysis

Evaluation of the Ex-Post Performance of Securities and Rules-Based Strategies on an Absolute, Relative and Risk-Adjusted Basis.

Paul McAteer, MSc, MBA

pcm353@stern.nyu.edu


ContentsΒΆ

  1. Import libraries.
  2. Specify investment universe and historic time period.
  3. Define parameters for raw data import and storage.
  4. Import price data over sample period, save and perform preliminary inspection.
  5. Pass price data to dataframe. Clean data structure.
  6. Visualize asset price evolution. Calculate and inspect daily and monthly returns.
  7. Construct cap-weighted benchmark.
  8. Construct equal-weighted benchmark.
  9. Compute expected return vector and sample covariance matrix.
  10. Compute idiosyncratic risk statistics.
  11. Construct efficient frontier based on classical Markowitz model.
  12. Shrink covariance matrix.
  13. Construct efficient frontier based on robust covariance estimate.
  14. Design Risk Parity portfolio.
  15. Design Black-Litterman optimized portfolio.
  16. Create security weighting scheme for Black-Litterman portfolios..
  17. Generate strategy backtest returns applying security weighting schemes.
  18. Generate risk-adjusted performance metrics for strategies.

1) Import libraries.ΒΆ

In [7]:
# Import the python libraries
import pandas as pd
import numpy as np
import math
from datetime import datetime
import matplotlib.pyplot as plt

2) Specify investment universe and historic time period.ΒΆ

In [8]:
Securities = "MSFT AAPL AMZN GOOG NVDA BRK-A JNJ V PG JPM UNH MA INTC VZ HD T PFE MRK PEP WMT BAC XOM DIS KO CVX CSCO CMCSA WFC BA ADBE"
Start = "2016-05-30"
End   = "2020-06-30"

#Start = "2010-06-30"
#End   = "2020-06-30"

3) Define parameters for raw data import and storage.ΒΆ

In [9]:
# Select File Type for upload of Security Data
filetype =".csv"
# Specify Local Storage Location 
path = r"C:\Users\delga\Desktop\NYU\CQF_Work\Portfolio_Management"
# Convert data parameters to string for file naming purposes
Sec_Dates = Securities,Start, End
def convertTuple(tup): 
    str =  '_'.join(tup) 
    return str
conv = convertTuple(Sec_Dates)
# Converted data parameters + filetype = filename
filename = conv+filetype
# Join path, filename & filetype for single reference "File"
import os 
File = os.path.join(path,filename)
print(File)
C:\Users\delga\Desktop\NYU\CQF_Work\Portfolio_Management\MSFT AAPL AMZN GOOG NVDA BRK-A JNJ V PG JPM UNH MA INTC VZ HD T PFE MRK PEP WMT BAC XOM DIS KO CVX CSCO CMCSA WFC BA ADBE_2016-05-30_2020-06-30.csv

4) Import price data over sample period, save and perform preliminary inspection.ΒΆ

In [10]:
import yfinance as yf
data = yf.download(Securities, start=Start, end=End)
[*********************100%***********************]  30 of 30 completed
In [11]:
# View data
data
Out[11]:
Adj Close ... Volume
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-05-31 23.396452 99.470001 722.789978 114.231476 13.455158 211695.0 28.980476 25.153624 83.339264 93.608437 ... 6368700 34547300 6705000 27940000 3634100 8639600 15834500 19725000 8390200 13178800
2016-06-01 23.068445 100.040001 719.440002 114.466904 13.564697 212360.0 29.177340 25.023746 83.446510 92.948021 ... 4741400 24361200 6184100 17055700 2618000 4507000 10670800 16774300 7220900 7994800
2016-06-02 22.895067 100.169998 728.239990 114.865326 13.637724 212355.0 29.145294 25.179604 82.951439 93.136711 ... 3618200 31807700 5186300 12301700 4015000 5627500 8721100 14206700 6508700 9837500
2016-06-03 22.941923 98.699997 725.539978 115.345253 13.163051 211615.0 29.099510 25.222895 83.058708 93.165016 ... 4511700 28377600 6306700 19244900 3625600 7628000 9500700 25452600 6374500 9367100
2016-06-06 23.108265 99.120003 726.729980 119.438217 13.254335 212880.0 29.026255 25.196920 83.479523 93.193321 ... 2944200 21526800 5292300 16739100 2959900 7620100 10075600 14528500 9018000 8573000
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-06-23 91.310051 440.549988 2764.409912 187.880005 24.466021 272700.0 38.772812 44.702293 88.833359 116.589996 ... 3625600 37690400 5340400 38913000 4023400 9866800 20716400 47279100 6575900 18916600
2020-06-24 89.698242 431.679993 2734.399902 176.690002 23.498827 266440.0 38.139790 43.994450 85.141685 112.070000 ... 4853500 30817700 6547800 65596000 3399900 9453100 24794600 57380900 6871600 27626900
2020-06-25 90.889038 436.950012 2754.580078 174.880005 24.396935 267840.0 38.149681 44.456512 86.666924 111.360001 ... 4442000 27418700 5489300 36571300 3112500 9936600 17122500 45102200 6856600 19353600
2020-06-26 88.096405 426.920013 2692.870117 170.009995 22.847452 263400.0 38.228809 45.528111 83.995323 109.099998 ... 7372700 42154000 23201700 76576700 5043200 11836000 30211900 81172300 8997200 31518600
2020-06-29 90.126732 424.200012 2680.379883 194.490005 23.084316 265219.0 38.515648 45.370815 85.170822 111.519997 ... 4173900 23956300 6866900 37534500 2356700 8020400 15930300 43769200 5503800 17052100

1028 rows Γ— 180 columns

In [12]:
# Save data to named file
data.to_csv(File)
In [13]:
# Inspecting the first 3 lines and all columns lines of the saved CSV file
f =open(File,"r")
f.readlines()[:3]
Out[13]:
[',Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Adj Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,Close,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,High,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Low,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Open,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume,Volume\n',
 ',AAPL,ADBE,AMZN,BA,BAC,BRK-A,CMCSA,CSCO,CVX,DIS,GOOG,HD,INTC,JNJ,JPM,KO,MA,MRK,MSFT,NVDA,PEP,PFE,PG,T,UNH,V,VZ,WFC,WMT,XOM,AAPL,ADBE,AMZN,BA,BAC,BRK-A,CMCSA,CSCO,CVX,DIS,GOOG,HD,INTC,JNJ,JPM,KO,MA,MRK,MSFT,NVDA,PEP,PFE,PG,T,UNH,V,VZ,WFC,WMT,XOM,AAPL,ADBE,AMZN,BA,BAC,BRK-A,CMCSA,CSCO,CVX,DIS,GOOG,HD,INTC,JNJ,JPM,KO,MA,MRK,MSFT,NVDA,PEP,PFE,PG,T,UNH,V,VZ,WFC,WMT,XOM,AAPL,ADBE,AMZN,BA,BAC,BRK-A,CMCSA,CSCO,CVX,DIS,GOOG,HD,INTC,JNJ,JPM,KO,MA,MRK,MSFT,NVDA,PEP,PFE,PG,T,UNH,V,VZ,WFC,WMT,XOM,AAPL,ADBE,AMZN,BA,BAC,BRK-A,CMCSA,CSCO,CVX,DIS,GOOG,HD,INTC,JNJ,JPM,KO,MA,MRK,MSFT,NVDA,PEP,PFE,PG,T,UNH,V,VZ,WFC,WMT,XOM,AAPL,ADBE,AMZN,BA,BAC,BRK-A,CMCSA,CSCO,CVX,DIS,GOOG,HD,INTC,JNJ,JPM,KO,MA,MRK,MSFT,NVDA,PEP,PFE,PG,T,UNH,V,VZ,WFC,WMT,XOM\n',
 'Date,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,\n']

5) Pass price data to dataframe. Clean data structure.ΒΆ

In [14]:
#The filename passed to the pd.read_csv() function creates the daily price dataframe.
#Specified that the first two rows shall be handled as headers.
#Specified that the first column shall be handled as an index.
#Specified that the index values are of type datetime
df_csv = pd.read_csv(File, header= [0,1], index_col=0, parse_dates=True,)
df_csv.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1028 entries, 2016-05-31 to 2020-06-29
Columns: 180 entries, ('Adj Close', 'AAPL') to ('Volume', 'XOM')
dtypes: float64(150), int64(30)
memory usage: 1.4 MB
In [15]:
df_csv
Out[15]:
Adj Close ... Volume
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-05-31 23.396452 99.470001 722.789978 114.231476 13.455158 211695.0 28.980476 25.153624 83.339264 93.608437 ... 6368700 34547300 6705000 27940000 3634100 8639600 15834500 19725000 8390200 13178800
2016-06-01 23.068445 100.040001 719.440002 114.466904 13.564697 212360.0 29.177340 25.023746 83.446510 92.948021 ... 4741400 24361200 6184100 17055700 2618000 4507000 10670800 16774300 7220900 7994800
2016-06-02 22.895067 100.169998 728.239990 114.865326 13.637724 212355.0 29.145294 25.179604 82.951439 93.136711 ... 3618200 31807700 5186300 12301700 4015000 5627500 8721100 14206700 6508700 9837500
2016-06-03 22.941923 98.699997 725.539978 115.345253 13.163051 211615.0 29.099510 25.222895 83.058708 93.165016 ... 4511700 28377600 6306700 19244900 3625600 7628000 9500700 25452600 6374500 9367100
2016-06-06 23.108265 99.120003 726.729980 119.438217 13.254335 212880.0 29.026255 25.196920 83.479523 93.193321 ... 2944200 21526800 5292300 16739100 2959900 7620100 10075600 14528500 9018000 8573000
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-06-23 91.310051 440.549988 2764.409912 187.880005 24.466021 272700.0 38.772812 44.702293 88.833359 116.589996 ... 3625600 37690400 5340400 38913000 4023400 9866800 20716400 47279100 6575900 18916600
2020-06-24 89.698242 431.679993 2734.399902 176.690002 23.498827 266440.0 38.139790 43.994450 85.141685 112.070000 ... 4853500 30817700 6547800 65596000 3399900 9453100 24794600 57380900 6871600 27626900
2020-06-25 90.889038 436.950012 2754.580078 174.880005 24.396935 267840.0 38.149681 44.456512 86.666924 111.360001 ... 4442000 27418700 5489300 36571300 3112500 9936600 17122500 45102200 6856600 19353600
2020-06-26 88.096405 426.920013 2692.870117 170.009995 22.847452 263400.0 38.228809 45.528111 83.995323 109.099998 ... 7372700 42154000 23201700 76576700 5043200 11836000 30211900 81172300 8997200 31518600
2020-06-29 90.126732 424.200012 2680.379883 194.490005 23.084316 265219.0 38.515648 45.370815 85.170822 111.519997 ... 4173900 23956300 6866900 37534500 2356700 8020400 15930300 43769200 5503800 17052100

1028 rows Γ— 180 columns

In [16]:
# Define string and substring to count securities in portfolio. Reduce Dataframe to daily adj close for 30 securities
string = Securities
substring = " "
Sec_count = string.count(substring)+1

df_csv = df_csv.iloc[:,0:Sec_count]
df_csv
Out[16]:
Adj Close
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-05-31 23.396452 99.470001 722.789978 114.231476 13.455158 211695.0 28.980476 25.153624 83.339264 93.608437 ... 87.944633 27.820210 70.942688 30.285034 124.059410 76.602112 41.695221 43.575153 63.739830 71.519508
2016-06-01 23.068445 100.040001 719.440002 114.466904 13.564697 212360.0 29.177340 25.023746 83.446510 92.948021 ... 88.954414 27.860296 71.599236 29.960131 124.857597 76.873802 41.310215 43.815708 63.487690 71.696259
2016-06-02 22.895067 100.169998 728.239990 114.865326 13.637724 212355.0 29.145294 25.179604 82.951439 93.136711 ... 89.331017 27.956507 71.739296 30.045225 126.259026 77.582169 41.588726 43.910206 63.892910 71.125847
2016-06-03 22.941923 98.699997 725.539978 115.345253 13.163051 211615.0 29.099510 25.222895 83.058708 93.165016 ... 89.795204 27.812195 72.194511 30.331446 127.001511 77.572487 41.711597 43.119812 63.820892 70.997276
2016-06-06 23.108265 99.120003 726.729980 119.438217 13.254335 212880.0 29.026255 25.196920 83.479523 93.193321 ... 89.944069 28.004612 72.457123 30.432009 128.217346 78.154709 41.539574 43.377552 63.982983 71.776596
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-06-23 91.310051 440.549988 2764.409912 187.880005 24.466021 272700.0 38.772812 44.702293 88.833359 116.589996 ... 129.499603 30.476723 116.345726 29.196730 295.316254 197.373779 53.757511 26.994461 120.135170 44.717655
2020-06-24 89.698242 431.679993 2734.399902 176.690002 23.498827 266440.0 38.139790 43.994450 85.141685 112.070000 ... 127.725098 29.937311 115.051125 28.395628 286.960846 190.833527 52.769249 25.894064 119.371117 42.611038
2020-06-25 90.889038 436.950012 2754.580078 174.880005 24.396935 267840.0 38.149681 44.456512 86.666924 111.360001 ... 129.548904 30.058214 116.503845 28.685183 293.946838 193.395782 53.111717 27.133249 118.785667 43.252594
2020-06-26 88.096405 426.920013 2692.870117 170.009995 22.847452 263400.0 38.228809 45.528111 83.995323 109.099998 ... 127.104004 29.797808 113.875122 28.067467 284.678497 188.699966 52.015823 25.120810 117.406403 41.768391
2020-06-29 90.126732 424.200012 2680.379883 194.490005 23.084316 265219.0 38.515648 45.370815 85.170822 111.519997 ... 129.223572 30.355820 116.276558 28.868567 287.536407 190.803619 53.512894 25.477695 118.140686 42.438679

1028 rows Γ— 30 columns

In [17]:
# Check Column names
for col in df_csv.columns: 
    print(col)
('Adj Close', 'AAPL')
('Adj Close', 'ADBE')
('Adj Close', 'AMZN')
('Adj Close', 'BA')
('Adj Close', 'BAC')
('Adj Close', 'BRK-A')
('Adj Close', 'CMCSA')
('Adj Close', 'CSCO')
('Adj Close', 'CVX')
('Adj Close', 'DIS')
('Adj Close', 'GOOG')
('Adj Close', 'HD')
('Adj Close', 'INTC')
('Adj Close', 'JNJ')
('Adj Close', 'JPM')
('Adj Close', 'KO')
('Adj Close', 'MA')
('Adj Close', 'MRK')
('Adj Close', 'MSFT')
('Adj Close', 'NVDA')
('Adj Close', 'PEP')
('Adj Close', 'PFE')
('Adj Close', 'PG')
('Adj Close', 'T')
('Adj Close', 'UNH')
('Adj Close', 'V')
('Adj Close', 'VZ')
('Adj Close', 'WFC')
('Adj Close', 'WMT')
('Adj Close', 'XOM')
In [18]:
# Create single level header from multilevel header 
df_csv.columns = df_csv.columns.map('|'.join).str.strip('|')
df_csv.columns = df_csv.columns.str.replace(r'Adj Close|$', '')
df_csv.columns = df_csv.columns.str.lstrip('|')  # strip suffix at the right end only.
# Check column names 
print(df_csv.columns)
Index(['AAPL', 'ADBE', 'AMZN', 'BA', 'BAC', 'BRK-A', 'CMCSA', 'CSCO', 'CVX',
       'DIS', 'GOOG', 'HD', 'INTC', 'JNJ', 'JPM', 'KO', 'MA', 'MRK', 'MSFT',
       'NVDA', 'PEP', 'PFE', 'PG', 'T', 'UNH', 'V', 'VZ', 'WFC', 'WMT', 'XOM'],
      dtype='object')
In [19]:
# View Adj Close Dataframe
df_csv
Out[19]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-05-31 23.396452 99.470001 722.789978 114.231476 13.455158 211695.0 28.980476 25.153624 83.339264 93.608437 ... 87.944633 27.820210 70.942688 30.285034 124.059410 76.602112 41.695221 43.575153 63.739830 71.519508
2016-06-01 23.068445 100.040001 719.440002 114.466904 13.564697 212360.0 29.177340 25.023746 83.446510 92.948021 ... 88.954414 27.860296 71.599236 29.960131 124.857597 76.873802 41.310215 43.815708 63.487690 71.696259
2016-06-02 22.895067 100.169998 728.239990 114.865326 13.637724 212355.0 29.145294 25.179604 82.951439 93.136711 ... 89.331017 27.956507 71.739296 30.045225 126.259026 77.582169 41.588726 43.910206 63.892910 71.125847
2016-06-03 22.941923 98.699997 725.539978 115.345253 13.163051 211615.0 29.099510 25.222895 83.058708 93.165016 ... 89.795204 27.812195 72.194511 30.331446 127.001511 77.572487 41.711597 43.119812 63.820892 70.997276
2016-06-06 23.108265 99.120003 726.729980 119.438217 13.254335 212880.0 29.026255 25.196920 83.479523 93.193321 ... 89.944069 28.004612 72.457123 30.432009 128.217346 78.154709 41.539574 43.377552 63.982983 71.776596
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-06-23 91.310051 440.549988 2764.409912 187.880005 24.466021 272700.0 38.772812 44.702293 88.833359 116.589996 ... 129.499603 30.476723 116.345726 29.196730 295.316254 197.373779 53.757511 26.994461 120.135170 44.717655
2020-06-24 89.698242 431.679993 2734.399902 176.690002 23.498827 266440.0 38.139790 43.994450 85.141685 112.070000 ... 127.725098 29.937311 115.051125 28.395628 286.960846 190.833527 52.769249 25.894064 119.371117 42.611038
2020-06-25 90.889038 436.950012 2754.580078 174.880005 24.396935 267840.0 38.149681 44.456512 86.666924 111.360001 ... 129.548904 30.058214 116.503845 28.685183 293.946838 193.395782 53.111717 27.133249 118.785667 43.252594
2020-06-26 88.096405 426.920013 2692.870117 170.009995 22.847452 263400.0 38.228809 45.528111 83.995323 109.099998 ... 127.104004 29.797808 113.875122 28.067467 284.678497 188.699966 52.015823 25.120810 117.406403 41.768391
2020-06-29 90.126732 424.200012 2680.379883 194.490005 23.084316 265219.0 38.515648 45.370815 85.170822 111.519997 ... 129.223572 30.355820 116.276558 28.868567 287.536407 190.803619 53.512894 25.477695 118.140686 42.438679

1028 rows Γ— 30 columns

In [20]:
# View metadata
df_csv.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1028 entries, 2016-05-31 to 2020-06-29
Data columns (total 30 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   AAPL    1028 non-null   float64
 1   ADBE    1028 non-null   float64
 2   AMZN    1028 non-null   float64
 3   BA      1028 non-null   float64
 4   BAC     1028 non-null   float64
 5   BRK-A   1028 non-null   float64
 6   CMCSA   1028 non-null   float64
 7   CSCO    1028 non-null   float64
 8   CVX     1028 non-null   float64
 9   DIS     1028 non-null   float64
 10  GOOG    1028 non-null   float64
 11  HD      1028 non-null   float64
 12  INTC    1028 non-null   float64
 13  JNJ     1028 non-null   float64
 14  JPM     1028 non-null   float64
 15  KO      1028 non-null   float64
 16  MA      1028 non-null   float64
 17  MRK     1028 non-null   float64
 18  MSFT    1028 non-null   float64
 19  NVDA    1028 non-null   float64
 20  PEP     1028 non-null   float64
 21  PFE     1028 non-null   float64
 22  PG      1028 non-null   float64
 23  T       1028 non-null   float64
 24  UNH     1028 non-null   float64
 25  V       1028 non-null   float64
 26  VZ      1028 non-null   float64
 27  WFC     1028 non-null   float64
 28  WMT     1028 non-null   float64
 29  XOM     1028 non-null   float64
dtypes: float64(30)
memory usage: 249.0 KB
In [21]:
# Identify null values in dataset
df_csv.isnull().any()
Out[21]:
AAPL     False
ADBE     False
AMZN     False
BA       False
BAC      False
BRK-A    False
CMCSA    False
CSCO     False
CVX      False
DIS      False
GOOG     False
HD       False
INTC     False
JNJ      False
JPM      False
KO       False
MA       False
MRK      False
MSFT     False
NVDA     False
PEP      False
PFE      False
PG       False
T        False
UNH      False
V        False
VZ       False
WFC      False
WMT      False
XOM      False
dtype: bool
In [22]:
# Drop null values in dataset
df_csv = pd.DataFrame(df_csv.dropna().round(4))
df_csv.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1028 entries, 2016-05-31 to 2020-06-29
Data columns (total 30 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   AAPL    1028 non-null   float64
 1   ADBE    1028 non-null   float64
 2   AMZN    1028 non-null   float64
 3   BA      1028 non-null   float64
 4   BAC     1028 non-null   float64
 5   BRK-A   1028 non-null   float64
 6   CMCSA   1028 non-null   float64
 7   CSCO    1028 non-null   float64
 8   CVX     1028 non-null   float64
 9   DIS     1028 non-null   float64
 10  GOOG    1028 non-null   float64
 11  HD      1028 non-null   float64
 12  INTC    1028 non-null   float64
 13  JNJ     1028 non-null   float64
 14  JPM     1028 non-null   float64
 15  KO      1028 non-null   float64
 16  MA      1028 non-null   float64
 17  MRK     1028 non-null   float64
 18  MSFT    1028 non-null   float64
 19  NVDA    1028 non-null   float64
 20  PEP     1028 non-null   float64
 21  PFE     1028 non-null   float64
 22  PG      1028 non-null   float64
 23  T       1028 non-null   float64
 24  UNH     1028 non-null   float64
 25  V       1028 non-null   float64
 26  VZ      1028 non-null   float64
 27  WFC     1028 non-null   float64
 28  WMT     1028 non-null   float64
 29  XOM     1028 non-null   float64
dtypes: float64(30)
memory usage: 249.0 KB

6) Visualize asset price evolution. Calculate and inspect daily and monthly returns.ΒΆ

In [23]:
# Plot Daily Price Evolution
df_csv.plot(figsize=(12, 60), subplots=True);
In [24]:
# Calculate and plot daily returns
returns_daily = df_csv.pct_change()
returns_daily.plot(figsize=(12, 60), subplots=True);
In [25]:
# Calculate and plot monthly returns (from first day of each mth)
"""Date Offset
"""
# Take prices at start of month...
prices_BOM = df_csv.resample("BMS").first()
prices_BOM
Out[25]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-05-02 23.3965 99.47 722.7900 114.2315 13.4552 211695.0 28.9805 25.1536 83.3393 93.6084 ... 87.9446 27.8202 70.9427 30.2850 124.0594 76.6021 41.6952 43.5752 63.7398 71.5195
2016-06-01 23.0684 100.04 719.4400 114.4669 13.5647 212360.0 29.1773 25.0237 83.4465 92.9480 ... 88.9544 27.8603 71.5992 29.9601 124.8576 76.8738 41.3102 43.8157 63.4877 71.6963
2016-07-01 22.4663 95.32 725.6800 117.4370 11.9581 216298.0 30.0136 24.9372 85.9384 92.4857 ... 92.5101 28.5177 74.2167 33.6268 131.3278 72.2742 46.0613 40.4050 65.5679 75.3919
2016-08-01 24.8467 97.72 767.7400 120.6244 13.0809 215960.0 31.0527 26.8507 81.7797 90.7913 ... 95.4003 29.9127 76.2364 33.7765 133.7985 75.9422 45.0949 41.0751 66.4414 68.9807
2016-09-01 25.1415 102.90 770.6200 118.6020 14.6550 225350.0 30.2940 27.5934 83.5586 89.5749 ... 94.6286 28.0353 77.9127 32.0400 126.5543 79.0291 43.4897 43.6739 66.0440 70.3630
2016-10-03 26.5054 108.45 836.7400 120.8662 14.3340 215700.0 30.5587 27.7510 85.4264 87.8929 ... 95.4753 27.2269 78.2215 31.8913 129.7145 80.5455 42.9270 37.9581 65.2914 70.5332
2016-11-01 26.2628 106.87 785.4100 130.0239 15.2327 215370.0 28.3703 26.8524 88.7868 87.7979 ... 94.1171 25.1170 77.2161 28.9464 130.5948 79.3402 39.8850 39.8288 62.8342 67.7783
2016-12-01 25.9241 99.51 743.6500 141.2874 19.7904 239821.0 32.2530 25.9449 95.4109 94.0223 ... 87.9895 25.6859 72.7797 30.7832 151.3420 73.4774 41.7345 47.4522 64.0764 71.3130
2017-01-02 27.5010 103.48 753.6700 145.5337 20.7385 245850.0 32.0046 26.9052 99.2513 101.5844 ... 92.9830 26.9432 74.8601 34.0611 151.8217 77.4420 45.6761 48.9018 62.6995 74.2967
2017-02-01 30.4843 113.36 832.3500 152.0237 21.0699 245430.0 35.0452 27.1007 93.4823 106.5831 ... 91.5258 26.1208 78.2582 33.6881 153.0065 80.3059 40.9289 49.1548 60.4805 67.7981
2017-03-01 33.2417 120.35 853.0800 171.9776 23.5439 266013.0 34.8459 30.6016 96.8258 106.3342 ... 98.1663 28.3889 82.1384 33.6720 157.9246 86.8514 42.1300 52.5132 64.3341 68.4840
2017-04-03 34.1715 129.59 891.5100 165.1886 21.7804 250600.0 34.9650 29.8374 91.6563 108.4026 ... 100.0718 28.2405 80.3641 33.2956 156.2952 87.2125 41.5971 48.7855 66.0766 67.7004
2017-05-01 34.8564 135.11 948.2300 170.5563 21.7989 248270.0 36.4824 30.4469 90.0579 109.8678 ... 100.4476 27.8611 78.6408 31.6913 164.7900 89.0668 39.2689 47.8800 69.2043 67.6921
2017-06-01 36.5762 141.38 995.9500 176.5073 20.9627 250000.0 38.7818 28.5199 89.5568 103.6241 ... 105.5962 27.2397 79.5799 31.5049 169.4999 93.2725 39.8082 46.1088 73.9088 67.1989
2017-07-03 34.2648 138.41 953.6600 187.1268 22.8616 257980.0 35.8555 28.0807 91.3003 102.9059 ... 103.9839 28.1641 79.2277 30.8889 176.9006 91.2682 38.5157 49.3846 69.7878 68.3646
2017-08-01 35.8288 147.36 996.1900 225.6188 22.6486 264321.0 37.7062 28.6325 95.1482 106.7104 ... 104.4162 27.5478 82.9071 31.9234 182.1891 98.6206 42.3940 47.8795 74.5478 66.7575
2017-09-01 39.3256 155.06 978.2500 227.8082 22.4292 271062.0 38.3792 29.2206 94.3518 97.9215 ... 105.0744 28.5569 84.2085 30.7739 189.3163 101.7466 41.5529 45.4538 73.0318 64.3778
2017-10-02 36.8709 147.94 959.1900 242.6522 23.8538 278010.0 35.4910 30.5323 101.8732 96.3394 ... 98.9789 30.3312 83.5169 32.1122 187.8371 103.2547 42.8016 49.4669 73.1063 68.6321
2017-11-01 40.0064 176.25 1103.6801 245.0314 25.6321 280000.0 33.8653 31.5900 100.5459 95.5386 ... 99.8950 29.6501 79.6683 27.8930 199.3391 108.7680 41.9724 50.1268 81.9499 70.5155
2017-12-01 41.1510 179.52 1162.3500 258.6232 26.2743 291000.0 36.0710 34.3092 104.6482 101.5393 ... 106.6619 30.8460 82.8499 30.3455 216.4786 108.6271 44.9736 50.4680 90.7189 70.8202
2018-01-01 41.4421 177.70 1189.0100 282.8864 27.9573 295755.0 38.7017 35.4589 111.7147 108.7261 ... 107.8310 30.9223 83.1158 32.0416 211.1139 112.3354 46.9743 54.8593 92.8427 72.1524
2018-02-01 40.3643 199.38 1390.0000 340.1613 30.3884 325900.0 39.4744 38.3342 109.9546 107.4521 ... 109.8769 31.5428 79.3148 32.9883 224.5352 123.3325 48.1928 59.1793 99.3687 75.5805
2018-03-01 42.2729 206.03 1493.4500 334.8971 29.5451 302946.0 34.4329 40.2647 99.0838 99.7498 ... 99.4820 30.5151 72.7091 30.3263 214.2544 118.3191 42.5658 51.7717 83.8870 64.4636
2018-04-02 40.2631 212.28 1371.9900 308.7999 27.5085 293410.0 31.5870 37.6999 99.2607 95.9473 ... 98.4975 30.0184 71.5080 29.5681 208.0202 116.3439 41.8558 46.3877 81.0431 62.7663
2018-05-01 40.8477 224.08 1582.2600 315.5995 28.1092 292730.0 30.3835 41.5429 110.4213 97.3088 ... 91.2103 30.3181 67.0973 27.8017 226.8398 125.3062 43.8743 47.4808 82.8052 65.9638
2018-06-01 46.1315 251.31 1641.5400 343.3339 27.7057 289200.0 29.6253 40.4586 110.4832 96.6281 ... 93.0891 31.3492 68.4867 27.7419 233.0650 128.7952 42.9666 49.7769 79.1133 70.8581
2018-07-02 45.3895 243.26 1713.7800 323.4685 26.6502 283800.0 31.6185 39.6710 110.8400 102.4339 ... 101.7063 31.4183 72.8504 27.5198 237.8589 130.4193 45.3122 51.2605 80.0761 70.7975
2018-08-01 48.8619 248.01 1797.1700 339.5226 29.4491 301200.0 33.7442 39.0930 111.8570 110.7470 ... 105.4948 34.8257 75.8826 27.6784 243.5199 136.0789 47.0285 52.4710 84.1180 69.6112
2018-09-03 55.5695 266.68 2039.5100 334.9035 29.3454 317250.0 34.6784 44.5749 107.0573 108.6687 ... 103.0713 36.0816 77.8114 27.6437 258.0714 145.6977 48.3558 53.9093 91.4334 70.2417
2018-10-01 55.3018 275.49 2004.3600 369.7625 28.0764 321930.0 33.8586 45.6396 112.0288 113.9527 ... 103.6523 38.6109 78.7241 29.0580 259.5110 148.6451 48.9467 47.9041 90.5130 75.0708
2018-11-01 54.0753 245.28 1665.5300 351.1724 26.3340 308366.0 36.3695 42.9207 100.1225 113.8154 ... 104.4013 38.0876 85.0390 26.8486 251.6321 138.8268 51.5205 49.1051 96.4385 70.5741
2018-12-03 45.1313 255.26 1772.3600 349.7720 27.0253 330921.0 37.5195 45.8259 109.7406 113.4625 ... 111.3951 40.4205 88.5795 27.9228 277.0094 143.1941 53.4600 50.1309 94.6839 71.7756
2019-01-01 38.5626 224.57 1539.1300 314.6451 23.7674 304057.0 33.1218 40.3821 100.6645 107.6543 ... 103.1259 38.0123 86.6432 26.0120 235.5640 131.2645 51.4929 43.3839 89.9850 61.5863
2019-02-01 40.6626 247.38 1626.2300 376.4645 27.0240 313875.0 35.4539 44.8543 107.6489 109.9562 ... 105.8720 38.0163 93.2505 26.8549 259.9727 138.4045 50.6651 45.6145 90.4863 67.0919
2019-03-01 42.9093 264.01 1671.7300 430.3000 28.0520 304860.0 37.6800 48.7106 112.0930 112.6335 ... 110.5263 38.4419 94.1785 27.5890 238.1374 147.8661 52.9034 46.6590 94.4100 71.4823
2019-04-01 46.8993 272.17 1814.1899 382.3695 27.3151 307800.0 38.8461 52.0931 114.7660 111.1516 ... 116.0631 37.9808 99.1534 28.6005 238.4539 155.5725 54.8817 45.5212 94.8114 73.0282
2019-05-01 51.6275 283.35 1911.5200 367.9748 28.9612 325900.0 42.0622 52.9950 108.2166 134.7334 ... 121.0481 36.1456 101.0962 28.0030 225.2561 161.0431 53.0356 44.9803 98.2425 70.2939
2019-06-03 42.6634 259.03 1692.6899 332.8540 25.5349 299742.0 39.6792 49.3717 107.5931 130.8706 ... 122.7034 37.4948 100.0075 28.2759 229.7331 157.1394 52.9042 41.9217 99.3490 64.9631
2019-07-01 49.6180 300.97 1922.1899 350.1111 28.3094 321891.0 41.3744 52.1941 115.8024 139.9398 ... 126.3713 39.1495 106.4531 30.4041 236.6811 172.3382 53.1670 44.9067 107.7873 69.1927
2019-08-01 51.3118 298.44 1855.3199 328.3359 28.3768 303660.0 41.7444 53.1472 111.9992 141.0052 ... 121.8385 34.5323 113.1934 31.5007 243.1287 177.5200 52.3991 44.3134 106.5790 65.4873
2019-09-02 50.8321 282.45 1789.8400 350.2796 26.0289 301356.0 42.7179 44.6171 108.9615 135.4982 ... 131.7282 32.6093 117.6831 32.6640 224.9563 177.8059 55.0352 43.8886 112.2542 62.7330
2019-10-01 55.5001 272.71 1735.6500 370.5599 27.5468 310005.0 43.5438 45.8069 108.7179 128.7785 ... 132.5517 31.9864 120.0977 34.5381 212.8748 172.9341 56.7515 46.7168 115.3974 63.0899
2019-11-01 63.2176 277.82 1791.4399 341.1574 30.8013 323400.0 43.7687 45.4674 108.9053 131.9594 ... 132.1271 34.6587 120.8844 36.4560 247.1762 179.5224 57.8402 49.6878 115.1722 63.6846
2019-12-02 65.4746 302.75 1781.6000 353.0793 32.3801 330609.0 42.6733 43.2149 110.5368 149.7230 ... 131.1140 34.9025 119.7621 34.9303 274.0784 180.6779 57.4474 51.5476 116.7976 63.3599
2020-01-01 74.4446 334.43 1898.0100 331.3486 34.7091 342261.0 44.3751 47.1554 114.9185 148.2000 ... 131.9740 35.6773 120.4355 36.3717 287.7642 189.9508 58.4917 51.6726 116.9871 65.6565
2020-02-03 76.5043 358.00 2004.2000 314.1310 32.1089 334860.0 41.9217 45.3148 100.5809 141.3200 ... 138.4746 34.5408 122.8199 35.0564 269.5834 199.5815 56.1962 45.2989 112.3938 56.2386
2020-03-02 74.2387 360.28 1953.9500 289.2700 28.6029 324500.0 41.7841 40.0947 92.4789 119.9800 ... 133.6842 32.1190 117.3715 35.2651 268.6881 191.4302 55.4895 41.0602 113.9773 50.6115
2020-04-01 59.8535 301.21 1907.7000 130.7000 19.3765 261250.0 32.0667 37.3289 65.6419 94.9200 ... 115.5502 29.2367 107.3287 26.6053 234.4889 152.3937 51.2300 25.8156 112.7626 35.2534
2020-05-01 71.8188 343.84 2286.0400 133.3700 22.6206 273975.0 36.5770 40.2291 85.6332 105.5000 ... 127.3087 34.6605 115.4464 28.8589 281.1160 174.7486 55.6068 26.8067 121.4367 40.5231
2020-06-01 80.1794 389.68 2471.0400 151.3900 24.1202 275600.0 39.7421 45.5183 90.1449 118.7700 ... 130.0967 32.9785 115.8714 29.8531 302.2804 193.7647 54.5794 26.8557 123.0029 44.3155

50 rows Γ— 30 columns

In [26]:
# ...use to calculate monthly returns
ind_return = prices_BOM.pct_change()
ind_return
Out[26]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-05-02 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2016-06-01 -0.014023 0.005730 -0.004635 0.002061 0.008138 0.003141 0.006791 -0.005164 0.001286 -0.007055 ... 0.011482 0.001441 0.009254 -0.010728 0.006434 0.003547 -0.009234 0.005519 -0.003955 0.002472
2016-07-01 -0.026101 -0.047181 0.008673 0.025947 -0.118440 0.018544 0.028663 -0.003457 0.029862 -0.004974 ... 0.039972 0.023596 0.036558 0.122386 0.051821 -0.059833 0.115010 -0.077842 0.032765 0.051545
2016-08-01 0.105954 0.025178 0.057959 0.027141 0.093895 -0.001563 0.034621 0.076733 -0.048392 -0.018321 ... 0.031242 0.048917 0.027214 0.004452 0.018813 0.050751 -0.020981 0.016585 0.013322 -0.085038
2016-09-01 0.011865 0.053009 0.003751 -0.016766 0.120336 0.043480 -0.024433 0.027660 0.021752 -0.013398 ... -0.008089 -0.062763 0.021988 -0.051411 -0.054143 0.040648 -0.035596 0.063269 -0.005981 0.020039
2016-10-03 0.054249 0.053936 0.085801 0.019091 -0.021904 -0.042822 0.008738 0.005712 0.022353 -0.018778 ... 0.008948 -0.028835 0.003963 -0.004641 0.024971 0.019188 -0.012939 -0.130875 -0.011395 0.002419
2016-11-01 -0.009153 -0.014569 -0.061345 0.075767 0.062697 -0.001530 -0.071613 -0.032381 0.039337 -0.001081 ... -0.014226 -0.077493 -0.012853 -0.092342 0.006786 -0.014964 -0.070864 0.049283 -0.037634 -0.039058
2016-12-01 -0.012897 -0.068869 -0.053170 0.086626 0.299205 0.113530 0.136858 -0.033796 0.074607 0.070895 ... -0.065106 0.022650 -0.057454 0.063455 0.158867 -0.073894 0.046371 0.191404 0.019769 0.052151
2017-01-02 0.060828 0.039895 0.013474 0.030054 0.047907 0.025140 -0.007702 0.037013 0.040251 0.080429 ... 0.056751 0.048949 0.028585 0.106483 0.003170 0.053957 0.094445 0.030549 -0.021488 0.041839
2017-02-01 0.108480 0.095477 0.104396 0.044594 0.015980 -0.001708 0.095005 0.007266 -0.058125 0.049207 ... -0.015672 -0.030523 0.045393 -0.010951 0.007804 0.036981 -0.103932 0.005174 -0.035391 -0.087468
2017-03-01 0.090453 0.061662 0.024905 0.131255 0.117419 0.083865 -0.005687 0.129181 0.035766 -0.002335 ... 0.072553 0.086831 0.049582 -0.000478 0.032143 0.081507 0.029346 0.068323 0.063716 0.010117
2017-04-03 0.027971 0.076776 0.045049 -0.039476 -0.074903 -0.057941 0.003418 -0.024973 -0.053390 0.019452 ... 0.019411 -0.005227 -0.021601 -0.011178 -0.010318 0.004158 -0.012649 -0.070986 0.027085 -0.011442
2017-05-01 0.020043 0.042596 0.063622 0.032494 0.000849 -0.009298 0.043398 0.020427 -0.017439 0.013516 ... 0.003755 -0.013435 -0.021444 -0.048184 0.054351 0.021262 -0.055970 -0.018561 0.047334 -0.000123
2017-06-01 0.049340 0.046407 0.050325 0.034892 -0.038360 0.006968 0.063028 -0.063291 -0.005564 -0.056829 ... 0.051257 -0.022303 0.011942 -0.005882 0.028581 0.047220 0.013734 -0.036992 0.067980 -0.007286
2017-07-03 -0.063194 -0.021007 -0.042462 0.060165 0.090585 0.031920 -0.075455 -0.015400 0.019468 -0.006931 ... -0.015269 0.033936 -0.004426 -0.019553 0.043662 -0.021489 -0.032468 0.071045 -0.055758 0.017347
2017-08-01 0.045645 0.064663 0.044597 0.205700 -0.009317 0.024579 0.051616 0.019651 0.042146 0.036971 ... 0.004157 -0.021882 0.046441 0.033491 0.029895 0.080558 0.100694 -0.030477 0.068207 -0.023508
2017-09-01 0.097597 0.052253 -0.018009 0.009704 -0.009687 0.025503 0.017849 0.020540 -0.008370 -0.082362 ... 0.006304 0.036631 0.015697 -0.036008 0.039120 0.031697 -0.019840 -0.050663 -0.020336 -0.035647
2017-10-02 -0.062420 -0.045918 -0.019484 0.065160 0.063515 0.025633 -0.075254 0.044890 0.079717 -0.016157 ... -0.058011 0.062132 -0.008213 0.043488 -0.007813 0.014822 0.030051 0.088290 0.001020 0.066083
2017-11-01 0.085040 0.191361 0.150638 0.009805 0.074550 0.007158 -0.045806 0.034642 -0.013029 -0.008312 ... 0.009256 -0.022455 -0.046082 -0.131389 0.061234 0.053395 -0.019373 0.013340 0.120969 0.027442
2017-12-01 0.028610 0.018553 0.053158 0.055470 0.025055 0.039286 0.065132 0.086078 0.040800 0.062809 ... 0.067740 0.040334 0.039936 0.087925 0.085982 -0.001295 0.071504 0.006807 0.107004 0.004321
2018-01-01 0.007074 -0.010138 0.022936 0.093817 0.064055 0.016340 0.072931 0.033510 0.067526 0.070779 ... 0.010961 0.002474 0.003209 0.055893 -0.024782 0.034138 0.044486 0.087012 0.023411 0.018811
2018-02-01 -0.026007 0.122003 0.169040 0.202466 0.086958 0.101926 0.019966 0.081088 -0.015755 -0.011718 ... 0.018973 0.020066 -0.045731 0.029546 0.063574 0.097895 0.025940 0.078747 0.070291 0.047512
2018-03-01 0.047284 0.033353 0.074424 -0.015476 -0.027751 -0.070433 -0.127716 0.050360 -0.098866 -0.071681 ... -0.094605 -0.032581 -0.083285 -0.080695 -0.045787 -0.040649 -0.116760 -0.125172 -0.155801 -0.147087
2018-04-02 -0.047543 0.030335 -0.081328 -0.077926 -0.068932 -0.031478 -0.082651 -0.063698 0.001785 -0.038120 ... -0.009896 -0.016277 -0.016519 -0.025001 -0.029097 -0.016694 -0.016680 -0.103995 -0.033902 -0.026330
2018-05-01 0.014519 0.055587 0.153259 0.022019 0.021837 -0.002318 -0.038101 0.101937 0.112437 0.014190 ... -0.073984 0.009984 -0.061681 -0.059740 0.090470 0.077033 0.048225 0.023564 0.021743 0.050943
2018-06-01 0.129354 0.121519 0.037465 0.087878 -0.014355 -0.012059 -0.024954 -0.026101 0.000561 -0.006995 ... 0.020599 0.034009 0.020707 -0.002151 0.027443 0.027844 -0.020689 0.048358 -0.044585 0.074197
2018-07-02 -0.016084 -0.032032 0.044007 -0.057860 -0.038097 -0.018672 0.067280 -0.019467 0.003229 0.060084 ... 0.092569 0.002204 0.063716 -0.008006 0.020569 0.012610 0.054591 0.029805 0.012170 -0.000855
2018-08-01 0.076502 0.019526 0.048659 0.049631 0.105024 0.061311 0.067230 -0.014570 0.009175 0.081156 ... 0.037249 0.108453 0.041622 0.005763 0.023800 0.043395 0.037877 0.023615 0.050476 -0.016756
2018-09-03 0.137277 0.075279 0.134845 -0.013605 -0.003521 0.053287 0.027685 0.140227 -0.042909 -0.018766 ... -0.022973 0.036062 0.025418 -0.001254 0.059755 0.070685 0.028223 0.027411 0.086966 0.009057
2018-10-01 -0.004817 0.033036 -0.017235 0.104087 -0.043244 0.014752 -0.023640 0.023886 0.046438 0.048625 ... 0.005637 0.070099 0.011730 0.051162 0.005578 0.020230 0.012220 -0.111395 -0.010066 0.068750
2018-11-01 -0.022178 -0.109659 -0.169046 -0.050276 -0.062059 -0.042133 0.074158 -0.059573 -0.106279 -0.001205 ... 0.007226 -0.013553 0.080216 -0.076034 -0.030361 -0.066052 0.052584 0.025071 0.065466 -0.059899
2018-12-03 -0.165399 0.040688 0.064142 -0.003988 0.026251 0.073144 0.031620 0.067688 0.096063 -0.003101 ... 0.066990 0.061251 0.041634 0.040010 0.100851 0.031459 0.037645 0.020890 -0.018194 0.017025
2019-01-01 -0.145546 -0.120230 -0.131593 -0.100428 -0.120550 -0.081179 -0.117211 -0.118793 -0.082705 -0.051190 ... -0.074233 -0.059579 -0.021859 -0.068432 -0.149617 -0.083311 -0.036796 -0.134588 -0.049627 -0.141960
2019-02-01 0.054457 0.101572 0.056590 0.196473 0.137020 0.032290 0.070410 0.110747 0.069383 0.021382 ... 0.026629 0.000105 0.076259 0.032404 0.103618 0.054394 -0.016076 0.051415 0.005571 0.089397
2019-03-01 0.055252 0.067225 0.027979 0.143003 0.038040 -0.028722 0.062789 0.085974 0.041283 0.024349 ... 0.043962 0.011195 0.009952 0.027336 -0.083991 0.068362 0.044178 0.022898 0.043362 0.065439
2019-04-01 0.092987 0.030908 0.085217 -0.111389 -0.026269 0.009644 0.030947 0.069441 0.023846 -0.013157 ... 0.050095 -0.011995 0.052824 0.036663 0.001329 0.052117 0.037395 -0.024385 0.004252 0.021626
2019-05-01 0.100816 0.041077 0.053649 -0.037646 0.060263 0.058804 0.082791 0.017313 -0.057067 0.212159 ... 0.042951 -0.048319 0.019594 -0.020891 -0.055347 0.035164 -0.033638 -0.011882 0.036189 -0.037442
2019-06-03 -0.173630 -0.085830 -0.114480 -0.095443 -0.118307 -0.080264 -0.056654 -0.068371 -0.005762 -0.028670 ... 0.013675 0.037327 -0.010769 0.009745 0.019875 -0.024240 -0.002478 -0.067999 0.011263 -0.075836
2019-07-01 0.163011 0.161912 0.135583 0.051846 0.108655 0.073894 0.042723 0.057166 0.076300 0.069299 ... 0.029892 0.044131 0.064451 0.075266 0.030244 0.096722 0.004967 0.071204 0.084936 0.065108
2019-08-01 0.034137 -0.008406 -0.034788 -0.062195 0.002381 -0.056637 0.008943 0.018261 -0.032842 0.007613 ... -0.035869 -0.117938 0.063317 0.036068 0.027242 0.030068 -0.014443 -0.013212 -0.011210 -0.053552
2019-09-02 -0.009349 -0.053579 -0.035293 0.066833 -0.082740 -0.007587 0.023320 -0.160500 -0.027123 -0.039055 ... 0.081171 -0.055687 0.039664 0.036929 -0.074744 0.001611 0.050308 -0.009586 0.053249 -0.042059
2019-10-01 0.091832 -0.034484 -0.030276 0.057897 0.058316 0.028700 0.019334 0.026667 -0.002236 -0.049593 ... 0.006252 -0.019102 0.020518 0.057375 -0.053706 -0.027400 0.031185 0.064440 0.028001 0.005689
2019-11-01 0.139054 0.018738 0.032144 -0.079346 0.118144 0.043209 0.005165 -0.007412 0.001724 0.024701 ... -0.003203 0.083545 0.006551 0.055530 0.161134 0.038097 0.019184 0.063596 -0.001952 0.009426
2019-12-02 0.035702 0.089734 -0.005493 0.034945 0.051258 0.022291 -0.025027 -0.049541 0.014981 0.134614 ... -0.007668 0.007034 -0.009284 -0.041850 0.108838 0.006437 -0.006791 0.037430 0.014113 -0.005099
2020-01-01 0.137000 0.104641 0.065340 -0.061546 0.071927 0.035244 0.039880 0.091184 0.039640 -0.010172 ... 0.006559 0.022199 0.005623 0.041265 0.049934 0.051323 0.018178 0.002425 0.001622 0.036247
2020-02-03 0.027668 0.070478 0.055948 -0.051962 -0.074914 -0.021624 -0.055288 -0.039033 -0.124763 -0.046424 ... 0.049257 -0.031855 0.019798 -0.036163 -0.063180 0.050701 -0.039245 -0.123348 -0.039263 -0.143442
2020-03-02 -0.029614 0.006369 -0.025072 -0.079142 -0.109191 -0.030938 -0.003282 -0.115196 -0.080552 -0.151005 ... -0.034594 -0.070114 -0.044361 0.005953 -0.003321 -0.040842 -0.012576 -0.093572 0.014089 -0.100058
2020-04-01 -0.193770 -0.163956 -0.023670 -0.548173 -0.322569 -0.194915 -0.232562 -0.068982 -0.290196 -0.208868 ... -0.135648 -0.089738 -0.085564 -0.245563 -0.127282 -0.203920 -0.076762 -0.371274 -0.010657 -0.303451
2020-05-01 0.199910 0.141529 0.198323 0.020428 0.167424 0.048708 0.140654 0.077693 0.304551 0.111462 ... 0.101761 0.185513 0.075634 0.084705 0.198846 0.146692 0.085434 0.038392 0.076924 0.149481
2020-06-01 0.116412 0.133318 0.080926 0.135113 0.066294 0.005931 0.086533 0.131477 0.052686 0.125782 ... 0.021900 -0.048528 0.003681 0.034450 0.075287 0.108820 -0.018476 0.001828 0.012897 0.093586

50 rows Γ— 30 columns

In [27]:
# Remove null values (first month)
ind_return = ind_return.dropna().round(6)
ind_return
Out[27]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-06-01 -0.014023 0.005730 -0.004635 0.002061 0.008138 0.003141 0.006791 -0.005164 0.001286 -0.007055 ... 0.011482 0.001441 0.009254 -0.010728 0.006434 0.003547 -0.009234 0.005519 -0.003955 0.002472
2016-07-01 -0.026101 -0.047181 0.008673 0.025947 -0.118440 0.018544 0.028663 -0.003457 0.029862 -0.004974 ... 0.039972 0.023596 0.036558 0.122386 0.051821 -0.059833 0.115010 -0.077842 0.032765 0.051545
2016-08-01 0.105954 0.025178 0.057959 0.027141 0.093895 -0.001563 0.034621 0.076733 -0.048392 -0.018321 ... 0.031242 0.048917 0.027214 0.004452 0.018813 0.050751 -0.020981 0.016585 0.013322 -0.085038
2016-09-01 0.011865 0.053009 0.003751 -0.016766 0.120336 0.043480 -0.024433 0.027660 0.021752 -0.013398 ... -0.008089 -0.062763 0.021988 -0.051411 -0.054143 0.040648 -0.035596 0.063269 -0.005981 0.020039
2016-10-03 0.054249 0.053936 0.085801 0.019091 -0.021904 -0.042822 0.008738 0.005712 0.022353 -0.018778 ... 0.008948 -0.028835 0.003963 -0.004641 0.024971 0.019188 -0.012939 -0.130875 -0.011395 0.002419
2016-11-01 -0.009153 -0.014569 -0.061345 0.075767 0.062697 -0.001530 -0.071613 -0.032381 0.039337 -0.001081 ... -0.014226 -0.077493 -0.012853 -0.092342 0.006786 -0.014964 -0.070864 0.049283 -0.037634 -0.039058
2016-12-01 -0.012897 -0.068869 -0.053170 0.086626 0.299205 0.113530 0.136858 -0.033796 0.074607 0.070895 ... -0.065106 0.022650 -0.057454 0.063455 0.158867 -0.073894 0.046371 0.191404 0.019769 0.052151
2017-01-02 0.060828 0.039895 0.013474 0.030054 0.047907 0.025140 -0.007702 0.037013 0.040251 0.080429 ... 0.056751 0.048949 0.028585 0.106483 0.003170 0.053957 0.094445 0.030549 -0.021488 0.041839
2017-02-01 0.108480 0.095477 0.104396 0.044594 0.015980 -0.001708 0.095005 0.007266 -0.058125 0.049207 ... -0.015672 -0.030523 0.045393 -0.010951 0.007804 0.036981 -0.103932 0.005174 -0.035391 -0.087468
2017-03-01 0.090453 0.061662 0.024905 0.131255 0.117419 0.083865 -0.005687 0.129181 0.035766 -0.002335 ... 0.072553 0.086831 0.049582 -0.000478 0.032143 0.081507 0.029346 0.068323 0.063716 0.010117
2017-04-03 0.027971 0.076776 0.045049 -0.039476 -0.074903 -0.057941 0.003418 -0.024973 -0.053390 0.019452 ... 0.019411 -0.005227 -0.021601 -0.011178 -0.010318 0.004158 -0.012649 -0.070986 0.027085 -0.011442
2017-05-01 0.020043 0.042596 0.063622 0.032494 0.000849 -0.009298 0.043398 0.020427 -0.017439 0.013516 ... 0.003755 -0.013435 -0.021444 -0.048184 0.054351 0.021262 -0.055970 -0.018561 0.047334 -0.000123
2017-06-01 0.049340 0.046407 0.050325 0.034892 -0.038360 0.006968 0.063028 -0.063291 -0.005564 -0.056829 ... 0.051257 -0.022303 0.011942 -0.005882 0.028581 0.047220 0.013734 -0.036992 0.067980 -0.007286
2017-07-03 -0.063194 -0.021007 -0.042462 0.060165 0.090585 0.031920 -0.075455 -0.015400 0.019468 -0.006931 ... -0.015269 0.033936 -0.004426 -0.019553 0.043662 -0.021489 -0.032468 0.071045 -0.055758 0.017347
2017-08-01 0.045645 0.064663 0.044597 0.205700 -0.009317 0.024579 0.051616 0.019651 0.042146 0.036971 ... 0.004157 -0.021882 0.046441 0.033491 0.029895 0.080558 0.100694 -0.030477 0.068207 -0.023508
2017-09-01 0.097597 0.052253 -0.018009 0.009704 -0.009687 0.025503 0.017849 0.020540 -0.008370 -0.082362 ... 0.006304 0.036631 0.015697 -0.036008 0.039120 0.031697 -0.019840 -0.050663 -0.020336 -0.035647
2017-10-02 -0.062420 -0.045918 -0.019484 0.065160 0.063515 0.025633 -0.075254 0.044890 0.079717 -0.016157 ... -0.058011 0.062132 -0.008213 0.043488 -0.007813 0.014822 0.030051 0.088290 0.001020 0.066083
2017-11-01 0.085040 0.191361 0.150638 0.009805 0.074550 0.007158 -0.045806 0.034642 -0.013029 -0.008312 ... 0.009256 -0.022455 -0.046082 -0.131389 0.061234 0.053395 -0.019373 0.013340 0.120969 0.027442
2017-12-01 0.028610 0.018553 0.053158 0.055470 0.025055 0.039286 0.065132 0.086078 0.040800 0.062809 ... 0.067740 0.040334 0.039936 0.087925 0.085982 -0.001295 0.071504 0.006807 0.107004 0.004321
2018-01-01 0.007074 -0.010138 0.022936 0.093817 0.064055 0.016340 0.072931 0.033510 0.067526 0.070779 ... 0.010961 0.002474 0.003209 0.055893 -0.024782 0.034138 0.044486 0.087012 0.023411 0.018811
2018-02-01 -0.026007 0.122003 0.169040 0.202466 0.086958 0.101926 0.019966 0.081088 -0.015755 -0.011718 ... 0.018973 0.020066 -0.045731 0.029546 0.063574 0.097895 0.025940 0.078747 0.070291 0.047512
2018-03-01 0.047284 0.033353 0.074424 -0.015476 -0.027751 -0.070433 -0.127716 0.050360 -0.098866 -0.071681 ... -0.094605 -0.032581 -0.083285 -0.080695 -0.045787 -0.040649 -0.116760 -0.125172 -0.155801 -0.147087
2018-04-02 -0.047543 0.030335 -0.081328 -0.077926 -0.068932 -0.031478 -0.082651 -0.063698 0.001785 -0.038120 ... -0.009896 -0.016277 -0.016519 -0.025001 -0.029097 -0.016694 -0.016680 -0.103995 -0.033902 -0.026330
2018-05-01 0.014519 0.055587 0.153259 0.022019 0.021837 -0.002318 -0.038101 0.101937 0.112437 0.014190 ... -0.073984 0.009984 -0.061681 -0.059740 0.090470 0.077033 0.048225 0.023564 0.021743 0.050943
2018-06-01 0.129354 0.121519 0.037465 0.087878 -0.014355 -0.012059 -0.024954 -0.026101 0.000561 -0.006995 ... 0.020599 0.034009 0.020707 -0.002151 0.027443 0.027844 -0.020689 0.048358 -0.044585 0.074197
2018-07-02 -0.016084 -0.032032 0.044007 -0.057860 -0.038097 -0.018672 0.067280 -0.019467 0.003229 0.060084 ... 0.092569 0.002204 0.063716 -0.008006 0.020569 0.012610 0.054591 0.029805 0.012170 -0.000855
2018-08-01 0.076502 0.019526 0.048659 0.049631 0.105024 0.061311 0.067230 -0.014570 0.009175 0.081156 ... 0.037249 0.108453 0.041622 0.005763 0.023800 0.043395 0.037877 0.023615 0.050476 -0.016756
2018-09-03 0.137277 0.075279 0.134845 -0.013605 -0.003521 0.053287 0.027685 0.140227 -0.042909 -0.018766 ... -0.022973 0.036062 0.025418 -0.001254 0.059755 0.070685 0.028223 0.027411 0.086966 0.009057
2018-10-01 -0.004817 0.033036 -0.017235 0.104087 -0.043244 0.014752 -0.023640 0.023886 0.046438 0.048625 ... 0.005637 0.070099 0.011730 0.051162 0.005578 0.020230 0.012220 -0.111395 -0.010066 0.068750
2018-11-01 -0.022178 -0.109659 -0.169046 -0.050276 -0.062059 -0.042133 0.074158 -0.059573 -0.106279 -0.001205 ... 0.007226 -0.013553 0.080216 -0.076034 -0.030361 -0.066052 0.052584 0.025071 0.065466 -0.059899
2018-12-03 -0.165399 0.040688 0.064142 -0.003988 0.026251 0.073144 0.031620 0.067688 0.096063 -0.003101 ... 0.066990 0.061251 0.041634 0.040010 0.100851 0.031459 0.037645 0.020890 -0.018194 0.017025
2019-01-01 -0.145546 -0.120230 -0.131593 -0.100428 -0.120550 -0.081179 -0.117211 -0.118793 -0.082705 -0.051190 ... -0.074233 -0.059579 -0.021859 -0.068432 -0.149617 -0.083311 -0.036796 -0.134588 -0.049627 -0.141960
2019-02-01 0.054457 0.101572 0.056590 0.196473 0.137020 0.032290 0.070410 0.110747 0.069383 0.021382 ... 0.026629 0.000105 0.076259 0.032404 0.103618 0.054394 -0.016076 0.051415 0.005571 0.089397
2019-03-01 0.055252 0.067225 0.027979 0.143003 0.038040 -0.028722 0.062789 0.085974 0.041283 0.024349 ... 0.043962 0.011195 0.009952 0.027336 -0.083991 0.068362 0.044178 0.022898 0.043362 0.065439
2019-04-01 0.092987 0.030908 0.085217 -0.111389 -0.026269 0.009644 0.030947 0.069441 0.023846 -0.013157 ... 0.050095 -0.011995 0.052824 0.036663 0.001329 0.052117 0.037395 -0.024385 0.004252 0.021626
2019-05-01 0.100816 0.041077 0.053649 -0.037646 0.060263 0.058804 0.082791 0.017313 -0.057067 0.212159 ... 0.042951 -0.048319 0.019594 -0.020891 -0.055347 0.035164 -0.033638 -0.011882 0.036189 -0.037442
2019-06-03 -0.173630 -0.085830 -0.114480 -0.095443 -0.118307 -0.080264 -0.056654 -0.068371 -0.005762 -0.028670 ... 0.013675 0.037327 -0.010769 0.009745 0.019875 -0.024240 -0.002478 -0.067999 0.011263 -0.075836
2019-07-01 0.163011 0.161912 0.135583 0.051846 0.108655 0.073894 0.042723 0.057166 0.076300 0.069299 ... 0.029892 0.044131 0.064451 0.075266 0.030244 0.096722 0.004967 0.071204 0.084936 0.065108
2019-08-01 0.034137 -0.008406 -0.034788 -0.062195 0.002381 -0.056637 0.008943 0.018261 -0.032842 0.007613 ... -0.035869 -0.117938 0.063317 0.036068 0.027242 0.030068 -0.014443 -0.013212 -0.011210 -0.053552
2019-09-02 -0.009349 -0.053579 -0.035293 0.066833 -0.082740 -0.007587 0.023320 -0.160500 -0.027123 -0.039055 ... 0.081171 -0.055687 0.039664 0.036929 -0.074744 0.001611 0.050308 -0.009586 0.053249 -0.042059
2019-10-01 0.091832 -0.034484 -0.030276 0.057897 0.058316 0.028700 0.019334 0.026667 -0.002236 -0.049593 ... 0.006252 -0.019102 0.020518 0.057375 -0.053706 -0.027400 0.031185 0.064440 0.028001 0.005689
2019-11-01 0.139054 0.018738 0.032144 -0.079346 0.118144 0.043209 0.005165 -0.007412 0.001724 0.024701 ... -0.003203 0.083545 0.006551 0.055530 0.161134 0.038097 0.019184 0.063596 -0.001952 0.009426
2019-12-02 0.035702 0.089734 -0.005493 0.034945 0.051258 0.022291 -0.025027 -0.049541 0.014981 0.134614 ... -0.007668 0.007034 -0.009284 -0.041850 0.108838 0.006437 -0.006791 0.037430 0.014113 -0.005099
2020-01-01 0.137000 0.104641 0.065340 -0.061546 0.071927 0.035244 0.039880 0.091184 0.039640 -0.010172 ... 0.006559 0.022199 0.005623 0.041265 0.049934 0.051323 0.018178 0.002425 0.001622 0.036247
2020-02-03 0.027668 0.070478 0.055948 -0.051962 -0.074914 -0.021624 -0.055288 -0.039033 -0.124763 -0.046424 ... 0.049257 -0.031855 0.019798 -0.036163 -0.063180 0.050701 -0.039245 -0.123348 -0.039263 -0.143442
2020-03-02 -0.029614 0.006369 -0.025072 -0.079142 -0.109191 -0.030938 -0.003282 -0.115196 -0.080552 -0.151005 ... -0.034594 -0.070114 -0.044361 0.005953 -0.003321 -0.040842 -0.012576 -0.093572 0.014089 -0.100058
2020-04-01 -0.193770 -0.163956 -0.023670 -0.548173 -0.322569 -0.194915 -0.232562 -0.068982 -0.290196 -0.208868 ... -0.135648 -0.089738 -0.085564 -0.245563 -0.127282 -0.203920 -0.076762 -0.371274 -0.010657 -0.303451
2020-05-01 0.199910 0.141529 0.198323 0.020428 0.167424 0.048708 0.140654 0.077693 0.304551 0.111462 ... 0.101761 0.185513 0.075634 0.084705 0.198846 0.146692 0.085434 0.038392 0.076924 0.149481
2020-06-01 0.116412 0.133318 0.080926 0.135113 0.066294 0.005931 0.086533 0.131477 0.052686 0.125782 ... 0.021900 -0.048528 0.003681 0.034450 0.075287 0.108820 -0.018476 0.001828 0.012897 0.093586

49 rows Γ— 30 columns

In [28]:
# Format datetime index
ind_return.index = pd.to_datetime(ind_return.index, format="%Y%m").to_period('M')
ind_return
Out[28]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-06 -0.014023 0.005730 -0.004635 0.002061 0.008138 0.003141 0.006791 -0.005164 0.001286 -0.007055 ... 0.011482 0.001441 0.009254 -0.010728 0.006434 0.003547 -0.009234 0.005519 -0.003955 0.002472
2016-07 -0.026101 -0.047181 0.008673 0.025947 -0.118440 0.018544 0.028663 -0.003457 0.029862 -0.004974 ... 0.039972 0.023596 0.036558 0.122386 0.051821 -0.059833 0.115010 -0.077842 0.032765 0.051545
2016-08 0.105954 0.025178 0.057959 0.027141 0.093895 -0.001563 0.034621 0.076733 -0.048392 -0.018321 ... 0.031242 0.048917 0.027214 0.004452 0.018813 0.050751 -0.020981 0.016585 0.013322 -0.085038
2016-09 0.011865 0.053009 0.003751 -0.016766 0.120336 0.043480 -0.024433 0.027660 0.021752 -0.013398 ... -0.008089 -0.062763 0.021988 -0.051411 -0.054143 0.040648 -0.035596 0.063269 -0.005981 0.020039
2016-10 0.054249 0.053936 0.085801 0.019091 -0.021904 -0.042822 0.008738 0.005712 0.022353 -0.018778 ... 0.008948 -0.028835 0.003963 -0.004641 0.024971 0.019188 -0.012939 -0.130875 -0.011395 0.002419
2016-11 -0.009153 -0.014569 -0.061345 0.075767 0.062697 -0.001530 -0.071613 -0.032381 0.039337 -0.001081 ... -0.014226 -0.077493 -0.012853 -0.092342 0.006786 -0.014964 -0.070864 0.049283 -0.037634 -0.039058
2016-12 -0.012897 -0.068869 -0.053170 0.086626 0.299205 0.113530 0.136858 -0.033796 0.074607 0.070895 ... -0.065106 0.022650 -0.057454 0.063455 0.158867 -0.073894 0.046371 0.191404 0.019769 0.052151
2017-01 0.060828 0.039895 0.013474 0.030054 0.047907 0.025140 -0.007702 0.037013 0.040251 0.080429 ... 0.056751 0.048949 0.028585 0.106483 0.003170 0.053957 0.094445 0.030549 -0.021488 0.041839
2017-02 0.108480 0.095477 0.104396 0.044594 0.015980 -0.001708 0.095005 0.007266 -0.058125 0.049207 ... -0.015672 -0.030523 0.045393 -0.010951 0.007804 0.036981 -0.103932 0.005174 -0.035391 -0.087468
2017-03 0.090453 0.061662 0.024905 0.131255 0.117419 0.083865 -0.005687 0.129181 0.035766 -0.002335 ... 0.072553 0.086831 0.049582 -0.000478 0.032143 0.081507 0.029346 0.068323 0.063716 0.010117
2017-04 0.027971 0.076776 0.045049 -0.039476 -0.074903 -0.057941 0.003418 -0.024973 -0.053390 0.019452 ... 0.019411 -0.005227 -0.021601 -0.011178 -0.010318 0.004158 -0.012649 -0.070986 0.027085 -0.011442
2017-05 0.020043 0.042596 0.063622 0.032494 0.000849 -0.009298 0.043398 0.020427 -0.017439 0.013516 ... 0.003755 -0.013435 -0.021444 -0.048184 0.054351 0.021262 -0.055970 -0.018561 0.047334 -0.000123
2017-06 0.049340 0.046407 0.050325 0.034892 -0.038360 0.006968 0.063028 -0.063291 -0.005564 -0.056829 ... 0.051257 -0.022303 0.011942 -0.005882 0.028581 0.047220 0.013734 -0.036992 0.067980 -0.007286
2017-07 -0.063194 -0.021007 -0.042462 0.060165 0.090585 0.031920 -0.075455 -0.015400 0.019468 -0.006931 ... -0.015269 0.033936 -0.004426 -0.019553 0.043662 -0.021489 -0.032468 0.071045 -0.055758 0.017347
2017-08 0.045645 0.064663 0.044597 0.205700 -0.009317 0.024579 0.051616 0.019651 0.042146 0.036971 ... 0.004157 -0.021882 0.046441 0.033491 0.029895 0.080558 0.100694 -0.030477 0.068207 -0.023508
2017-09 0.097597 0.052253 -0.018009 0.009704 -0.009687 0.025503 0.017849 0.020540 -0.008370 -0.082362 ... 0.006304 0.036631 0.015697 -0.036008 0.039120 0.031697 -0.019840 -0.050663 -0.020336 -0.035647
2017-10 -0.062420 -0.045918 -0.019484 0.065160 0.063515 0.025633 -0.075254 0.044890 0.079717 -0.016157 ... -0.058011 0.062132 -0.008213 0.043488 -0.007813 0.014822 0.030051 0.088290 0.001020 0.066083
2017-11 0.085040 0.191361 0.150638 0.009805 0.074550 0.007158 -0.045806 0.034642 -0.013029 -0.008312 ... 0.009256 -0.022455 -0.046082 -0.131389 0.061234 0.053395 -0.019373 0.013340 0.120969 0.027442
2017-12 0.028610 0.018553 0.053158 0.055470 0.025055 0.039286 0.065132 0.086078 0.040800 0.062809 ... 0.067740 0.040334 0.039936 0.087925 0.085982 -0.001295 0.071504 0.006807 0.107004 0.004321
2018-01 0.007074 -0.010138 0.022936 0.093817 0.064055 0.016340 0.072931 0.033510 0.067526 0.070779 ... 0.010961 0.002474 0.003209 0.055893 -0.024782 0.034138 0.044486 0.087012 0.023411 0.018811
2018-02 -0.026007 0.122003 0.169040 0.202466 0.086958 0.101926 0.019966 0.081088 -0.015755 -0.011718 ... 0.018973 0.020066 -0.045731 0.029546 0.063574 0.097895 0.025940 0.078747 0.070291 0.047512
2018-03 0.047284 0.033353 0.074424 -0.015476 -0.027751 -0.070433 -0.127716 0.050360 -0.098866 -0.071681 ... -0.094605 -0.032581 -0.083285 -0.080695 -0.045787 -0.040649 -0.116760 -0.125172 -0.155801 -0.147087
2018-04 -0.047543 0.030335 -0.081328 -0.077926 -0.068932 -0.031478 -0.082651 -0.063698 0.001785 -0.038120 ... -0.009896 -0.016277 -0.016519 -0.025001 -0.029097 -0.016694 -0.016680 -0.103995 -0.033902 -0.026330
2018-05 0.014519 0.055587 0.153259 0.022019 0.021837 -0.002318 -0.038101 0.101937 0.112437 0.014190 ... -0.073984 0.009984 -0.061681 -0.059740 0.090470 0.077033 0.048225 0.023564 0.021743 0.050943
2018-06 0.129354 0.121519 0.037465 0.087878 -0.014355 -0.012059 -0.024954 -0.026101 0.000561 -0.006995 ... 0.020599 0.034009 0.020707 -0.002151 0.027443 0.027844 -0.020689 0.048358 -0.044585 0.074197
2018-07 -0.016084 -0.032032 0.044007 -0.057860 -0.038097 -0.018672 0.067280 -0.019467 0.003229 0.060084 ... 0.092569 0.002204 0.063716 -0.008006 0.020569 0.012610 0.054591 0.029805 0.012170 -0.000855
2018-08 0.076502 0.019526 0.048659 0.049631 0.105024 0.061311 0.067230 -0.014570 0.009175 0.081156 ... 0.037249 0.108453 0.041622 0.005763 0.023800 0.043395 0.037877 0.023615 0.050476 -0.016756
2018-09 0.137277 0.075279 0.134845 -0.013605 -0.003521 0.053287 0.027685 0.140227 -0.042909 -0.018766 ... -0.022973 0.036062 0.025418 -0.001254 0.059755 0.070685 0.028223 0.027411 0.086966 0.009057
2018-10 -0.004817 0.033036 -0.017235 0.104087 -0.043244 0.014752 -0.023640 0.023886 0.046438 0.048625 ... 0.005637 0.070099 0.011730 0.051162 0.005578 0.020230 0.012220 -0.111395 -0.010066 0.068750
2018-11 -0.022178 -0.109659 -0.169046 -0.050276 -0.062059 -0.042133 0.074158 -0.059573 -0.106279 -0.001205 ... 0.007226 -0.013553 0.080216 -0.076034 -0.030361 -0.066052 0.052584 0.025071 0.065466 -0.059899
2018-12 -0.165399 0.040688 0.064142 -0.003988 0.026251 0.073144 0.031620 0.067688 0.096063 -0.003101 ... 0.066990 0.061251 0.041634 0.040010 0.100851 0.031459 0.037645 0.020890 -0.018194 0.017025
2019-01 -0.145546 -0.120230 -0.131593 -0.100428 -0.120550 -0.081179 -0.117211 -0.118793 -0.082705 -0.051190 ... -0.074233 -0.059579 -0.021859 -0.068432 -0.149617 -0.083311 -0.036796 -0.134588 -0.049627 -0.141960
2019-02 0.054457 0.101572 0.056590 0.196473 0.137020 0.032290 0.070410 0.110747 0.069383 0.021382 ... 0.026629 0.000105 0.076259 0.032404 0.103618 0.054394 -0.016076 0.051415 0.005571 0.089397
2019-03 0.055252 0.067225 0.027979 0.143003 0.038040 -0.028722 0.062789 0.085974 0.041283 0.024349 ... 0.043962 0.011195 0.009952 0.027336 -0.083991 0.068362 0.044178 0.022898 0.043362 0.065439
2019-04 0.092987 0.030908 0.085217 -0.111389 -0.026269 0.009644 0.030947 0.069441 0.023846 -0.013157 ... 0.050095 -0.011995 0.052824 0.036663 0.001329 0.052117 0.037395 -0.024385 0.004252 0.021626
2019-05 0.100816 0.041077 0.053649 -0.037646 0.060263 0.058804 0.082791 0.017313 -0.057067 0.212159 ... 0.042951 -0.048319 0.019594 -0.020891 -0.055347 0.035164 -0.033638 -0.011882 0.036189 -0.037442
2019-06 -0.173630 -0.085830 -0.114480 -0.095443 -0.118307 -0.080264 -0.056654 -0.068371 -0.005762 -0.028670 ... 0.013675 0.037327 -0.010769 0.009745 0.019875 -0.024240 -0.002478 -0.067999 0.011263 -0.075836
2019-07 0.163011 0.161912 0.135583 0.051846 0.108655 0.073894 0.042723 0.057166 0.076300 0.069299 ... 0.029892 0.044131 0.064451 0.075266 0.030244 0.096722 0.004967 0.071204 0.084936 0.065108
2019-08 0.034137 -0.008406 -0.034788 -0.062195 0.002381 -0.056637 0.008943 0.018261 -0.032842 0.007613 ... -0.035869 -0.117938 0.063317 0.036068 0.027242 0.030068 -0.014443 -0.013212 -0.011210 -0.053552
2019-09 -0.009349 -0.053579 -0.035293 0.066833 -0.082740 -0.007587 0.023320 -0.160500 -0.027123 -0.039055 ... 0.081171 -0.055687 0.039664 0.036929 -0.074744 0.001611 0.050308 -0.009586 0.053249 -0.042059
2019-10 0.091832 -0.034484 -0.030276 0.057897 0.058316 0.028700 0.019334 0.026667 -0.002236 -0.049593 ... 0.006252 -0.019102 0.020518 0.057375 -0.053706 -0.027400 0.031185 0.064440 0.028001 0.005689
2019-11 0.139054 0.018738 0.032144 -0.079346 0.118144 0.043209 0.005165 -0.007412 0.001724 0.024701 ... -0.003203 0.083545 0.006551 0.055530 0.161134 0.038097 0.019184 0.063596 -0.001952 0.009426
2019-12 0.035702 0.089734 -0.005493 0.034945 0.051258 0.022291 -0.025027 -0.049541 0.014981 0.134614 ... -0.007668 0.007034 -0.009284 -0.041850 0.108838 0.006437 -0.006791 0.037430 0.014113 -0.005099
2020-01 0.137000 0.104641 0.065340 -0.061546 0.071927 0.035244 0.039880 0.091184 0.039640 -0.010172 ... 0.006559 0.022199 0.005623 0.041265 0.049934 0.051323 0.018178 0.002425 0.001622 0.036247
2020-02 0.027668 0.070478 0.055948 -0.051962 -0.074914 -0.021624 -0.055288 -0.039033 -0.124763 -0.046424 ... 0.049257 -0.031855 0.019798 -0.036163 -0.063180 0.050701 -0.039245 -0.123348 -0.039263 -0.143442
2020-03 -0.029614 0.006369 -0.025072 -0.079142 -0.109191 -0.030938 -0.003282 -0.115196 -0.080552 -0.151005 ... -0.034594 -0.070114 -0.044361 0.005953 -0.003321 -0.040842 -0.012576 -0.093572 0.014089 -0.100058
2020-04 -0.193770 -0.163956 -0.023670 -0.548173 -0.322569 -0.194915 -0.232562 -0.068982 -0.290196 -0.208868 ... -0.135648 -0.089738 -0.085564 -0.245563 -0.127282 -0.203920 -0.076762 -0.371274 -0.010657 -0.303451
2020-05 0.199910 0.141529 0.198323 0.020428 0.167424 0.048708 0.140654 0.077693 0.304551 0.111462 ... 0.101761 0.185513 0.075634 0.084705 0.198846 0.146692 0.085434 0.038392 0.076924 0.149481
2020-06 0.116412 0.133318 0.080926 0.135113 0.066294 0.005931 0.086533 0.131477 0.052686 0.125782 ... 0.021900 -0.048528 0.003681 0.034450 0.075287 0.108820 -0.018476 0.001828 0.012897 0.093586

49 rows Γ— 30 columns

In [29]:
# plot monthly returns
ind_return.plot.bar(figsize=(12, 60), subplots=True);
In [30]:
#prices_BOM.to_excel("mktcap_2008_2020.xlsx", sheet_name='Prices_BOM')

7) Construct cap-weighted benchmark.ΒΆ

In [31]:
#Import Monthly Market Capitalization data
ind_mktcap = pd.read_excel("mktcap_2008_2020.xlsx", sheet_name='Mkt_Cap', index_col=0, parse_dates=True)
In [32]:
#Slice by specified starting and ending dates
ind_mktcap =ind_mktcap.loc[Start:End]
ind_mktcap
Out[32]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-06-01 398650590000 4.816926e+10 3.597200e+11 6.477857e+10 120087600000 344660280000 1.339924e+11 106807500000 1.591727e+11 1.680536e+11 ... 1.251490e+11 1.647872e+11 1.832400e+11 2.179940e+11 1.194032e+11 1.640657e+11 1.728032e+11 1.807461e+11 1.803913e+11 3.050282e+11
2016-07-01 388256260000 4.589658e+10 3.628400e+11 6.645930e+10 105928800000 351051654000 1.378769e+11 106469100000 1.639164e+11 1.672219e+11 ... 1.301561e+11 1.686750e+11 1.899334e+11 2.447162e+11 1.255907e+11 1.542418e+11 1.926704e+11 1.666625e+11 1.863081e+11 3.207303e+11
2016-08-01 429402280000 4.705218e+10 3.838700e+11 6.825886e+10 115805000000 350503080000 1.426297e+11 114633000000 1.559855e+11 1.641483e+11 ... 1.342200e+11 1.768949e+11 1.950997e+11 2.457880e+11 1.279537e+11 1.620839e+11 1.886556e+11 1.694136e+11 1.887711e+11 2.934386e+11
2016-09-01 434491620000 4.954635e+10 3.853100e+11 6.711574e+10 129789000000 365743050000 1.391565e+11 117805500000 1.593765e+11 1.619426e+11 ... 1.331381e+11 1.657869e+11 1.994008e+11 2.331414e+11 1.210260e+11 1.686686e+11 1.819090e+11 1.801302e+11 1.876670e+11 2.993372e+11
2016-10-03 458040600000 5.221868e+10 4.183700e+11 6.840033e+10 126904800000 350081100000 1.403447e+11 118482300000 1.629343e+11 1.589051e+11 ... 1.343309e+11 1.610105e+11 2.001897e+11 2.320696e+11 1.240533e+11 1.719078e+11 1.795498e+11 1.565618e+11 1.855154e+11 3.000434e+11
2016-11-01 453856990000 5.145790e+10 3.927050e+11 7.357832e+10 134858200000 349545510000 1.302907e+11 114633000000 1.693457e+11 1.587424e+11 ... 1.324169e+11 1.485695e+11 1.975938e+11 2.106346e+11 1.248884e+11 1.693293e+11 1.668431e+11 1.642811e+11 1.785229e+11 2.883291e+11
2016-12-01 448034440000 4.791406e+10 3.718250e+11 7.995601e+10 175237000000 389229483000 1.481594e+11 110741400000 1.819831e+11 1.699882e+11 ... 1.237898e+11 1.519019e+11 1.862431e+11 2.239958e+11 1.447320e+11 1.568203e+11 1.745830e+11 1.957330e+11 1.820616e+11 3.033666e+11
2017-01-02 475249470000 4.982562e+10 3.768350e+11 8.235543e+10 183627400000 399014550000 1.470169e+11 114844500000 1.893025e+11 1.836566e+11 ... 1.308218e+11 1.593443e+11 1.915876e+11 2.478600e+11 1.451970e+11 1.652804e+11 1.910562e+11 2.017278e+11 1.781548e+11 3.160779e+11
2017-02-01 526832950000 5.458284e+10 4.161750e+11 8.602812e+10 186599000000 398332890000 1.609554e+11 115690500000 1.783142e+11 1.926966e+11 ... 1.287691e+11 1.544567e+11 2.002660e+11 2.451450e+11 1.463263e+11 1.713963e+11 1.711890e+11 2.027543e+11 1.718417e+11 2.884122e+11
2017-03-01 574491600000 5.794852e+10 4.265400e+11 9.732348e+10 208536400000 431739099000 1.600414e+11 130622400000 1.846885e+11 1.922446e+11 ... 1.381175e+11 1.678974e+11 2.101916e+11 2.450020e+11 1.510334e+11 1.853544e+11 1.762386e+11 2.165915e+11 1.827977e+11 2.913616e+11
2017-04-03 590535960000 6.239758e+10 4.457550e+11 9.348102e+10 192891800000 406723800000 1.605898e+11 127365300000 1.748306e+11 1.959872e+11 ... 1.407944e+11 1.670088e+11 2.056614e+11 2.422869e+11 1.494675e+11 1.861215e+11 1.740036e+11 2.012351e+11 1.877519e+11 2.879968e+11
2017-05-01 602396710000 6.505547e+10 4.741150e+11 9.651990e+10 193066600000 402942210000 1.675819e+11 129987900000 1.717731e+11 1.986450e+11 ... 1.413214e+11 1.647872e+11 2.012586e+11 2.305692e+11 1.575909e+11 1.900852e+11 1.642769e+11 1.974986e+11 1.966413e+11 2.879968e+11
2017-06-01 632113280000 6.807447e+10 4.979750e+11 9.988701e+10 185637600000 405750000000 1.781386e+11 121739400000 1.708095e+11 1.873450e+11 ... 1.485616e+11 1.611215e+11 2.036509e+11 2.292116e+11 1.620987e+11 1.990567e+11 1.665120e+11 1.901899e+11 2.100036e+11 2.858783e+11
2017-07-03 592174900000 6.664442e+10 4.768300e+11 1.058969e+11 202418400000 418701540000 1.647028e+11 119878200000 1.741449e+11 1.860613e+11 ... 1.463008e+11 1.665645e+11 2.027602e+11 2.247817e+11 1.691782e+11 1.947947e+11 1.611313e+11 2.036987e+11 1.982832e+11 2.908215e+11
2017-08-01 619174280000 7.095384e+10 4.980950e+11 1.276784e+11 200583000000 428992983000 1.732030e+11 122247000000 1.814828e+11 1.929317e+11 ... 1.469110e+11 1.628988e+11 2.121766e+11 2.322840e+11 1.742364e+11 2.104789e+11 1.773562e+11 1.974986e+11 2.118154e+11 2.840090e+11
2017-09-01 679599410000 7.466139e+10 4.891250e+11 1.289177e+11 198660200000 439933626000 1.762649e+11 124742700000 1.799634e+11 1.770394e+11 ... 1.478265e+11 1.688971e+11 2.155106e+11 2.239243e+11 1.810502e+11 2.171489e+11 1.738380e+11 1.874800e+11 2.075123e+11 2.738732e+11
2017-10-02 637202620000 7.123311e+10 4.795950e+11 1.373156e+11 211245800000 451210230000 1.630119e+11 130326300000 1.943056e+11 1.741827e+11 ... 1.392548e+11 1.793942e+11 2.137291e+11 2.336415e+11 1.796362e+11 2.203667e+11 1.790531e+11 2.040271e+11 2.077105e+11 2.919847e+11
2017-11-01 691373900000 8.486438e+10 5.518400e+11 1.386625e+11 226977800000 454440000000 1.555628e+11 134852400000 1.917855e+11 1.727363e+11 ... 1.405447e+11 1.753398e+11 2.038800e+11 2.029894e+11 1.906351e+11 2.321298e+11 1.755764e+11 2.067782e+11 2.328498e+11 3.000019e+11
2017-12-01 711170570000 8.643888e+10 5.811750e+11 1.463531e+11 232658800000 472293000000 1.656625e+11 146484900000 1.996052e+11 1.835843e+11 ... 1.500595e+11 1.824489e+11 2.120240e+11 2.207805e+11 2.070244e+11 2.318315e+11 1.881176e+11 2.081742e+11 2.577626e+11 3.012896e+11
2018-01-01 716173650000 8.556255e+10 5.945050e+11 1.600875e+11 247604200000 480010365000 1.777730e+11 151391700000 2.130765e+11 1.965838e+11 ... 1.517101e+11 1.828932e+11 2.127111e+11 2.331414e+11 2.018998e+11 2.397375e+11 1.964783e+11 2.262817e+11 2.637926e+11 3.069391e+11
2018-02-01 697584620000 9.600147e+10 6.950000e+11 1.924965e+11 269104600000 528935700000 1.812919e+11 163658700000 2.097225e+11 1.942696e+11 ... 1.545950e+11 1.865589e+11 2.029892e+11 2.400006e+11 2.147302e+11 2.632211e+11 2.016107e+11 2.441017e+11 2.823356e+11 3.215196e+11
2018-03-01 730535940000 9.920344e+10 7.467250e+11 1.895199e+11 261675600000 491681358000 1.581677e+11 171907200000 1.889875e+11 1.803480e+11 ... 1.399622e+11 1.804495e+11 1.860650e+11 2.206376e+11 2.048986e+11 2.525235e+11 1.780598e+11 2.135531e+11 2.383419e+11 2.742471e+11
2018-04-02 695816290000 1.022128e+11 6.859950e+11 1.747499e+11 243583800000 476204430000 1.450975e+11 160951500000 1.893210e+11 1.734776e+11 ... 1.385752e+11 1.775058e+11 1.830110e+11 2.151360e+11 1.989389e+11 2.483041e+11 1.750797e+11 1.913396e+11 2.302735e+11 2.670191e+11
2018-05-01 705908710000 1.078945e+11 7.911300e+11 1.785980e+11 248915200000 475100790000 1.395678e+11 177363900000 2.106120e+11 1.759365e+11 ... 1.283252e+11 1.792831e+11 1.717112e+11 2.022750e+11 2.169319e+11 2.674405e+11 1.835233e+11 1.958562e+11 2.352844e+11 2.806442e+11
2018-06-01 797214920000 1.210058e+11 8.207700e+11 1.942904e+11 245331800000 469371600000 1.360489e+11 172710900000 2.107417e+11 1.747070e+11 ... 1.309744e+11 1.853925e+11 1.752742e+11 2.018462e+11 2.228916e+11 2.748777e+11 1.797154e+11 2.053411e+11 2.247814e+11 3.014558e+11
2018-07-02 784405310000 1.171297e+11 8.568900e+11 1.830517e+11 235980000000 460607400000 1.452346e+11 169369200000 2.114088e+11 1.851934e+11 ... 1.430968e+11 1.858368e+11 1.864212e+11 2.002744e+11 2.274753e+11 2.783512e+11 1.895248e+11 2.114590e+11 2.275275e+11 3.012065e+11
2018-08-01 844399140000 1.194168e+11 8.985850e+11 1.921344e+11 260801600000 488847600000 1.549687e+11 166873500000 2.133544e+11 2.002360e+11 ... 1.484229e+11 2.059423e+11 1.941835e+11 2.014176e+11 2.328846e+11 2.904127e+11 1.967267e+11 2.164273e+11 2.390213e+11 2.961387e+11
2018-09-03 960332580000 1.284064e+11 1.019755e+12 1.895199e+11 259840200000 514896750000 1.592645e+11 190307700000 2.042006e+11 1.964754e+11 ... 1.450108e+11 2.133847e+11 1.991208e+11 2.011318e+11 2.468064e+11 3.109555e+11 2.022729e+11 2.223810e+11 2.598009e+11 2.988388e+11
2018-10-01 955717670000 1.326484e+11 1.002180e+12 2.092472e+11 248653000000 522492390000 1.555171e+11 194833800000 2.136880e+11 2.060216e+11 ... 1.458292e+11 2.283249e+11 2.014622e+11 2.114206e+11 2.481825e+11 3.172420e+11 2.047563e+11 1.975807e+11 2.571680e+11 3.193595e+11
2018-11-01 934497710000 1.181023e+11 8.327650e+11 1.987271e+11 233183200000 500478018000 1.670335e+11 183243600000 1.909702e+11 2.057866e+11 ... 1.468833e+11 2.252702e+11 2.176230e+11 1.953443e+11 2.406474e+11 2.962942e+11 2.155177e+11 2.025490e+11 2.740125e+11 3.002511e+11
2018-12-03 779962920000 1.229077e+11 8.861800e+11 1.979348e+11 239301200000 537084783000 1.723347e+11 195637500000 2.093149e+11 2.051357e+11 ... 1.567310e+11 2.390442e+11 2.266831e+11 2.032038e+11 2.649133e+11 3.056067e+11 2.236302e+11 2.067782e+11 2.690299e+11 3.053605e+11
2019-01-01 666444760000 1.081305e+11 7.695650e+11 1.780604e+11 210459200000 493484511000 1.521353e+11 172372500000 1.920079e+11 1.946312e+11 ... 1.450941e+11 2.248259e+11 2.217204e+11 1.892710e+11 2.252831e+11 2.801413e+11 2.153936e+11 1.789395e+11 2.556676e+11 2.619928e+11
2019-02-01 702717090000 1.191135e+11 8.131150e+11 2.130387e+11 239301200000 509419125000 1.628291e+11 191492100000 2.053309e+11 1.988077e+11 ... 1.489499e+11 2.248259e+11 2.386446e+11 1.954158e+11 2.486190e+11 2.953779e+11 2.119168e+11 1.881369e+11 2.571114e+11 2.854213e+11
2019-03-01 741534090000 1.271208e+11 8.358650e+11 2.435068e+11 248390800000 494787780000 1.730659e+11 207946800000 2.137991e+11 2.036350e+11 ... 1.554966e+11 2.273252e+11 2.410115e+11 2.007745e+11 2.277410e+11 3.155798e+11 2.213123e+11 1.924482e+11 2.682656e+11 3.041143e+11
2019-04-01 810498960000 1.310499e+11 9.070950e+11 2.163832e+11 241923200000 499559400000 1.784128e+11 222371100000 2.188949e+11 2.009592e+11 ... 1.632915e+11 2.246038e+11 2.537365e+11 2.081338e+11 2.280447e+11 3.320311e+11 2.295903e+11 1.877674e+11 2.693980e+11 3.106777e+11
2019-05-01 892230310000 1.364330e+11 9.557600e+11 2.082342e+11 256431600000 528935700000 1.931739e+11 226220400000 2.064057e+11 2.435918e+11 ... 1.703097e+11 2.137735e+11 2.587247e+11 2.037754e+11 2.154230e+11 3.437090e+11 2.218504e+11 1.855501e+11 2.791366e+11 2.990465e+11
2019-06-03 737307350000 1.247229e+11 8.463450e+11 1.883598e+11 226103800000 486481266000 1.822516e+11 210780900000 2.052198e+11 2.366130e+11 ... 1.726399e+11 2.217712e+11 2.559252e+11 2.057760e+11 2.197030e+11 3.353768e+11 2.213123e+11 1.729037e+11 2.822790e+11 2.763656e+11
2019-07-01 857467530000 1.449171e+11 9.610950e+11 1.981272e+11 250663200000 522429093000 1.900206e+11 222836400000 2.208776e+11 2.530115e+11 ... 1.777995e+11 2.315463e+11 2.724168e+11 2.212092e+11 2.263460e+11 3.678106e+11 2.223885e+11 1.852217e+11 3.062576e+11 2.943524e+11
2019-08-01 886752800000 1.436989e+11 9.276600e+11 1.858076e+11 251275000000 492840180000 1.917572e+11 226897200000 2.136324e+11 2.549461e+11 ... 1.714193e+11 2.042206e+11 2.896719e+11 2.292116e+11 2.325145e+11 3.788705e+11 2.192014e+11 1.827991e+11 3.028321e+11 2.786088e+11
2019-09-02 878471840000 1.359997e+11 8.949200e+11 1.982235e+11 230473800000 489100788000 1.961901e+11 190476900000 2.078325e+11 2.449840e+11 ... 1.853309e+11 1.928349e+11 3.011753e+11 2.376427e+11 2.151383e+11 3.794672e+11 2.302112e+11 1.810335e+11 3.189405e+11 2.668945e+11
2019-10-01 959124940000 1.313099e+11 8.678250e+11 2.096999e+11 243933400000 503138115000 1.999832e+11 195552900000 2.073692e+11 2.328342e+11 ... 1.864960e+11 1.891692e+11 3.073342e+11 2.512896e+11 2.035795e+11 3.690679e+11 2.374130e+11 1.926946e+11 3.278864e+11 2.683899e+11
2019-11-01 1092526030000 1.337703e+11 8.957200e+11 1.930624e+11 272775400000 524878200000 2.010343e+11 194114700000 2.077213e+11 2.385837e+11 ... 1.858996e+11 2.049981e+11 3.093702e+11 2.652939e+11 2.363864e+11 3.831325e+11 2.419659e+11 2.049715e+11 3.272353e+11 2.709239e+11
2019-12-02 1131515550000 1.457741e+11 8.908000e+11 1.998080e+11 286759400000 536578407000 1.960073e+11 184470300000 2.108343e+11 2.706938e+11 ... 1.844710e+11 2.064422e+11 3.064944e+11 2.541476e+11 2.621138e+11 3.856044e+11 2.403103e+11 2.126087e+11 3.318498e+11 2.695531e+11
2020-01-01 1286524770000 1.610280e+11 9.490050e+11 1.875110e+11 307385800000 555489603000 2.038220e+11 201305700000 2.191914e+11 2.679456e+11 ... 1.856777e+11 2.109965e+11 3.081995e+11 2.646508e+11 2.752005e+11 4.054014e+11 2.446563e+11 2.131425e+11 3.323877e+11 2.793150e+11
2020-02-03 1322150150000 1.723770e+11 1.002100e+12 1.777662e+11 284312200000 543477780000 1.925341e+11 193437900000 1.918411e+11 2.555066e+11 ... 1.948180e+11 2.042761e+11 3.143075e+11 2.550765e+11 2.578148e+11 4.259443e+11 2.350538e+11 1.868641e+11 3.193368e+11 2.392704e+11
2020-03-02 1282988110000 1.734748e+11 9.769750e+11 1.636979e+11 253285200000 526663500000 1.918943e+11 171145800000 1.763871e+11 2.169238e+11 ... 1.880772e+11 1.899468e+11 3.003609e+11 2.565769e+11 2.569607e+11 4.085553e+11 2.321151e+11 1.693725e+11 3.238381e+11 2.153018e+11
2020-04-01 1034386790000 1.450326e+11 9.538500e+11 7.396313e+10 171566200000 424008750000 1.472911e+11 159344100000 1.252072e+11 1.716154e+11 ... 1.625703e+11 1.728960e+11 2.746564e+11 1.935580e+11 2.242487e+11 3.252332e+11 2.143174e+11 1.064686e+11 3.203843e+11 1.499594e+11
2020-05-01 1241152010000 1.655590e+11 1.143020e+12 7.547408e+10 200320800000 444661425000 1.679932e+11 171738000000 1.633420e+11 1.907440e+11 ... 1.791172e+11 2.049981e+11 2.954490e+11 2.099916e+11 2.688422e+11 3.729463e+11 2.326118e+11 1.105746e+11 3.450423e+11 1.723910e+11
2020-06-01 1385637510000 1.876309e+11 1.235520e+12 8.567160e+10 213605600000 447298800000 1.825258e+11 194326200000 1.719399e+11 2.147362e+11 ... 1.830424e+11 1.950565e+11 2.965180e+11 2.172080e+11 2.890844e+11 4.135419e+11 2.283072e+11 1.107799e+11 3.494870e+11 1.885085e+11

49 rows Γ— 30 columns

In [33]:
# Datetime format for index to ensure consistency
ind_mktcap.index = pd.to_datetime(ind_mktcap.index, format="%Y%m").to_period('M')
ind_mktcap
Out[33]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-06 398650590000 4.816926e+10 3.597200e+11 6.477857e+10 120087600000 344660280000 1.339924e+11 106807500000 1.591727e+11 1.680536e+11 ... 1.251490e+11 1.647872e+11 1.832400e+11 2.179940e+11 1.194032e+11 1.640657e+11 1.728032e+11 1.807461e+11 1.803913e+11 3.050282e+11
2016-07 388256260000 4.589658e+10 3.628400e+11 6.645930e+10 105928800000 351051654000 1.378769e+11 106469100000 1.639164e+11 1.672219e+11 ... 1.301561e+11 1.686750e+11 1.899334e+11 2.447162e+11 1.255907e+11 1.542418e+11 1.926704e+11 1.666625e+11 1.863081e+11 3.207303e+11
2016-08 429402280000 4.705218e+10 3.838700e+11 6.825886e+10 115805000000 350503080000 1.426297e+11 114633000000 1.559855e+11 1.641483e+11 ... 1.342200e+11 1.768949e+11 1.950997e+11 2.457880e+11 1.279537e+11 1.620839e+11 1.886556e+11 1.694136e+11 1.887711e+11 2.934386e+11
2016-09 434491620000 4.954635e+10 3.853100e+11 6.711574e+10 129789000000 365743050000 1.391565e+11 117805500000 1.593765e+11 1.619426e+11 ... 1.331381e+11 1.657869e+11 1.994008e+11 2.331414e+11 1.210260e+11 1.686686e+11 1.819090e+11 1.801302e+11 1.876670e+11 2.993372e+11
2016-10 458040600000 5.221868e+10 4.183700e+11 6.840033e+10 126904800000 350081100000 1.403447e+11 118482300000 1.629343e+11 1.589051e+11 ... 1.343309e+11 1.610105e+11 2.001897e+11 2.320696e+11 1.240533e+11 1.719078e+11 1.795498e+11 1.565618e+11 1.855154e+11 3.000434e+11
2016-11 453856990000 5.145790e+10 3.927050e+11 7.357832e+10 134858200000 349545510000 1.302907e+11 114633000000 1.693457e+11 1.587424e+11 ... 1.324169e+11 1.485695e+11 1.975938e+11 2.106346e+11 1.248884e+11 1.693293e+11 1.668431e+11 1.642811e+11 1.785229e+11 2.883291e+11
2016-12 448034440000 4.791406e+10 3.718250e+11 7.995601e+10 175237000000 389229483000 1.481594e+11 110741400000 1.819831e+11 1.699882e+11 ... 1.237898e+11 1.519019e+11 1.862431e+11 2.239958e+11 1.447320e+11 1.568203e+11 1.745830e+11 1.957330e+11 1.820616e+11 3.033666e+11
2017-01 475249470000 4.982562e+10 3.768350e+11 8.235543e+10 183627400000 399014550000 1.470169e+11 114844500000 1.893025e+11 1.836566e+11 ... 1.308218e+11 1.593443e+11 1.915876e+11 2.478600e+11 1.451970e+11 1.652804e+11 1.910562e+11 2.017278e+11 1.781548e+11 3.160779e+11
2017-02 526832950000 5.458284e+10 4.161750e+11 8.602812e+10 186599000000 398332890000 1.609554e+11 115690500000 1.783142e+11 1.926966e+11 ... 1.287691e+11 1.544567e+11 2.002660e+11 2.451450e+11 1.463263e+11 1.713963e+11 1.711890e+11 2.027543e+11 1.718417e+11 2.884122e+11
2017-03 574491600000 5.794852e+10 4.265400e+11 9.732348e+10 208536400000 431739099000 1.600414e+11 130622400000 1.846885e+11 1.922446e+11 ... 1.381175e+11 1.678974e+11 2.101916e+11 2.450020e+11 1.510334e+11 1.853544e+11 1.762386e+11 2.165915e+11 1.827977e+11 2.913616e+11
2017-04 590535960000 6.239758e+10 4.457550e+11 9.348102e+10 192891800000 406723800000 1.605898e+11 127365300000 1.748306e+11 1.959872e+11 ... 1.407944e+11 1.670088e+11 2.056614e+11 2.422869e+11 1.494675e+11 1.861215e+11 1.740036e+11 2.012351e+11 1.877519e+11 2.879968e+11
2017-05 602396710000 6.505547e+10 4.741150e+11 9.651990e+10 193066600000 402942210000 1.675819e+11 129987900000 1.717731e+11 1.986450e+11 ... 1.413214e+11 1.647872e+11 2.012586e+11 2.305692e+11 1.575909e+11 1.900852e+11 1.642769e+11 1.974986e+11 1.966413e+11 2.879968e+11
2017-06 632113280000 6.807447e+10 4.979750e+11 9.988701e+10 185637600000 405750000000 1.781386e+11 121739400000 1.708095e+11 1.873450e+11 ... 1.485616e+11 1.611215e+11 2.036509e+11 2.292116e+11 1.620987e+11 1.990567e+11 1.665120e+11 1.901899e+11 2.100036e+11 2.858783e+11
2017-07 592174900000 6.664442e+10 4.768300e+11 1.058969e+11 202418400000 418701540000 1.647028e+11 119878200000 1.741449e+11 1.860613e+11 ... 1.463008e+11 1.665645e+11 2.027602e+11 2.247817e+11 1.691782e+11 1.947947e+11 1.611313e+11 2.036987e+11 1.982832e+11 2.908215e+11
2017-08 619174280000 7.095384e+10 4.980950e+11 1.276784e+11 200583000000 428992983000 1.732030e+11 122247000000 1.814828e+11 1.929317e+11 ... 1.469110e+11 1.628988e+11 2.121766e+11 2.322840e+11 1.742364e+11 2.104789e+11 1.773562e+11 1.974986e+11 2.118154e+11 2.840090e+11
2017-09 679599410000 7.466139e+10 4.891250e+11 1.289177e+11 198660200000 439933626000 1.762649e+11 124742700000 1.799634e+11 1.770394e+11 ... 1.478265e+11 1.688971e+11 2.155106e+11 2.239243e+11 1.810502e+11 2.171489e+11 1.738380e+11 1.874800e+11 2.075123e+11 2.738732e+11
2017-10 637202620000 7.123311e+10 4.795950e+11 1.373156e+11 211245800000 451210230000 1.630119e+11 130326300000 1.943056e+11 1.741827e+11 ... 1.392548e+11 1.793942e+11 2.137291e+11 2.336415e+11 1.796362e+11 2.203667e+11 1.790531e+11 2.040271e+11 2.077105e+11 2.919847e+11
2017-11 691373900000 8.486438e+10 5.518400e+11 1.386625e+11 226977800000 454440000000 1.555628e+11 134852400000 1.917855e+11 1.727363e+11 ... 1.405447e+11 1.753398e+11 2.038800e+11 2.029894e+11 1.906351e+11 2.321298e+11 1.755764e+11 2.067782e+11 2.328498e+11 3.000019e+11
2017-12 711170570000 8.643888e+10 5.811750e+11 1.463531e+11 232658800000 472293000000 1.656625e+11 146484900000 1.996052e+11 1.835843e+11 ... 1.500595e+11 1.824489e+11 2.120240e+11 2.207805e+11 2.070244e+11 2.318315e+11 1.881176e+11 2.081742e+11 2.577626e+11 3.012896e+11
2018-01 716173650000 8.556255e+10 5.945050e+11 1.600875e+11 247604200000 480010365000 1.777730e+11 151391700000 2.130765e+11 1.965838e+11 ... 1.517101e+11 1.828932e+11 2.127111e+11 2.331414e+11 2.018998e+11 2.397375e+11 1.964783e+11 2.262817e+11 2.637926e+11 3.069391e+11
2018-02 697584620000 9.600147e+10 6.950000e+11 1.924965e+11 269104600000 528935700000 1.812919e+11 163658700000 2.097225e+11 1.942696e+11 ... 1.545950e+11 1.865589e+11 2.029892e+11 2.400006e+11 2.147302e+11 2.632211e+11 2.016107e+11 2.441017e+11 2.823356e+11 3.215196e+11
2018-03 730535940000 9.920344e+10 7.467250e+11 1.895199e+11 261675600000 491681358000 1.581677e+11 171907200000 1.889875e+11 1.803480e+11 ... 1.399622e+11 1.804495e+11 1.860650e+11 2.206376e+11 2.048986e+11 2.525235e+11 1.780598e+11 2.135531e+11 2.383419e+11 2.742471e+11
2018-04 695816290000 1.022128e+11 6.859950e+11 1.747499e+11 243583800000 476204430000 1.450975e+11 160951500000 1.893210e+11 1.734776e+11 ... 1.385752e+11 1.775058e+11 1.830110e+11 2.151360e+11 1.989389e+11 2.483041e+11 1.750797e+11 1.913396e+11 2.302735e+11 2.670191e+11
2018-05 705908710000 1.078945e+11 7.911300e+11 1.785980e+11 248915200000 475100790000 1.395678e+11 177363900000 2.106120e+11 1.759365e+11 ... 1.283252e+11 1.792831e+11 1.717112e+11 2.022750e+11 2.169319e+11 2.674405e+11 1.835233e+11 1.958562e+11 2.352844e+11 2.806442e+11
2018-06 797214920000 1.210058e+11 8.207700e+11 1.942904e+11 245331800000 469371600000 1.360489e+11 172710900000 2.107417e+11 1.747070e+11 ... 1.309744e+11 1.853925e+11 1.752742e+11 2.018462e+11 2.228916e+11 2.748777e+11 1.797154e+11 2.053411e+11 2.247814e+11 3.014558e+11
2018-07 784405310000 1.171297e+11 8.568900e+11 1.830517e+11 235980000000 460607400000 1.452346e+11 169369200000 2.114088e+11 1.851934e+11 ... 1.430968e+11 1.858368e+11 1.864212e+11 2.002744e+11 2.274753e+11 2.783512e+11 1.895248e+11 2.114590e+11 2.275275e+11 3.012065e+11
2018-08 844399140000 1.194168e+11 8.985850e+11 1.921344e+11 260801600000 488847600000 1.549687e+11 166873500000 2.133544e+11 2.002360e+11 ... 1.484229e+11 2.059423e+11 1.941835e+11 2.014176e+11 2.328846e+11 2.904127e+11 1.967267e+11 2.164273e+11 2.390213e+11 2.961387e+11
2018-09 960332580000 1.284064e+11 1.019755e+12 1.895199e+11 259840200000 514896750000 1.592645e+11 190307700000 2.042006e+11 1.964754e+11 ... 1.450108e+11 2.133847e+11 1.991208e+11 2.011318e+11 2.468064e+11 3.109555e+11 2.022729e+11 2.223810e+11 2.598009e+11 2.988388e+11
2018-10 955717670000 1.326484e+11 1.002180e+12 2.092472e+11 248653000000 522492390000 1.555171e+11 194833800000 2.136880e+11 2.060216e+11 ... 1.458292e+11 2.283249e+11 2.014622e+11 2.114206e+11 2.481825e+11 3.172420e+11 2.047563e+11 1.975807e+11 2.571680e+11 3.193595e+11
2018-11 934497710000 1.181023e+11 8.327650e+11 1.987271e+11 233183200000 500478018000 1.670335e+11 183243600000 1.909702e+11 2.057866e+11 ... 1.468833e+11 2.252702e+11 2.176230e+11 1.953443e+11 2.406474e+11 2.962942e+11 2.155177e+11 2.025490e+11 2.740125e+11 3.002511e+11
2018-12 779962920000 1.229077e+11 8.861800e+11 1.979348e+11 239301200000 537084783000 1.723347e+11 195637500000 2.093149e+11 2.051357e+11 ... 1.567310e+11 2.390442e+11 2.266831e+11 2.032038e+11 2.649133e+11 3.056067e+11 2.236302e+11 2.067782e+11 2.690299e+11 3.053605e+11
2019-01 666444760000 1.081305e+11 7.695650e+11 1.780604e+11 210459200000 493484511000 1.521353e+11 172372500000 1.920079e+11 1.946312e+11 ... 1.450941e+11 2.248259e+11 2.217204e+11 1.892710e+11 2.252831e+11 2.801413e+11 2.153936e+11 1.789395e+11 2.556676e+11 2.619928e+11
2019-02 702717090000 1.191135e+11 8.131150e+11 2.130387e+11 239301200000 509419125000 1.628291e+11 191492100000 2.053309e+11 1.988077e+11 ... 1.489499e+11 2.248259e+11 2.386446e+11 1.954158e+11 2.486190e+11 2.953779e+11 2.119168e+11 1.881369e+11 2.571114e+11 2.854213e+11
2019-03 741534090000 1.271208e+11 8.358650e+11 2.435068e+11 248390800000 494787780000 1.730659e+11 207946800000 2.137991e+11 2.036350e+11 ... 1.554966e+11 2.273252e+11 2.410115e+11 2.007745e+11 2.277410e+11 3.155798e+11 2.213123e+11 1.924482e+11 2.682656e+11 3.041143e+11
2019-04 810498960000 1.310499e+11 9.070950e+11 2.163832e+11 241923200000 499559400000 1.784128e+11 222371100000 2.188949e+11 2.009592e+11 ... 1.632915e+11 2.246038e+11 2.537365e+11 2.081338e+11 2.280447e+11 3.320311e+11 2.295903e+11 1.877674e+11 2.693980e+11 3.106777e+11
2019-05 892230310000 1.364330e+11 9.557600e+11 2.082342e+11 256431600000 528935700000 1.931739e+11 226220400000 2.064057e+11 2.435918e+11 ... 1.703097e+11 2.137735e+11 2.587247e+11 2.037754e+11 2.154230e+11 3.437090e+11 2.218504e+11 1.855501e+11 2.791366e+11 2.990465e+11
2019-06 737307350000 1.247229e+11 8.463450e+11 1.883598e+11 226103800000 486481266000 1.822516e+11 210780900000 2.052198e+11 2.366130e+11 ... 1.726399e+11 2.217712e+11 2.559252e+11 2.057760e+11 2.197030e+11 3.353768e+11 2.213123e+11 1.729037e+11 2.822790e+11 2.763656e+11
2019-07 857467530000 1.449171e+11 9.610950e+11 1.981272e+11 250663200000 522429093000 1.900206e+11 222836400000 2.208776e+11 2.530115e+11 ... 1.777995e+11 2.315463e+11 2.724168e+11 2.212092e+11 2.263460e+11 3.678106e+11 2.223885e+11 1.852217e+11 3.062576e+11 2.943524e+11
2019-08 886752800000 1.436989e+11 9.276600e+11 1.858076e+11 251275000000 492840180000 1.917572e+11 226897200000 2.136324e+11 2.549461e+11 ... 1.714193e+11 2.042206e+11 2.896719e+11 2.292116e+11 2.325145e+11 3.788705e+11 2.192014e+11 1.827991e+11 3.028321e+11 2.786088e+11
2019-09 878471840000 1.359997e+11 8.949200e+11 1.982235e+11 230473800000 489100788000 1.961901e+11 190476900000 2.078325e+11 2.449840e+11 ... 1.853309e+11 1.928349e+11 3.011753e+11 2.376427e+11 2.151383e+11 3.794672e+11 2.302112e+11 1.810335e+11 3.189405e+11 2.668945e+11
2019-10 959124940000 1.313099e+11 8.678250e+11 2.096999e+11 243933400000 503138115000 1.999832e+11 195552900000 2.073692e+11 2.328342e+11 ... 1.864960e+11 1.891692e+11 3.073342e+11 2.512896e+11 2.035795e+11 3.690679e+11 2.374130e+11 1.926946e+11 3.278864e+11 2.683899e+11
2019-11 1092526030000 1.337703e+11 8.957200e+11 1.930624e+11 272775400000 524878200000 2.010343e+11 194114700000 2.077213e+11 2.385837e+11 ... 1.858996e+11 2.049981e+11 3.093702e+11 2.652939e+11 2.363864e+11 3.831325e+11 2.419659e+11 2.049715e+11 3.272353e+11 2.709239e+11
2019-12 1131515550000 1.457741e+11 8.908000e+11 1.998080e+11 286759400000 536578407000 1.960073e+11 184470300000 2.108343e+11 2.706938e+11 ... 1.844710e+11 2.064422e+11 3.064944e+11 2.541476e+11 2.621138e+11 3.856044e+11 2.403103e+11 2.126087e+11 3.318498e+11 2.695531e+11
2020-01 1286524770000 1.610280e+11 9.490050e+11 1.875110e+11 307385800000 555489603000 2.038220e+11 201305700000 2.191914e+11 2.679456e+11 ... 1.856777e+11 2.109965e+11 3.081995e+11 2.646508e+11 2.752005e+11 4.054014e+11 2.446563e+11 2.131425e+11 3.323877e+11 2.793150e+11
2020-02 1322150150000 1.723770e+11 1.002100e+12 1.777662e+11 284312200000 543477780000 1.925341e+11 193437900000 1.918411e+11 2.555066e+11 ... 1.948180e+11 2.042761e+11 3.143075e+11 2.550765e+11 2.578148e+11 4.259443e+11 2.350538e+11 1.868641e+11 3.193368e+11 2.392704e+11
2020-03 1282988110000 1.734748e+11 9.769750e+11 1.636979e+11 253285200000 526663500000 1.918943e+11 171145800000 1.763871e+11 2.169238e+11 ... 1.880772e+11 1.899468e+11 3.003609e+11 2.565769e+11 2.569607e+11 4.085553e+11 2.321151e+11 1.693725e+11 3.238381e+11 2.153018e+11
2020-04 1034386790000 1.450326e+11 9.538500e+11 7.396313e+10 171566200000 424008750000 1.472911e+11 159344100000 1.252072e+11 1.716154e+11 ... 1.625703e+11 1.728960e+11 2.746564e+11 1.935580e+11 2.242487e+11 3.252332e+11 2.143174e+11 1.064686e+11 3.203843e+11 1.499594e+11
2020-05 1241152010000 1.655590e+11 1.143020e+12 7.547408e+10 200320800000 444661425000 1.679932e+11 171738000000 1.633420e+11 1.907440e+11 ... 1.791172e+11 2.049981e+11 2.954490e+11 2.099916e+11 2.688422e+11 3.729463e+11 2.326118e+11 1.105746e+11 3.450423e+11 1.723910e+11
2020-06 1385637510000 1.876309e+11 1.235520e+12 8.567160e+10 213605600000 447298800000 1.825258e+11 194326200000 1.719399e+11 2.147362e+11 ... 1.830424e+11 1.950565e+11 2.965180e+11 2.172080e+11 2.890844e+11 4.135419e+11 2.283072e+11 1.107799e+11 3.494870e+11 1.885085e+11

49 rows Γ— 30 columns

In [34]:
# Compute and inspect price evolution of benchmark expressed in terms of capitalization
total_mktcap = ind_mktcap.sum(axis="columns")
In [35]:
total_mktcap.plot(figsize=(12,6), title='Evolution of Market Capitalization of Index' );
In [36]:
 # Compute benchmark capweights by dividing the total mkt cap at each date by each security mkt cap
ind_capweight = ind_mktcap.divide(total_mktcap, axis="rows")
ind_capweight = ind_capweight.iloc[0:]
ind_capweight
Out[36]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-06 0.070701 0.008543 0.063797 0.011489 0.021298 0.061126 0.023764 0.018942 0.028230 0.029805 ... 0.022195 0.029225 0.032498 0.038662 0.021176 0.029097 0.030647 0.032056 0.031993 0.054097
2016-07 0.068551 0.008104 0.064063 0.011734 0.018703 0.061982 0.024344 0.018798 0.028941 0.029525 ... 0.022980 0.029781 0.033535 0.043207 0.022174 0.027233 0.034018 0.029426 0.032895 0.056628
2016-08 0.073225 0.008024 0.065461 0.011640 0.019748 0.059771 0.024322 0.019548 0.026600 0.027992 ... 0.022888 0.030166 0.033270 0.041914 0.021820 0.027640 0.032171 0.028890 0.032191 0.050040
2016-09 0.073711 0.008405 0.065367 0.011386 0.022019 0.062048 0.023608 0.019986 0.027038 0.027473 ... 0.022587 0.028126 0.033828 0.039552 0.020532 0.028614 0.030861 0.030559 0.031837 0.050782
2016-10 0.077242 0.008806 0.070552 0.011535 0.021401 0.059036 0.023667 0.019980 0.027477 0.026797 ... 0.022653 0.027152 0.033759 0.039135 0.020920 0.028990 0.030279 0.026402 0.031285 0.050598
2016-11 0.077578 0.008796 0.067125 0.012577 0.023051 0.059748 0.022271 0.019594 0.028946 0.027134 ... 0.022634 0.025395 0.033775 0.036004 0.021347 0.028944 0.028519 0.028081 0.030515 0.049284
2016-12 0.074753 0.007994 0.062038 0.013340 0.029238 0.064942 0.024720 0.018477 0.030363 0.028362 ... 0.020654 0.025344 0.031074 0.037373 0.024148 0.026165 0.029129 0.032657 0.030376 0.050616
2017-01 0.075906 0.007958 0.060188 0.013154 0.029329 0.063730 0.023481 0.018343 0.030235 0.029333 ... 0.020895 0.025450 0.030600 0.039588 0.023191 0.026398 0.030515 0.032220 0.028455 0.050484
2017-02 0.083199 0.008620 0.065724 0.013586 0.029468 0.062906 0.025419 0.018270 0.028160 0.030431 ... 0.020336 0.024392 0.031627 0.038714 0.023108 0.027067 0.027035 0.032020 0.027138 0.045547
2017-03 0.085799 0.008654 0.063703 0.014535 0.031144 0.064479 0.023902 0.019508 0.027583 0.028711 ... 0.020627 0.025075 0.031392 0.036590 0.022556 0.027682 0.026321 0.032347 0.027300 0.043514
2017-04 0.088724 0.009375 0.066971 0.014045 0.028981 0.061107 0.024127 0.019136 0.026267 0.029446 ... 0.021153 0.025092 0.030899 0.036402 0.022456 0.027963 0.026143 0.030234 0.028208 0.043269
2017-05 0.088897 0.009600 0.069966 0.014244 0.028491 0.059463 0.024730 0.019183 0.025349 0.029314 ... 0.020855 0.024318 0.029700 0.034026 0.023256 0.028051 0.024243 0.029145 0.029019 0.042500
2017-06 0.090766 0.009775 0.071505 0.014343 0.026656 0.058262 0.025579 0.017481 0.024527 0.026901 ... 0.021332 0.023136 0.029243 0.032913 0.023276 0.028583 0.023910 0.027310 0.030155 0.041050
2017-07 0.085873 0.009664 0.069146 0.015356 0.029353 0.060717 0.023884 0.017384 0.025253 0.026981 ... 0.021215 0.024154 0.029403 0.032596 0.024533 0.028248 0.023366 0.029539 0.028754 0.042173
2017-08 0.086690 0.009934 0.069738 0.017876 0.028084 0.060063 0.024250 0.017116 0.025409 0.027012 ... 0.020569 0.022807 0.029707 0.032522 0.024395 0.029469 0.024832 0.027652 0.029656 0.039764
2017-09 0.094309 0.010361 0.067877 0.017890 0.027568 0.061050 0.024461 0.017311 0.024974 0.024568 ... 0.020514 0.023438 0.029907 0.031074 0.025125 0.030134 0.024124 0.026017 0.028797 0.038006
2017-10 0.087080 0.009735 0.065541 0.018766 0.028869 0.061662 0.022277 0.017810 0.026554 0.023804 ... 0.019031 0.024516 0.029208 0.031929 0.024549 0.030115 0.024469 0.027882 0.028386 0.039903
2017-11 0.090383 0.011094 0.072141 0.018127 0.029673 0.059408 0.020337 0.017629 0.025072 0.022582 ... 0.018373 0.022922 0.026653 0.026537 0.024922 0.030346 0.022953 0.027032 0.030440 0.039219
2017-12 0.090197 0.010963 0.073710 0.018562 0.029508 0.059900 0.021011 0.018579 0.025316 0.023284 ... 0.019032 0.023140 0.026891 0.028001 0.026257 0.029403 0.023859 0.026402 0.032692 0.038212
2018-01 0.088403 0.010562 0.073385 0.019761 0.030564 0.059252 0.021944 0.018687 0.026302 0.024266 ... 0.018727 0.022576 0.026257 0.028779 0.024922 0.029593 0.024253 0.027932 0.032562 0.037888
2018-02 0.080632 0.011097 0.080333 0.022250 0.031105 0.061138 0.020955 0.018917 0.024241 0.022455 ... 0.017869 0.021564 0.023463 0.027741 0.024820 0.030425 0.023304 0.028215 0.032634 0.037164
2018-03 0.088421 0.012007 0.090380 0.022939 0.031672 0.059511 0.019144 0.020807 0.022874 0.021828 ... 0.016940 0.021841 0.022520 0.026705 0.024800 0.030564 0.021552 0.025847 0.028848 0.033194
2018-04 0.087738 0.012888 0.086499 0.022035 0.030714 0.060046 0.018296 0.020295 0.023872 0.021874 ... 0.017473 0.022382 0.023076 0.027127 0.025085 0.031309 0.022076 0.024127 0.029036 0.033669
2018-05 0.085728 0.013103 0.096077 0.021690 0.030229 0.057698 0.016950 0.021540 0.025577 0.021366 ... 0.015584 0.021773 0.020853 0.024565 0.026345 0.032479 0.022288 0.023785 0.028574 0.034082
2018-06 0.093187 0.014144 0.095940 0.022711 0.028677 0.054865 0.015903 0.020188 0.024634 0.020422 ... 0.015310 0.021671 0.020488 0.023594 0.026054 0.032131 0.021007 0.024002 0.026275 0.035237
2018-07 0.091122 0.013607 0.099542 0.021265 0.027413 0.053507 0.016871 0.019675 0.024559 0.021513 ... 0.016623 0.021588 0.021656 0.023265 0.026425 0.032335 0.022016 0.024565 0.026431 0.034990
2018-08 0.093298 0.013194 0.099285 0.021229 0.028816 0.054013 0.017122 0.018438 0.023573 0.022124 ... 0.016399 0.022755 0.021455 0.022255 0.025731 0.032088 0.021736 0.023913 0.026409 0.032720
2018-09 0.100980 0.013502 0.107228 0.019928 0.027322 0.054142 0.016747 0.020011 0.021472 0.020660 ... 0.015248 0.022438 0.020938 0.021149 0.025952 0.032697 0.021269 0.023384 0.027318 0.031423
2018-10 0.099238 0.013774 0.104062 0.021727 0.025819 0.054253 0.016148 0.020231 0.022188 0.021392 ... 0.015142 0.023708 0.020919 0.021953 0.025770 0.032941 0.021261 0.020516 0.026703 0.033161
2018-11 0.103046 0.013023 0.091828 0.021913 0.025713 0.055187 0.018419 0.020206 0.021058 0.022692 ... 0.016197 0.024840 0.023997 0.021540 0.026536 0.032672 0.023765 0.022335 0.030215 0.033108
2018-12 0.084396 0.013299 0.095889 0.021418 0.025894 0.058115 0.018648 0.021169 0.022649 0.022197 ... 0.016959 0.025866 0.024528 0.021988 0.028665 0.033068 0.024198 0.022375 0.029110 0.033042
2019-01 0.080023 0.012984 0.092405 0.021380 0.025271 0.059255 0.018268 0.020697 0.023055 0.023370 ... 0.017422 0.026996 0.026623 0.022727 0.027051 0.033638 0.025863 0.021486 0.030699 0.031459
2019-02 0.079361 0.013452 0.091828 0.024059 0.027025 0.057531 0.018389 0.021626 0.023189 0.022452 ... 0.016821 0.025390 0.026951 0.022069 0.028077 0.033358 0.023933 0.021247 0.029037 0.032234
2019-03 0.080756 0.013844 0.091030 0.026519 0.027051 0.053885 0.018848 0.022646 0.023284 0.022177 ... 0.016934 0.024757 0.026247 0.021865 0.024802 0.034368 0.024102 0.020958 0.029215 0.033119
2019-04 0.085216 0.013779 0.095372 0.022750 0.025436 0.052524 0.018758 0.023380 0.023015 0.021129 ... 0.017168 0.023615 0.026678 0.021883 0.023977 0.034910 0.024139 0.019742 0.028324 0.032665
2019-05 0.091033 0.013920 0.097515 0.021246 0.026163 0.053966 0.019709 0.023081 0.021059 0.024853 ... 0.017376 0.021811 0.026397 0.020791 0.021979 0.035068 0.022635 0.018931 0.028480 0.030511
2019-06 0.080697 0.013651 0.092631 0.020616 0.024747 0.053245 0.019947 0.023070 0.022461 0.025897 ... 0.018895 0.024273 0.028011 0.022522 0.024046 0.036707 0.024222 0.018924 0.030895 0.030248
2019-07 0.086243 0.014576 0.096666 0.019927 0.025211 0.052545 0.019112 0.022413 0.022216 0.025448 ... 0.017883 0.023289 0.027399 0.022249 0.022766 0.036994 0.022368 0.018629 0.030803 0.029606
2019-08 0.089029 0.014427 0.093136 0.018655 0.025228 0.049481 0.019252 0.022780 0.021448 0.025596 ... 0.017210 0.020503 0.029083 0.023013 0.023344 0.038038 0.022008 0.018353 0.030404 0.027972
2019-09 0.089016 0.013781 0.090683 0.020086 0.023354 0.049561 0.019880 0.019301 0.021060 0.024824 ... 0.018780 0.019540 0.030518 0.024081 0.021800 0.038452 0.023328 0.018344 0.032319 0.027045
2019-10 0.095901 0.013129 0.086772 0.020967 0.024390 0.050308 0.019996 0.019553 0.020734 0.023281 ... 0.018647 0.018915 0.030730 0.025126 0.020355 0.036902 0.023738 0.019267 0.032785 0.026836
2019-11 0.104381 0.012781 0.085578 0.018445 0.026061 0.050147 0.019207 0.018546 0.019846 0.022795 ... 0.017761 0.019586 0.029558 0.025346 0.022585 0.036605 0.023118 0.019583 0.031264 0.025884
2019-12 0.105926 0.013647 0.083392 0.018705 0.026845 0.050232 0.018349 0.017269 0.019737 0.025341 ... 0.017269 0.019326 0.028692 0.023792 0.024538 0.036098 0.022497 0.019903 0.031066 0.025234
2020-01 0.114038 0.014274 0.084120 0.016621 0.027247 0.049239 0.018067 0.017844 0.019429 0.023751 ... 0.016459 0.018703 0.027319 0.023459 0.024394 0.035935 0.021686 0.018893 0.029463 0.024759
2020-02 0.115807 0.015099 0.087774 0.015571 0.024903 0.047603 0.016864 0.016943 0.016803 0.022380 ... 0.017064 0.017893 0.027530 0.022342 0.022582 0.037309 0.020588 0.016367 0.027971 0.020958
2020-03 0.117601 0.015901 0.089551 0.015005 0.023217 0.048275 0.017589 0.015687 0.016168 0.019884 ... 0.017239 0.017411 0.027532 0.023518 0.023553 0.037449 0.021276 0.015525 0.029684 0.019735
2020-04 0.115519 0.016197 0.106525 0.008260 0.019160 0.047353 0.016449 0.017795 0.013983 0.019166 ... 0.018156 0.019309 0.030673 0.021616 0.025044 0.036322 0.023935 0.011890 0.035780 0.016747
2020-05 0.120315 0.016049 0.110802 0.007316 0.019419 0.043105 0.016285 0.016648 0.015834 0.018490 ... 0.017363 0.019872 0.028640 0.020356 0.026061 0.036153 0.022549 0.010719 0.033448 0.016711
2020-06 0.125112 0.016942 0.111558 0.007735 0.019287 0.040388 0.016481 0.017546 0.015525 0.019389 ... 0.016527 0.017612 0.026773 0.019612 0.026102 0.037340 0.020614 0.010003 0.031556 0.017021

49 rows Γ— 30 columns

In [37]:
#Check that all rows add to one by summing each all elements in each row 
ind_capweight.sum(axis="columns")
Out[37]:
Date
2016-06    1.0
2016-07    1.0
2016-08    1.0
2016-09    1.0
2016-10    1.0
2016-11    1.0
2016-12    1.0
2017-01    1.0
2017-02    1.0
2017-03    1.0
2017-04    1.0
2017-05    1.0
2017-06    1.0
2017-07    1.0
2017-08    1.0
2017-09    1.0
2017-10    1.0
2017-11    1.0
2017-12    1.0
2018-01    1.0
2018-02    1.0
2018-03    1.0
2018-04    1.0
2018-05    1.0
2018-06    1.0
2018-07    1.0
2018-08    1.0
2018-09    1.0
2018-10    1.0
2018-11    1.0
2018-12    1.0
2019-01    1.0
2019-02    1.0
2019-03    1.0
2019-04    1.0
2019-05    1.0
2019-06    1.0
2019-07    1.0
2019-08    1.0
2019-09    1.0
2019-10    1.0
2019-11    1.0
2019-12    1.0
2020-01    1.0
2020-02    1.0
2020-03    1.0
2020-04    1.0
2020-05    1.0
2020-06    1.0
Freq: M, dtype: float64
In [38]:
# Compute monthly market return
total_market_return = (ind_capweight * ind_return).sum(axis="columns")
total_market_return
Out[38]:
Date
2016-06   -0.000224
2016-07    0.007698
2016-08    0.038088
2016-09    0.006595
2016-10    0.007675
2016-11   -0.011754
2016-12    0.031922
2017-01    0.045396
2017-02    0.014358
2017-03    0.058897
2017-04   -0.004802
2017-05    0.019389
2017-06    0.030120
2017-07   -0.007451
2017-08    0.037411
2017-09    0.010362
2017-10    0.017436
2017-11    0.049297
2017-12    0.031848
2018-01    0.028185
2018-02    0.071724
2018-03   -0.040649
2018-04   -0.039336
2018-05    0.040884
2018-06    0.041444
2018-07    0.007247
2018-08    0.052442
2018-09    0.053940
2018-10    0.013883
2018-11   -0.053184
2018-12    0.024455
2019-01   -0.097318
2019-02    0.064845
2019-03    0.038554
2019-04    0.037569
2019-05    0.033297
2019-06   -0.064033
2019-07    0.089802
2019-08    0.004030
2019-09   -0.007273
2019-10    0.015098
2019-11    0.048879
2019-12    0.021797
2020-01    0.057693
2020-02    0.015775
2020-03   -0.042676
2020-04   -0.167258
2020-05    0.154606
2020-06    0.076198
Freq: M, dtype: float64
In [39]:
# Plot monthly market return
total_market_return.plot.bar(figsize=(12,6), title='Monthly Returns Cap-Weighted Index' );
In [40]:
# Plot cumulative market return
total_market_index = 1000*(1+total_market_return).cumprod()
total_market_index.plot(figsize=(12,6), title='Cumulative Return Cap-Weighted Index' );

8) Construct equal-weighted benchmark.ΒΆ

In [41]:
# Number of Securities in EW Index
n_ew = ind_return.shape[1]
# Weight of Securities in EW Index
w_ew = np.repeat(1/n_ew, n_ew)
ind_equalweight = ind_capweight.multiply(1/ind_capweight/n_ew, axis="rows")
ind_equalweight
Out[41]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2016-06 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2016-07 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2016-08 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2016-09 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2016-10 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2016-11 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2016-12 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-01 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-02 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-03 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-04 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-05 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-06 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-07 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-08 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-09 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-10 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-11 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2017-12 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-01 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-02 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-03 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-04 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-05 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-06 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-07 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-08 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-09 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-10 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-11 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2018-12 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-01 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-02 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-03 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-04 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-05 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-06 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-07 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-08 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-09 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-10 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-11 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2019-12 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2020-01 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2020-02 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2020-03 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2020-04 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2020-05 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333
2020-06 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 ... 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333 0.033333

49 rows Γ— 30 columns

In [42]:
# Calculate monthly return of EW index
total_eqweighted_return = (ind_equalweight * ind_return).sum(axis="columns")
total_eqweighted_return.plot.bar(figsize=(12,6), title='Monthly Returns Equal-Weighted Index' );
In [43]:
# Calculate cumulative return of equal-weighted index
total_eqweighted_index = 1000*(1+total_eqweighted_return).cumprod()
total_eqweighted_index.plot(figsize=(12,6), title='Cumulative Return Equal-Weighted Index' );
In [44]:
# Compare cumulative return of cap-weighted and equal-weighted index
total_market_index.plot(figsize=(12,6),title="Market Cap Weighted Index", label="Mkt-weighted", legend=True)
total_eqweighted_index.plot(title="Equal Cap Weighted Vs. Market Cap Weighted Indices", label="Eq-weighted", legend=True);

9) Compute expected return vector and sample covariance matrix.ΒΆ

In [45]:
def annualize_rets(r, periods_per_year):
    """
    Gives the annualized return. Takes a times series of returns and their periodicity as arguments
    """
    compounded_growth = (1+r).prod()
    n_periods = r.shape[0]
    return compounded_growth**(periods_per_year/n_periods)-1

def annualize_vol(r, periods_per_year):
    """
    Gives the annualized volatility. Takes a times series of returns and their periodicity as arguments.
    """
    return r.std()*(periods_per_year**0.5)
In [46]:
rf = 0.00
ann_factor = 12
er = annualize_rets(ind_return, ann_factor) # Expected annualized return of securities
ev = annualize_vol(ind_return, ann_factor)  # Expected annualized volatility of securities
corr = ind_return.corr()
cov = ind_return.cov()
covmat_ann = cov*(ann_factor)               # Annualized covariance matrix
In [47]:
# Expected annualized return of securities
er
Out[47]:
AAPL     0.352070
ADBE     0.397102
AMZN     0.351272
BA       0.071405
BAC      0.153664
BRK-A    0.066738
CMCSA    0.080406
CSCO     0.156331
CVX      0.019410
DIS      0.060036
GOOG     0.177114
HD       0.191639
INTC     0.209027
JNJ      0.095944
JPM      0.137475
KO       0.045938
MA       0.331933
MRK      0.120641
MSFT     0.378470
NVDA     0.645902
PEP      0.100644
PFE      0.042535
PG       0.127666
T       -0.003512
UNH      0.243717
V        0.255170
VZ       0.068166
WFC     -0.111778
WMT      0.174680
XOM     -0.110608
dtype: float64
In [48]:
# Expected annualized volatility of securities
ev
Out[48]:
AAPL     0.295099
ADBE     0.251604
AMZN     0.260945
BA       0.391421
BAC      0.334418
BRK-A    0.183612
CMCSA    0.239443
CSCO     0.231982
CVX      0.278542
DIS      0.238579
GOOG     0.237595
HD       0.241727
INTC     0.239499
JNJ      0.174936
JPM      0.269292
KO       0.174216
MA       0.240644
MRK      0.171822
MSFT     0.192687
NVDA     0.457953
PEP      0.164489
PFE      0.189503
PG       0.138455
T        0.220863
UNH      0.236314
V        0.201790
VZ       0.170932
WFC      0.299001
WMT      0.168523
XOM      0.262441
dtype: float64
In [49]:
# Correlation matrix
corr
Out[49]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 1.000000 0.700614 0.582240 0.380270 0.517836 0.444515 0.533227 0.494223 0.345771 0.431635 ... 0.363775 0.301593 0.385373 0.334203 0.367953 0.679045 0.096008 0.387123 0.263956 0.457414
ADBE 0.700614 1.000000 0.770998 0.484703 0.448204 0.454062 0.343541 0.560204 0.419138 0.382440 ... 0.369224 0.263297 0.163183 0.203773 0.440520 0.810876 -0.034067 0.298119 0.244133 0.537471
AMZN 0.582240 0.770998 1.000000 0.246641 0.325885 0.374145 0.324668 0.641141 0.350192 0.277179 ... 0.275921 0.310176 0.055438 0.163458 0.442242 0.688607 0.078593 0.164697 0.319126 0.385566
BA 0.380270 0.484703 0.246641 1.000000 0.629046 0.664630 0.539149 0.389265 0.596850 0.490659 ... 0.404854 0.300977 0.296816 0.553654 0.364535 0.619203 0.309924 0.678326 0.232294 0.688292
BAC 0.517836 0.448204 0.325885 0.629046 1.000000 0.810649 0.557198 0.501999 0.657566 0.590028 ... 0.236792 0.448962 0.209290 0.433659 0.600981 0.556478 0.192888 0.860774 0.206416 0.660896
BRK-A 0.444515 0.454062 0.374145 0.664630 0.810649 1.000000 0.605805 0.466224 0.624357 0.540668 ... 0.439785 0.534214 0.332900 0.592964 0.584709 0.588865 0.428866 0.791319 0.383599 0.690730
CMCSA 0.533227 0.343541 0.324668 0.539149 0.557198 0.605805 1.000000 0.319867 0.525435 0.620546 ... 0.602203 0.325992 0.581925 0.628389 0.496363 0.536353 0.478246 0.586616 0.509343 0.579077
CSCO 0.494223 0.560204 0.641141 0.389265 0.501999 0.466224 0.319867 1.000000 0.450991 0.333962 ... 0.187004 0.386280 0.208801 0.298684 0.409854 0.634858 0.180895 0.364834 0.219697 0.522599
CVX 0.345771 0.419138 0.350192 0.596850 0.657566 0.624357 0.525435 0.450991 1.000000 0.546468 ... 0.444176 0.611039 0.353074 0.636936 0.647590 0.627520 0.533327 0.619580 0.259729 0.859999
DIS 0.431635 0.382440 0.277179 0.490659 0.590028 0.540668 0.620546 0.333962 0.546468 1.000000 ... 0.438619 0.337782 0.389477 0.454865 0.416166 0.516261 0.300374 0.547780 0.273828 0.576771
GOOG 0.654312 0.693716 0.613339 0.529939 0.574704 0.508039 0.512732 0.497266 0.576110 0.441563 ... 0.518916 0.380315 0.399397 0.433029 0.468948 0.834754 0.223285 0.483629 0.284158 0.585399
HD 0.542737 0.505450 0.548984 0.529138 0.610291 0.637283 0.621764 0.511175 0.693677 0.470215 ... 0.523227 0.510073 0.376669 0.666938 0.524565 0.726324 0.389617 0.575692 0.386620 0.687365
INTC 0.514641 0.571557 0.456478 0.348978 0.415988 0.294693 0.211472 0.463874 0.406879 0.221834 ... 0.127739 0.254557 0.141305 0.263680 0.290044 0.534675 0.261725 0.341665 0.218898 0.501687
JNJ 0.503708 0.514118 0.484352 0.392479 0.460389 0.592359 0.487537 0.443044 0.569086 0.456161 ... 0.654612 0.681768 0.468864 0.408370 0.503903 0.584328 0.500497 0.377445 0.510584 0.605528
JPM 0.518329 0.427040 0.298984 0.653687 0.950845 0.859990 0.554626 0.478354 0.661235 0.649474 ... 0.342806 0.494589 0.259243 0.519959 0.589101 0.581745 0.282649 0.857182 0.218336 0.695704
KO 0.353705 0.443898 0.231510 0.566434 0.379612 0.575389 0.568677 0.136529 0.557852 0.532966 ... 0.751216 0.359273 0.588649 0.545761 0.387250 0.651386 0.411959 0.474295 0.338845 0.590943
MA 0.628146 0.800730 0.650832 0.684522 0.600044 0.596123 0.473020 0.602241 0.650400 0.482444 ... 0.531120 0.406633 0.362209 0.463902 0.489719 0.940006 0.190885 0.524186 0.236059 0.686957
MRK 0.167124 0.181567 0.177656 0.390041 0.343622 0.508330 0.461645 0.332435 0.545620 0.314324 ... 0.372490 0.525696 0.440016 0.521086 0.344102 0.459672 0.487436 0.445036 0.244548 0.563427
MSFT 0.689640 0.809427 0.755718 0.479077 0.581339 0.582706 0.445954 0.583700 0.521230 0.474292 ... 0.454040 0.410324 0.231106 0.339300 0.446632 0.842374 0.190097 0.458451 0.354887 0.548653
NVDA 0.650334 0.574116 0.543208 0.353374 0.464397 0.422272 0.400126 0.288680 0.283729 0.184797 ... 0.104767 0.096694 -0.009783 0.327762 0.363512 0.505433 0.116919 0.336889 0.253872 0.424166
PEP 0.363775 0.369224 0.275921 0.404854 0.236792 0.439785 0.602203 0.187004 0.444176 0.438619 ... 1.000000 0.422862 0.702414 0.540534 0.246574 0.568056 0.497497 0.324485 0.435136 0.477491
PFE 0.301593 0.263297 0.310176 0.300977 0.448962 0.534214 0.325992 0.386280 0.611039 0.337782 ... 0.422862 1.000000 0.291966 0.486611 0.568963 0.421027 0.489444 0.394215 0.257942 0.543688
PG 0.385373 0.163183 0.055438 0.296816 0.209290 0.332900 0.581925 0.208801 0.353074 0.389477 ... 0.702414 0.291966 1.000000 0.510042 0.162225 0.434372 0.424351 0.321915 0.298629 0.353217
T 0.334203 0.203773 0.163458 0.553654 0.433659 0.592964 0.628389 0.298684 0.636936 0.454865 ... 0.540534 0.486611 0.510042 1.000000 0.419724 0.456825 0.658508 0.505242 0.231000 0.657295
UNH 0.367953 0.440520 0.442242 0.364535 0.600981 0.584709 0.496363 0.409854 0.647590 0.416166 ... 0.246574 0.568963 0.162225 0.419724 1.000000 0.448814 0.336093 0.516818 0.299103 0.612346
V 0.679045 0.810876 0.688607 0.619203 0.556478 0.588865 0.536353 0.634858 0.627520 0.516261 ... 0.568056 0.421027 0.434372 0.456825 0.448814 1.000000 0.273975 0.500538 0.355954 0.657262
VZ 0.096008 -0.034067 0.078593 0.309924 0.192888 0.428866 0.478246 0.180895 0.533327 0.300374 ... 0.497497 0.489444 0.424351 0.658508 0.336093 0.273975 1.000000 0.360569 0.563258 0.534676
WFC 0.387123 0.298119 0.164697 0.678326 0.860774 0.791319 0.586616 0.364834 0.619580 0.547780 ... 0.324485 0.394215 0.321915 0.505242 0.516818 0.500538 0.360569 1.000000 0.301153 0.698304
WMT 0.263956 0.244133 0.319126 0.232294 0.206416 0.383599 0.509343 0.219697 0.259729 0.273828 ... 0.435136 0.257942 0.298629 0.231000 0.299103 0.355954 0.563258 0.301153 1.000000 0.364863
XOM 0.457414 0.537471 0.385566 0.688292 0.660896 0.690730 0.579077 0.522599 0.859999 0.576771 ... 0.477491 0.543688 0.353217 0.657295 0.612346 0.657262 0.534676 0.698304 0.364863 1.000000

30 rows Γ— 30 columns

In [50]:
# Covariance matrix
cov
Out[50]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 0.007257 0.004335 0.003736 0.003660 0.004259 0.002007 0.003140 0.002819 0.002368 0.002532 ... 0.001471 0.001405 0.001312 0.001815 0.002138 0.003370 0.000404 0.002846 0.001094 0.002952
ADBE 0.004335 0.005275 0.004218 0.003978 0.003143 0.001748 0.001725 0.002725 0.002448 0.001913 ... 0.001273 0.001046 0.000474 0.000944 0.002183 0.003431 -0.000122 0.001869 0.000863 0.002957
AMZN 0.003736 0.004218 0.005674 0.002099 0.002370 0.001494 0.001690 0.003234 0.002121 0.001438 ... 0.000987 0.001278 0.000167 0.000785 0.002273 0.003022 0.000292 0.001071 0.001169 0.002200
BA 0.003660 0.003978 0.002099 0.012768 0.006862 0.003981 0.004211 0.002946 0.005423 0.003818 ... 0.002172 0.001860 0.001340 0.003989 0.002810 0.004076 0.001728 0.006616 0.001277 0.005892
BAC 0.004259 0.003143 0.002370 0.006862 0.009320 0.004148 0.003718 0.003245 0.005104 0.003923 ... 0.001085 0.002371 0.000808 0.002669 0.003958 0.003129 0.000919 0.007172 0.000969 0.004834
BRK-A 0.002007 0.001748 0.001494 0.003981 0.004148 0.002809 0.002220 0.001655 0.002661 0.001974 ... 0.001107 0.001549 0.000705 0.002004 0.002114 0.001818 0.001122 0.003620 0.000989 0.002774
CMCSA 0.003140 0.001725 0.001690 0.004211 0.003718 0.002220 0.004778 0.001481 0.002920 0.002954 ... 0.001977 0.001233 0.001608 0.002769 0.002341 0.002160 0.001631 0.003500 0.001713 0.003032
CSCO 0.002819 0.002725 0.003234 0.002946 0.003245 0.001655 0.001481 0.004485 0.002428 0.001540 ... 0.000595 0.001415 0.000559 0.001275 0.001872 0.002477 0.000598 0.002109 0.000716 0.002651
CVX 0.002368 0.002448 0.002121 0.005423 0.005104 0.002661 0.002920 0.002428 0.006465 0.003026 ... 0.001696 0.002688 0.001135 0.003265 0.003552 0.002939 0.002116 0.004300 0.001016 0.005239
DIS 0.002532 0.001913 0.001438 0.003818 0.003923 0.001974 0.002954 0.001540 0.003026 0.004743 ... 0.001434 0.001273 0.001072 0.001997 0.001955 0.002071 0.001021 0.003256 0.000917 0.003009
GOOG 0.003823 0.003456 0.003169 0.004107 0.003805 0.001847 0.002431 0.002284 0.003177 0.002086 ... 0.001690 0.001427 0.001095 0.001894 0.002194 0.003335 0.000756 0.002863 0.000948 0.003042
HD 0.003226 0.002562 0.002886 0.004172 0.004111 0.002357 0.002999 0.002389 0.003892 0.002260 ... 0.001734 0.001947 0.001051 0.002967 0.002497 0.002952 0.001342 0.003467 0.001312 0.003634
INTC 0.003031 0.002870 0.002377 0.002726 0.002776 0.001080 0.001011 0.002148 0.002262 0.001056 ... 0.000419 0.000963 0.000390 0.001162 0.001368 0.002153 0.000893 0.002039 0.000736 0.002628
JNJ 0.002167 0.001886 0.001843 0.002240 0.002244 0.001586 0.001702 0.001498 0.002311 0.001587 ... 0.001570 0.001883 0.000946 0.001315 0.001736 0.001719 0.001247 0.001645 0.001254 0.002317
JPM 0.003433 0.002411 0.001751 0.005742 0.007136 0.003544 0.002980 0.002490 0.004133 0.003477 ... 0.001265 0.002103 0.000805 0.002577 0.003124 0.002634 0.001084 0.005752 0.000826 0.004097
KO 0.001515 0.001621 0.000877 0.003219 0.001843 0.001534 0.001977 0.000460 0.002256 0.001846 ... 0.001794 0.000988 0.001183 0.001750 0.001329 0.001908 0.001022 0.002059 0.000829 0.002252
MA 0.003717 0.004040 0.003406 0.005373 0.004024 0.002195 0.002271 0.002802 0.003633 0.002308 ... 0.001752 0.001545 0.001006 0.002055 0.002321 0.003804 0.000654 0.003143 0.000798 0.003615
MRK 0.000706 0.000654 0.000664 0.002186 0.001645 0.001336 0.001583 0.001104 0.002176 0.001074 ... 0.000877 0.001426 0.000872 0.001648 0.001164 0.001328 0.001193 0.001905 0.000590 0.002117
MSFT 0.003268 0.003270 0.003167 0.003011 0.003122 0.001718 0.001715 0.002174 0.002331 0.001817 ... 0.001199 0.001249 0.000514 0.001203 0.001695 0.002729 0.000522 0.002201 0.000960 0.002312
NVDA 0.007324 0.005513 0.005409 0.005279 0.005927 0.002959 0.003656 0.002556 0.003016 0.001683 ... 0.000658 0.000699 -0.000052 0.002763 0.003278 0.003892 0.000763 0.003844 0.001633 0.004248
PEP 0.001471 0.001273 0.000987 0.002172 0.001085 0.001107 0.001977 0.000595 0.001696 0.001434 ... 0.002255 0.001098 0.001333 0.001636 0.000799 0.001571 0.001166 0.001330 0.001005 0.001718
PFE 0.001405 0.001046 0.001278 0.001860 0.002371 0.001549 0.001233 0.001415 0.002688 0.001273 ... 0.001098 0.002993 0.000638 0.001697 0.002123 0.001342 0.001321 0.001861 0.000686 0.002253
PG 0.001312 0.000474 0.000167 0.001340 0.000808 0.000705 0.001608 0.000559 0.001135 0.001072 ... 0.001333 0.000638 0.001597 0.001300 0.000442 0.001011 0.000837 0.001111 0.000581 0.001070
T 0.001815 0.000944 0.000785 0.003989 0.002669 0.002004 0.002769 0.001275 0.003265 0.001997 ... 0.001636 0.001697 0.001300 0.004065 0.001826 0.001697 0.002072 0.002780 0.000716 0.003175
UNH 0.002138 0.002183 0.002273 0.002810 0.003958 0.002114 0.002341 0.001872 0.003552 0.001955 ... 0.000799 0.002123 0.000442 0.001826 0.004654 0.001784 0.001131 0.003043 0.000993 0.003165
V 0.003370 0.003431 0.003022 0.004076 0.003129 0.001818 0.002160 0.002477 0.002939 0.002071 ... 0.001571 0.001342 0.001011 0.001697 0.001784 0.003393 0.000788 0.002517 0.001009 0.002901
VZ 0.000404 -0.000122 0.000292 0.001728 0.000919 0.001122 0.001631 0.000598 0.002116 0.001021 ... 0.001166 0.001321 0.000837 0.002072 0.001131 0.000788 0.002435 0.001536 0.001352 0.001999
WFC 0.002846 0.001869 0.001071 0.006616 0.007172 0.003620 0.003500 0.002109 0.004300 0.003256 ... 0.001330 0.001861 0.001111 0.002780 0.003043 0.002517 0.001536 0.007450 0.001265 0.004566
WMT 0.001094 0.000863 0.001169 0.001277 0.000969 0.000989 0.001713 0.000716 0.001016 0.000917 ... 0.001005 0.000686 0.000581 0.000716 0.000993 0.001009 0.001352 0.001265 0.002367 0.001345
XOM 0.002952 0.002957 0.002200 0.005892 0.004834 0.002774 0.003032 0.002651 0.005239 0.003009 ... 0.001718 0.002253 0.001070 0.003175 0.003165 0.002901 0.001999 0.004566 0.001345 0.005740

30 rows Γ— 30 columns

In [51]:
# Annualised covariance matrix
covmat_ann
Out[51]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 0.087083 0.052019 0.044835 0.043924 0.051103 0.024086 0.037678 0.033833 0.028422 0.030389 ... 0.017658 0.016866 0.015746 0.021782 0.025660 0.040436 0.004843 0.034158 0.013127 0.035425
ADBE 0.052019 0.063305 0.050620 0.047735 0.037712 0.020977 0.020697 0.032698 0.029374 0.022957 ... 0.015281 0.012554 0.005685 0.011324 0.026192 0.041169 -0.001465 0.022428 0.010351 0.035490
AMZN 0.044835 0.050620 0.068092 0.025192 0.028438 0.017926 0.020286 0.038811 0.025453 0.017256 ... 0.011843 0.015338 0.002003 0.009421 0.027271 0.036259 0.003506 0.012850 0.014034 0.026405
BA 0.043924 0.047735 0.025192 0.153210 0.082341 0.047767 0.050531 0.035346 0.065073 0.045820 ... 0.026066 0.022325 0.016086 0.047864 0.033719 0.048908 0.020736 0.079388 0.015323 0.070705
BAC 0.051103 0.037712 0.028438 0.082341 0.111835 0.049777 0.044617 0.038945 0.061252 0.047076 ... 0.013025 0.028452 0.009691 0.032030 0.047494 0.037552 0.011026 0.086070 0.011633 0.058004
BRK-A 0.024086 0.020977 0.017926 0.047767 0.049777 0.033714 0.026634 0.019859 0.031932 0.023685 ... 0.013283 0.018588 0.008463 0.024047 0.025371 0.021818 0.013460 0.043444 0.011870 0.033285
CMCSA 0.037678 0.020697 0.020286 0.050531 0.044617 0.026634 0.057333 0.017767 0.035044 0.035449 ... 0.023718 0.014792 0.019292 0.033232 0.028086 0.025915 0.019574 0.041998 0.020553 0.036389
CSCO 0.033833 0.032698 0.038811 0.035346 0.038945 0.019859 0.017767 0.053816 0.029142 0.018483 ... 0.007136 0.016981 0.006706 0.015303 0.022468 0.029719 0.007173 0.025306 0.008589 0.031817
CVX 0.028422 0.029374 0.025453 0.065073 0.061252 0.031932 0.035044 0.029142 0.077586 0.036315 ... 0.020351 0.032253 0.013617 0.039184 0.042627 0.035271 0.025393 0.051601 0.012192 0.062867
DIS 0.030389 0.022957 0.017256 0.045820 0.047076 0.023685 0.035449 0.018483 0.036315 0.056920 ... 0.017213 0.015272 0.012865 0.023968 0.023463 0.024854 0.012250 0.039076 0.011010 0.036113
GOOG 0.045877 0.041470 0.038027 0.049284 0.045664 0.022163 0.029170 0.027408 0.038127 0.025030 ... 0.020280 0.017124 0.013139 0.022724 0.026330 0.040022 0.009068 0.034358 0.011378 0.036502
HD 0.038715 0.030741 0.034628 0.050065 0.049335 0.028285 0.035988 0.028665 0.046706 0.027118 ... 0.020804 0.023365 0.012606 0.035607 0.029965 0.035429 0.016099 0.041609 0.015750 0.043606
INTC 0.036373 0.034442 0.028528 0.032715 0.033318 0.012959 0.012127 0.025773 0.027143 0.012676 ... 0.005032 0.011553 0.004686 0.013948 0.016416 0.025840 0.010715 0.024467 0.008835 0.031533
JNJ 0.026003 0.022629 0.022110 0.026875 0.026934 0.019027 0.020422 0.017980 0.027730 0.019038 ... 0.018837 0.022601 0.011356 0.015778 0.020831 0.020627 0.014966 0.019743 0.015052 0.027800
JPM 0.041191 0.028934 0.021010 0.068903 0.085629 0.042523 0.035762 0.029883 0.049599 0.041727 ... 0.015185 0.025240 0.009666 0.030925 0.037489 0.031612 0.013011 0.069019 0.009908 0.049168
KO 0.018184 0.019458 0.010525 0.038626 0.022117 0.018406 0.023722 0.005518 0.027071 0.022152 ... 0.021527 0.011861 0.014199 0.021000 0.015943 0.022900 0.012268 0.024706 0.009948 0.027019
MA 0.044607 0.048482 0.040869 0.064477 0.048289 0.026340 0.027256 0.033620 0.043596 0.027698 ... 0.021023 0.018544 0.012068 0.024656 0.027849 0.045646 0.007852 0.037717 0.009573 0.043385
MRK 0.008474 0.007849 0.007965 0.026232 0.019745 0.016037 0.018993 0.013251 0.026113 0.012885 ... 0.010528 0.017117 0.010468 0.019775 0.013972 0.015938 0.014316 0.022864 0.007081 0.025407
MSFT 0.039214 0.039242 0.037998 0.036133 0.037460 0.020616 0.020575 0.026091 0.027975 0.021804 ... 0.014391 0.014983 0.006166 0.014440 0.020337 0.032753 0.006261 0.026413 0.011524 0.027745
NVDA 0.087887 0.066151 0.064914 0.063343 0.071121 0.035507 0.043875 0.030668 0.036192 0.020191 ... 0.007892 0.008391 -0.000620 0.033151 0.039340 0.046707 0.009152 0.046130 0.019593 0.050979
PEP 0.017658 0.015281 0.011843 0.026066 0.013025 0.013283 0.023718 0.007136 0.020351 0.017213 ... 0.027057 0.013181 0.015997 0.019637 0.009585 0.018855 0.013988 0.015959 0.012062 0.020613
PFE 0.016866 0.012554 0.015338 0.022325 0.028452 0.018588 0.014792 0.016981 0.032253 0.015272 ... 0.013181 0.035912 0.007661 0.020367 0.025480 0.016100 0.015854 0.022337 0.008238 0.027040
PG 0.015746 0.005685 0.002003 0.016086 0.009691 0.008463 0.019292 0.006706 0.013617 0.012865 ... 0.015997 0.007661 0.019170 0.015597 0.005308 0.012136 0.010043 0.013327 0.006968 0.012835
T 0.021782 0.011324 0.009421 0.047864 0.032030 0.024047 0.033232 0.015303 0.039184 0.023968 ... 0.019637 0.020367 0.015597 0.048780 0.021907 0.020360 0.024860 0.033365 0.008598 0.038099
UNH 0.025660 0.026192 0.027271 0.033719 0.047494 0.025371 0.028086 0.022468 0.042627 0.023463 ... 0.009585 0.025480 0.005308 0.021907 0.055844 0.021402 0.013576 0.036517 0.011912 0.037977
V 0.040436 0.041169 0.036259 0.048908 0.037552 0.021818 0.025915 0.029719 0.035271 0.024854 ... 0.018855 0.016100 0.012136 0.020360 0.021402 0.040719 0.009450 0.030200 0.012105 0.034807
VZ 0.004843 -0.001465 0.003506 0.020736 0.011026 0.013460 0.019574 0.007173 0.025393 0.012250 ... 0.013988 0.015854 0.010043 0.024860 0.013576 0.009450 0.029218 0.018428 0.016225 0.023985
WFC 0.034158 0.022428 0.012850 0.079388 0.086070 0.043444 0.041998 0.025306 0.051601 0.039076 ... 0.015959 0.022337 0.013327 0.033365 0.036517 0.030200 0.018428 0.089402 0.015175 0.054796
WMT 0.013127 0.010351 0.014034 0.015323 0.011633 0.011870 0.020553 0.008589 0.012192 0.011010 ... 0.012062 0.008238 0.006968 0.008598 0.011912 0.012105 0.016225 0.015175 0.028400 0.016137
XOM 0.035425 0.035490 0.026405 0.070705 0.058004 0.033285 0.036389 0.031817 0.062867 0.036113 ... 0.020613 0.027040 0.012835 0.038099 0.037977 0.034807 0.023985 0.054796 0.016137 0.068875

30 rows Γ— 30 columns

10) Compute idiosyncratic risk statistics.ΒΆ

In [53]:
def sharpe_ratio(r, riskfree_rate, periods_per_year):
    """
    Computes the annualized sharpe ratio of a set of returns
    """
    # convert the annual riskfree rate to per period
    rf_per_period = (1+riskfree_rate)**(1/periods_per_year)-1
    excess_ret = r - rf_per_period
    ann_ex_ret = annualize_rets(excess_ret, periods_per_year)
    ann_vol = annualize_vol(r, periods_per_year)
    return ann_ex_ret/ann_vol

import scipy.stats
def is_normal(r, level=0.01):
    """
    Applies the Jarque-Bera test to determine if a Series is normal or not
    Test is applied at the 1% level by default
    Returns True if the hypothesis of normality is accepted, False otherwise
    """
    if isinstance(r, pd.DataFrame):
        return r.aggregate(is_normal)
    else:
        statistic, p_value = scipy.stats.jarque_bera(r)
        return p_value > level

def drawdown(return_series: pd.Series):
    """Takes a time series of asset returns.
       returns a DataFrame with columns for
       the wealth index, 
       the previous peaks, and 
       the percentage drawdown
    """
    wealth_index = 1000*(1+return_series).cumprod()
    previous_peaks = wealth_index.cummax()
    drawdowns = (wealth_index - previous_peaks)/previous_peaks
    return pd.DataFrame({"Wealth": wealth_index, 
                         "Previous Peak": previous_peaks, 
                         "Drawdown": drawdowns})

def semideviation(r):
    """
    Returns the semideviation aka negative semideviation of r
    r must be a Series or a DataFrame, else raises a TypeError
    """
    if isinstance(r, pd.Series):
        is_negative = r < 0
        return r[is_negative].std(ddof=0)
    elif isinstance(r, pd.DataFrame):
        return r.aggregate(semideviation)
    else:
        raise TypeError("Expected r to be a Series or DataFrame")

def var_historic(r, level=5):
    """
    Returns the historic Value at Risk at a specified level
    i.e. returns the number such that "level" percent of the returns
    fall below that number, and the (100-level) percent are above
    """
    if isinstance(r, pd.DataFrame):
        return r.aggregate(var_historic, level=level)
    elif isinstance(r, pd.Series):
        return -np.percentile(r, level)
    else:
        raise TypeError("Expected r to be a Series or DataFrame")


def cvar_historic(r, level=5):
    """
    Computes the Conditional VaR of Series or DataFrame
    """
    if isinstance(r, pd.Series):
        is_beyond = r <= -var_historic(r, level=level)
        return -r[is_beyond].mean()
    elif isinstance(r, pd.DataFrame):
        return r.aggregate(cvar_historic, level=level)
    else:
        raise TypeError("Expected r to be a Series or DataFrame")


from scipy.stats import norm
def var_gaussian(r, level=5, modified=False):
    """
    Returns the Parametric Gauusian VaR of a Series or DataFrame
    If "modified" is True, then the modified VaR is returned,
    using the Cornish-Fisher modification
    """
    # compute the Z score assuming it was Gaussian
    z = norm.ppf(level/100)
    if modified:
        # modify the Z score based on observed skewness and kurtosis
        s = skewness(r)
        k = kurtosis(r)
        z = (z +
                (z**2 - 1)*s/6 +
                (z**3 -3*z)*(k-3)/24 -
                (2*z**3 - 5*z)*(s**2)/36
            )
    return -(r.mean() + z*r.std(ddof=0))

def skewness(r):
    """
    Alternative to scipy.stats.skew()
    Computes the skewness of the supplied Series or DataFrame
    Returns a float or a Series
    """
    demeaned_r = r - r.mean()
    # use the population standard deviation, so set dof=0
    sigma_r = r.std(ddof=0)
    exp = (demeaned_r**3).mean()
    return exp/sigma_r**3


def kurtosis(r):
    """
    Alternative to scipy.stats.kurtosis()
    Computes the kurtosis of the supplied Series or DataFrame
    Returns a float or a Series
    """
    demeaned_r = r - r.mean()
    # use the population standard deviation, so set dof=0
    sigma_r = r.std(ddof=0)
    exp = (demeaned_r**4).mean()
    return exp/sigma_r**4
In [54]:
sharpe_ratio(ind_return, rf, ann_factor).sort_values().plot.bar(title="Sharpe Ratio");
In [55]:
var_gaussian(ind_return, level=5, modified=False).sort_values().plot.bar(title='Parametric (Gaussian) VaR @ 95%');
In [56]:
var_gaussian(ind_return, level=5, modified=True).sort_values().plot.bar(title='Modified (Cornish-Fisher) VaR @ 95%');
In [57]:
var_historic(ind_return, level=5).sort_values().plot.bar(title='Historic VaR @ 95%');
In [58]:
cvar_historic(ind_return, level=5).sort_values().plot.bar(title='Conditional VaR @ 95%');
In [59]:
semideviation(ind_return).sort_values().plot.bar(title='Negative Semi-Deviation');
In [60]:
skewness(ind_return).sort_values().plot.bar(title="Skewness")
Out[60]:
<matplotlib.axes._subplots.AxesSubplot at 0x1980ff01f60>
In [61]:
kurtosis(ind_return).sort_values().plot.bar(title="Kurtosis");
In [62]:
# Empirical Distribution of monthly returns
ind_return.hist(figsize=(18,20))
plt.show()
In [63]:
# Check for normality of returns
is_normal(ind_return, level=0.01)
Out[63]:
AAPL      True
ADBE      True
AMZN      True
BA       False
BAC      False
BRK-A    False
CMCSA    False
CSCO      True
CVX      False
DIS      False
GOOG      True
HD       False
INTC      True
JNJ       True
JPM      False
KO       False
MA       False
MRK       True
MSFT      True
NVDA      True
PEP       True
PFE       True
PG        True
T        False
UNH       True
V        False
VZ        True
WFC      False
WMT       True
XOM      False
dtype: bool
In [64]:
# Inspect normality of returns
from scipy import stats
for column in ind_return:
    stats.probplot(ind_return[column], dist="norm", plot=plt)
    plt.show()

11) Construct efficient frontier based on classical Markowitz model.ΒΆ

In [65]:
# Define functions for portfolio return and volatility

def portfolio_return(weights, returns):
    """
    Computes the return on a portfolio from constituent returns and weights
    """
    return weights.T @ returns


def portfolio_vol(weights, covmat):
    """
    Computes the vol of a portfolio from a covariance matrix and constituent weights
    """
    vol = (weights.T @ covmat @ weights)**0.5
    return vol 
In [66]:
# Program to return optimal weights for maximization of Sharpe ratio

from scipy.optimize import minimize

def msr(riskfree_rate, er, cov):
    """
    Returns the weights of the portfolio that gives you the maximum sharpe ratio
    given the riskfree rate, an expected returns vector and a covariance matrix
    """
    n = er.shape[0] # Input for initial guess
    init_guess = np.repeat(1/n, n) # Equal Weighting for init_guess
    bounds = ((0.0, 1.0),) * n # Minimum and maximum individual allocation (No shorting constraint)
    # Define the constraint: Sum of portfolio weights variable minus one must equal zero. ("Equality" Constraint)
    weights_sum_to_1 = {'type': 'eq',
                        'fun': lambda weights: np.sum(weights) - 1
    }
    def neg_sharpe(weights, riskfree_rate, er, cov):
        """
        Defining the objective function which we seek to minimize:
        The investor seeks weights to maximise Sharpe ratio (Excess Ret/Vol), for given return vector, cov matrix and rfr.
        Equivalent to minimizing the negative of this ratio.
        """
        r = portfolio_return(weights, er)
        vol = portfolio_vol(weights, cov)
        return -(r - riskfree_rate)/vol
    
    # Scipy optimize function takes obj fun; init guess, input args for obj fun, constraints on total weights, boundaries
    # for individual weights, the optimization method
    weights = minimize(neg_sharpe, init_guess,
                       args=(riskfree_rate, er, cov), method='SLSQP',
                       options={'disp': False},
                       constraints=(weights_sum_to_1,),
                       bounds=bounds)
    return weights.x
In [67]:
msr(0.0,er,cov).round(4)
Out[67]:
array([0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ,
       0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ,
       0.    , 0.    , 0.5431, 0.0775, 0.    , 0.    , 0.2676, 0.    ,
       0.0154, 0.    , 0.    , 0.    , 0.0965, 0.    ])
In [68]:
# Program to return optimal weights to minimize vol for a given target return

def minimize_vol(target_return, er, cov):
    """
    Returns the optimal weights that achieve the target return
    given a set of expected returns and a covariance matrix
    """
    n = er.shape[0]
    init_guess = np.repeat(1/n, n)
    bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples!
    # construct the constraints
    weights_sum_to_1 = {'type': 'eq',
                        'fun': lambda weights: np.sum(weights) - 1
    }
    return_is_target = {'type': 'eq',
                        'args': (er,),
                        'fun': lambda weights, er: target_return - portfolio_return(weights,er)
    }
    weights = minimize(portfolio_vol, init_guess,
                       args=(cov,), method='SLSQP',
                       options={'disp': False},
                       constraints=(weights_sum_to_1,return_is_target),
                       bounds=bounds)
    return weights.x
In [69]:
minimize_vol(0.05,er,cov).round(4)
Out[69]:
array([0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.0036,
       0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.204 ,
       0.    , 0.    , 0.    , 0.    , 0.    , 0.225 , 0.251 , 0.    ,
       0.    , 0.    , 0.1877, 0.0903, 0.    , 0.0384])
In [70]:
# Weighting scheme returning optimal weights for minimization of global min. variance

def gmv(cov):
    """
    Returns the weights of the Global Minimum Volatility portfolio
    given a covariance matrix
    """
    n = cov.shape[0]
    return msr(0, np.repeat(1, n), cov) #Exp. ret set to 1 for all securities 
In [71]:
gmv(cov).round(4)
Out[71]:
array([0.    , 0.    , 0.037 , 0.    , 0.    , 0.0008, 0.    , 0.0012,
       0.    , 0.    , 0.    , 0.    , 0.0815, 0.    , 0.    , 0.    ,
       0.    , 0.1245, 0.0256, 0.    , 0.    , 0.0757, 0.4228, 0.    ,
       0.0144, 0.    , 0.0081, 0.    , 0.2084, 0.    ])
In [72]:
# Weighting scheme returning  equal weighted portfolio. 
def weight_ew(r):
    """
    Returns the weights of the EW portfolio based on the asset returns "r" as a DataFrame
    """
    n = len(r.columns)
    ew = pd.Series(1/n, index=r.columns)
    return ew
In [73]:
weight_ew(ind_return)
Out[73]:
AAPL     0.033333
ADBE     0.033333
AMZN     0.033333
BA       0.033333
BAC      0.033333
BRK-A    0.033333
CMCSA    0.033333
CSCO     0.033333
CVX      0.033333
DIS      0.033333
GOOG     0.033333
HD       0.033333
INTC     0.033333
JNJ      0.033333
JPM      0.033333
KO       0.033333
MA       0.033333
MRK      0.033333
MSFT     0.033333
NVDA     0.033333
PEP      0.033333
PFE      0.033333
PG       0.033333
T        0.033333
UNH      0.033333
V        0.033333
VZ       0.033333
WFC      0.033333
WMT      0.033333
XOM      0.033333
dtype: float64
In [74]:
def optimal_weights(n_points, er, cov):
    """
    Returns a list of weights that represent a grid of n_points on the efficient frontier given a range of 
    target returns (from the lowest expected return to the highest expected return)
    """
    target_rs = np.linspace(er.min(), er.max(), n_points)
    weights = [minimize_vol(target_return, er, cov) for target_return in target_rs]
    return weights
In [75]:
def plot_ef(n_points, er, cov, style='.-', legend=False, show_cml=False, riskfree_rate=0, show_ew=False, show_gmv=False):
    """
    Plots the multi-asset efficient frontier using the "optimal weights" function
    """
    weights = optimal_weights(n_points, er, cov)
    rets = [portfolio_return(w, er) for w in weights]
    vols = [portfolio_vol(w, cov) for w in weights]
    ef = pd.DataFrame({
        "Returns": rets, 
        "Volatility": vols
    })
    ax = ef.plot.line(x="Volatility", y="Returns", style=style, legend=legend)
    ax.set_title('Figure 1: Ex-Ante Efficient Frontier (June 2020)')
    plt.xlabel('Volatility')
    plt.ylabel('Returns')
    if show_cml:
        ax.set_xlim(left = 0)
        # get MSR
        w_msr = msr(riskfree_rate, er, cov)
        r_msr = portfolio_return(w_msr, er)
        vol_msr = portfolio_vol(w_msr, cov)
        # add CML
        cml_x = [vol_msr]
        cml_y = [r_msr]
        ax.plot(cml_x, cml_y, color='red', marker="*", linestyle='dashed', linewidth=2, markersize=18, label='msr')
        plt.annotate("MSR", xy=(vol_msr, r_msr), ha='right', va='bottom', rotation=45)
    if show_ew:
        n = er.shape[0]
        w_ew = np.repeat(1/n, n)
        r_ew = portfolio_return(w_ew, er)
        vol_ew = portfolio_vol(w_ew, cov)
        # add EW
        ax.plot([vol_ew], [r_ew], color='green', marker='o', markersize=10, label='ew')
        plt.annotate("EW", xy=(vol_ew, r_ew), horizontalalignment='right', verticalalignment='bottom', rotation=45)
    if show_gmv:
        w_gmv = gmv(cov)
        r_gmv = portfolio_return(w_gmv, er)
        vol_gmv = portfolio_vol(w_gmv, cov)
        # add GMV
        ax.plot([vol_gmv], [r_gmv], color='goldenrod', marker="D", markersize=12, label='gmv')
        plt.annotate("GMV", xy=(vol_gmv, r_gmv), horizontalalignment='right', verticalalignment='bottom', rotation=45)
        return ax
In [76]:
# Display eff. frontier
plot_ef(100, er, covmat_ann, style='.-', legend=False, show_cml=True, riskfree_rate=rf, show_ew=True, show_gmv=True);
In [77]:
w_msr = msr(rf, er, covmat_ann)
r_msr = portfolio_return(w_msr, er)
vol_msr = portfolio_vol(w_msr, covmat_ann)
In [78]:
w_msr.round(4), r_msr ,vol_msr
Out[78]:
(array([0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ,
        0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ,
        0.    , 0.    , 0.5428, 0.0776, 0.    , 0.    , 0.2674, 0.    ,
        0.0154, 0.    , 0.    , 0.    , 0.0968, 0.    ]),
 0.3103511293211425,
 0.14938144606121154)
In [79]:
w_gmv = gmv(covmat_ann)
r_gmv = portfolio_return(w_gmv, er)
vol_gmv = portfolio_vol(w_gmv, covmat_ann)
In [80]:
w_gmv.round(4), r_gmv, vol_gmv
Out[80]:
(array([0.    , 0.    , 0.0371, 0.    , 0.    , 0.0007, 0.    , 0.0011,
        0.    , 0.    , 0.    , 0.    , 0.0816, 0.    , 0.    , 0.    ,
        0.    , 0.1246, 0.0256, 0.    , 0.    , 0.0754, 0.4229, 0.    ,
        0.0145, 0.    , 0.0082, 0.    , 0.2083, 0.    ]),
 0.15269802184299291,
 0.11057098555876727)
In [81]:
n = er.shape[0]
w_ew = np.repeat(1/n, n)
r_ew = portfolio_return(w_ew, er)
vol_ew = portfolio_vol(w_ew, covmat_ann)
In [82]:
w_ew, r_ew, vol_ew
Out[82]:
(array([0.03333333, 0.03333333, 0.03333333, 0.03333333, 0.03333333,
        0.03333333, 0.03333333, 0.03333333, 0.03333333, 0.03333333,
        0.03333333, 0.03333333, 0.03333333, 0.03333333, 0.03333333,
        0.03333333, 0.03333333, 0.03333333, 0.03333333, 0.03333333,
        0.03333333, 0.03333333, 0.03333333, 0.03333333, 0.03333333,
        0.03333333, 0.03333333, 0.03333333, 0.03333333, 0.03333333]),
 0.16097324013325692,
 0.1670813830257861)

12) Shrink covariance matrix.ΒΆ

In [83]:
def sample_cov(r, **kwargs):
    """
    Returns the sample covariance of the supplied returns
    """
    return r.cov()

def cc_cov(r, **kwargs):
    """
    Estimates a covariance matrix by using the Elton/Gruber Constant Correlation model
    """
    rhos = r.corr()
    n = rhos.shape[0]
    # this is a symmetric matrix with diagonals all 1 - so the mean correlation is ...
    rho_bar = (rhos.values.sum()-n)/(n*(n-1))
    ccor = np.full_like(rhos, rho_bar)
    np.fill_diagonal(ccor, 1.)
    sd = r.std()
    return pd.DataFrame(ccor * np.outer(sd, sd), index=r.columns, columns=r.columns)

def shrinkage_cov(r, delta=0.5, **kwargs):
    """
    Covariance estimator that shrinks between the Sample Covariance and the Constant Correlation Estimators
    """
    prior = cc_cov(r, **kwargs)
    sample = sample_cov(r, **kwargs)
    return delta*prior + (1-delta)*sample
In [84]:
shrink_cov = shrinkage_cov(ind_return, delta=0.5)
shrink_cov
Out[84]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 0.007257 0.003601 0.003355 0.004060 0.004035 0.002050 0.002934 0.002731 0.002771 0.002625 ... 0.001673 0.001782 0.001445 0.002166 0.002415 0.002834 0.001176 0.003127 0.001507 0.002971
ADBE 0.003601 0.005275 0.003377 0.003890 0.003196 0.001766 0.002025 0.002489 0.002577 0.002115 ... 0.001436 0.001444 0.000909 0.001545 0.002239 0.002696 0.000769 0.002387 0.001250 0.002754
AMZN 0.003355 0.003377 0.005674 0.003022 0.002870 0.001672 0.002051 0.002786 0.002464 0.001921 ... 0.001322 0.001594 0.000781 0.001505 0.002327 0.002527 0.001007 0.002042 0.001434 0.002422
BA 0.004060 0.003890 0.003022 0.012768 0.005958 0.003378 0.003915 0.003226 0.004816 0.003712 ... 0.002329 0.002362 0.001716 0.003663 0.003191 0.003563 0.002156 0.005567 0.001912 0.004929
BAC 0.004035 0.003196 0.002870 0.005958 0.009320 0.003259 0.003405 0.003120 0.004350 0.003502 ... 0.001605 0.002409 0.001298 0.002761 0.003505 0.002867 0.001563 0.005517 0.001573 0.004111
BRK-A 0.002050 0.001766 0.001672 0.003378 0.003259 0.002809 0.001959 0.001650 0.002318 0.001833 ... 0.001137 0.001446 0.000843 0.001785 0.001895 0.001624 0.001167 0.002870 0.001092 0.002317
CMCSA 0.002934 0.002025 0.002051 0.003915 0.003405 0.001959 0.004778 0.001813 0.002748 0.002580 ... 0.001749 0.001492 0.001444 0.002406 0.002263 0.002013 0.001606 0.003132 0.001635 0.002729
CSCO 0.002731 0.002489 0.002786 0.003226 0.003120 0.001650 0.001813 0.004485 0.002462 0.001839 ... 0.001034 0.001556 0.000900 0.001627 0.001995 0.002142 0.001064 0.002394 0.001113 0.002501
CVX 0.002771 0.002577 0.002464 0.004816 0.004350 0.002318 0.002748 0.002462 0.006465 0.002796 ... 0.001732 0.002363 0.001312 0.002820 0.003047 0.002555 0.001977 0.003758 0.001414 0.004031
DIS 0.002625 0.002115 0.001921 0.003712 0.003502 0.001833 0.002580 0.001839 0.002796 0.004743 ... 0.001475 0.001509 0.001174 0.002016 0.002066 0.001965 0.001298 0.003005 0.001235 0.002714
GOOG 0.003265 0.002882 0.002781 0.003849 0.003437 0.001766 0.002314 0.002206 0.002866 0.002137 ... 0.001600 0.001583 0.001183 0.001960 0.002181 0.002593 0.001162 0.002803 0.001247 0.002725
HD 0.002990 0.002455 0.002661 0.003913 0.003616 0.002035 0.002617 0.002277 0.003246 0.002243 ... 0.001634 0.001858 0.001171 0.002514 0.002351 0.002418 0.001468 0.003129 0.001443 0.003042
INTC 0.002880 0.002598 0.002395 0.003173 0.002934 0.001389 0.001612 0.002146 0.002419 0.001631 ... 0.000970 0.001358 0.000835 0.001602 0.001777 0.002010 0.001237 0.002402 0.001147 0.002527
JNJ 0.002080 0.001793 0.001803 0.002442 0.002252 0.001413 0.001660 0.001533 0.002096 0.001599 ... 0.001340 0.001582 0.000941 0.001403 0.001666 0.001541 0.001201 0.001832 0.001196 0.002045
JPM 0.003250 0.002514 0.002232 0.004906 0.005306 0.002726 0.002735 0.002451 0.003515 0.002979 ... 0.001488 0.002037 0.001123 0.002437 0.002791 0.002366 0.001431 0.004430 0.001289 0.003413
KO 0.001750 0.001657 0.001316 0.002926 0.002046 0.001384 0.001794 0.001010 0.002065 0.001725 ... 0.001450 0.001132 0.001057 0.001618 0.001459 0.001633 0.001086 0.002035 0.000981 0.002008
MA 0.003230 0.003189 0.002915 0.004505 0.003566 0.001951 0.002248 0.002479 0.003111 0.002262 ... 0.001640 0.001653 0.001146 0.002053 0.002258 0.002839 0.001121 0.002961 0.001182 0.003027
MRK 0.001332 0.001162 0.001197 0.002391 0.001932 0.001277 0.001586 0.001322 0.002012 0.001328 ... 0.000984 0.001342 0.000895 0.001557 0.001366 0.001333 0.001164 0.001944 0.000854 0.001929
MSFT 0.002732 0.002571 0.002554 0.002962 0.002805 0.001542 0.001748 0.001950 0.002202 0.001796 ... 0.001212 0.001329 0.000772 0.001423 0.001726 0.002115 0.000897 0.002213 0.001107 0.002132
NVDA 0.006271 0.004981 0.005012 0.006100 0.005920 0.003103 0.003945 0.003329 0.003971 0.002951 ... 0.001783 0.002025 0.001198 0.003334 0.003728 0.003730 0.001893 0.004566 0.002306 0.004444
PEP 0.001673 0.001436 0.001322 0.002329 0.001605 0.001137 0.001749 0.001034 0.001732 0.001475 ... 0.002255 0.001151 0.001106 0.001520 0.001150 0.001426 0.001126 0.001614 0.001038 0.001692
PFE 0.001782 0.001444 0.001594 0.002362 0.002409 0.001446 0.001492 0.001556 0.002363 0.001509 ... 0.001151 0.002993 0.000826 0.001657 0.001926 0.001409 0.001286 0.002025 0.000960 0.002087
PG 0.001445 0.000909 0.000781 0.001716 0.001298 0.000843 0.001444 0.000900 0.001312 0.001174 ... 0.001106 0.000826 0.001597 0.001240 0.000853 0.001045 0.000875 0.001354 0.000741 0.001236
T 0.002166 0.001545 0.001505 0.003663 0.002761 0.001785 0.002406 0.001627 0.002820 0.002016 ... 0.001520 0.001657 0.001240 0.004065 0.001920 0.001709 0.001765 0.002665 0.001077 0.002706
UNH 0.002415 0.002239 0.002327 0.003191 0.003505 0.001895 0.002263 0.001995 0.003047 0.002066 ... 0.001150 0.001926 0.000853 0.001920 0.004654 0.001812 0.001345 0.002886 0.001265 0.002780
V 0.002834 0.002696 0.002527 0.003563 0.002867 0.001624 0.002013 0.002142 0.002555 0.001965 ... 0.001426 0.001409 0.001045 0.001709 0.001812 0.003393 0.001060 0.002423 0.001161 0.002473
VZ 0.001176 0.000769 0.001007 0.002156 0.001563 0.001167 0.001606 0.001064 0.001977 0.001298 ... 0.001126 0.001286 0.000875 0.001765 0.001345 0.001060 0.002435 0.001755 0.001232 0.001865
WFC 0.003127 0.002387 0.002042 0.005567 0.005517 0.002870 0.003132 0.002394 0.003758 0.003005 ... 0.001614 0.002025 0.001354 0.002665 0.002886 0.002423 0.001755 0.007450 0.001605 0.003798
WMT 0.001507 0.001250 0.001434 0.001912 0.001573 0.001092 0.001635 0.001113 0.001414 0.001235 ... 0.001038 0.000960 0.000741 0.001077 0.001265 0.001161 0.001232 0.001605 0.002367 0.001526
XOM 0.002971 0.002754 0.002422 0.004929 0.004111 0.002317 0.002729 0.002501 0.004031 0.002714 ... 0.001692 0.002087 0.001236 0.002706 0.002780 0.002473 0.001865 0.003798 0.001526 0.005740

30 rows Γ— 30 columns

In [85]:
shrink_cov_ann = shrink_cov*(ann_factor)
shrink_cov_ann
Out[85]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 0.087083 0.043211 0.040257 0.048721 0.048414 0.024595 0.035208 0.032776 0.033253 0.031505 ... 0.020074 0.021388 0.017338 0.025990 0.028985 0.034013 0.014107 0.037520 0.018084 0.035654
ADBE 0.043211 0.063305 0.040520 0.046683 0.038349 0.021191 0.024305 0.029871 0.030923 0.025385 ... 0.017228 0.017323 0.010913 0.018536 0.026871 0.032347 0.009231 0.028642 0.014999 0.033042
AMZN 0.040257 0.040520 0.068092 0.036258 0.034435 0.020063 0.024618 0.033429 0.029565 0.023051 ... 0.015865 0.019125 0.009371 0.018062 0.027921 0.030328 0.012086 0.024500 0.017204 0.029068
BA 0.048721 0.046683 0.036258 0.153210 0.071495 0.040533 0.046978 0.038709 0.057794 0.044544 ... 0.027949 0.028347 0.020598 0.043959 0.038288 0.042752 0.025868 0.066807 0.022943 0.059150
BAC 0.048414 0.038349 0.034435 0.071495 0.111835 0.039113 0.040859 0.037445 0.052206 0.042021 ... 0.019256 0.028908 0.015572 0.033126 0.042055 0.034410 0.018756 0.066200 0.018873 0.049334
BRK-A 0.024595 0.021191 0.020063 0.040533 0.039113 0.033714 0.023502 0.019797 0.027814 0.021991 ... 0.013638 0.017355 0.010121 0.021418 0.022737 0.019493 0.014001 0.034440 0.013103 0.027806
CMCSA 0.035208 0.024305 0.024618 0.046978 0.040859 0.023502 0.057333 0.021752 0.032973 0.030959 ... 0.020984 0.017908 0.017326 0.028867 0.027152 0.024151 0.019269 0.037585 0.019625 0.032752
CSCO 0.032776 0.029871 0.033429 0.038709 0.037445 0.019797 0.021752 0.053816 0.029540 0.022064 ... 0.012408 0.018675 0.010794 0.019521 0.023934 0.025704 0.012773 0.028722 0.013351 0.030013
CVX 0.033253 0.030923 0.029565 0.057794 0.052206 0.027814 0.032973 0.029540 0.077586 0.033553 ... 0.020790 0.028355 0.015743 0.033844 0.036562 0.030657 0.023726 0.045095 0.016971 0.048369
DIS 0.031505 0.025385 0.023051 0.044544 0.042021 0.021991 0.030959 0.022064 0.033553 0.056920 ... 0.017698 0.018110 0.014085 0.024192 0.024793 0.023580 0.015572 0.036064 0.014819 0.032562
GOOG 0.039181 0.034584 0.033377 0.046187 0.041239 0.021188 0.027765 0.026473 0.034395 0.025647 ... 0.019194 0.018993 0.014190 0.023519 0.026173 0.031118 0.013943 0.033637 0.014965 0.032697
HD 0.035883 0.029461 0.031927 0.046952 0.043395 0.024425 0.031403 0.027323 0.038951 0.026919 ... 0.019614 0.022295 0.014057 0.030172 0.028216 0.029015 0.017622 0.037549 0.017312 0.036500
INTC 0.034560 0.031181 0.028742 0.038075 0.035214 0.016667 0.019349 0.025758 0.029026 0.019575 ... 0.011643 0.016291 0.010025 0.019228 0.021320 0.024116 0.014841 0.028823 0.013768 0.030328
JNJ 0.024961 0.021511 0.021630 0.029300 0.027020 0.016955 0.019915 0.018391 0.025153 0.019188 ... 0.016085 0.018981 0.011289 0.016840 0.019993 0.018491 0.014410 0.021989 0.014356 0.024536
JPM 0.039005 0.030164 0.026784 0.058871 0.063678 0.032716 0.032819 0.029414 0.042177 0.035748 ... 0.017854 0.024442 0.013471 0.029242 0.033487 0.028395 0.017169 0.053163 0.015468 0.040957
KO 0.021002 0.019884 0.015794 0.035111 0.024555 0.016613 0.021525 0.012122 0.024777 0.020705 ... 0.017403 0.013579 0.012688 0.019414 0.017509 0.019594 0.013033 0.024421 0.011776 0.024102
MA 0.038755 0.038268 0.034982 0.054060 0.042788 0.023406 0.026977 0.029743 0.037326 0.027150 ... 0.019682 0.019836 0.013753 0.024641 0.027099 0.034073 0.013455 0.035527 0.014182 0.036323
MRK 0.015984 0.013940 0.014370 0.028697 0.023184 0.015327 0.019028 0.015860 0.024144 0.015939 ... 0.011811 0.016102 0.010745 0.018679 0.016393 0.016001 0.013962 0.023334 0.010249 0.023150
MSFT 0.032780 0.030852 0.030647 0.035539 0.033658 0.018504 0.020976 0.023401 0.026422 0.021552 ... 0.014538 0.015951 0.009263 0.017079 0.020718 0.025385 0.010761 0.026554 0.013285 0.025588
NVDA 0.075252 0.059769 0.060141 0.073199 0.071040 0.037234 0.047341 0.039946 0.047647 0.035407 ... 0.021397 0.024301 0.014379 0.040008 0.044741 0.044762 0.022711 0.054787 0.027675 0.053333
PEP 0.020074 0.017228 0.015865 0.027949 0.019256 0.013638 0.020984 0.012408 0.020790 0.017698 ... 0.027057 0.013812 0.013275 0.018235 0.013797 0.017117 0.013508 0.019373 0.012453 0.020307
PFE 0.021388 0.017323 0.019125 0.028347 0.028908 0.017355 0.017908 0.018675 0.028355 0.018110 ... 0.013812 0.035912 0.009909 0.019880 0.023114 0.016909 0.015431 0.024295 0.011517 0.025041
PG 0.017338 0.010913 0.009371 0.020598 0.015572 0.010121 0.017326 0.010794 0.015743 0.014085 ... 0.013275 0.009909 0.019170 0.014883 0.010234 0.012540 0.010504 0.016254 0.008889 0.014835
T 0.025990 0.018536 0.018062 0.043959 0.033126 0.021418 0.028867 0.019521 0.033844 0.024192 ... 0.018235 0.019880 0.014883 0.048780 0.023045 0.020505 0.021176 0.031982 0.012922 0.032478
UNH 0.028985 0.026871 0.027921 0.038288 0.042055 0.022737 0.027152 0.023934 0.036562 0.024793 ... 0.013797 0.023114 0.010234 0.023045 0.055844 0.021748 0.016146 0.034628 0.015182 0.033356
V 0.034013 0.032347 0.030328 0.042752 0.034410 0.019493 0.024151 0.025704 0.030657 0.023580 ... 0.017117 0.016909 0.012540 0.020505 0.021748 0.040719 0.012716 0.029078 0.013930 0.029672
VZ 0.014107 0.009231 0.012086 0.025868 0.018756 0.014001 0.019269 0.012773 0.023726 0.015572 ... 0.013508 0.015431 0.010504 0.021176 0.016146 0.012716 0.029218 0.021054 0.014786 0.022385
WFC 0.037520 0.028642 0.024500 0.066807 0.066200 0.034440 0.037585 0.028722 0.045095 0.036064 ... 0.019373 0.024295 0.016254 0.031982 0.034628 0.029078 0.021054 0.089402 0.019261 0.045577
WMT 0.018084 0.014999 0.017204 0.022943 0.018873 0.013103 0.019625 0.013351 0.016971 0.014819 ... 0.012453 0.011517 0.008889 0.012922 0.015182 0.013930 0.014786 0.019261 0.028400 0.018314
XOM 0.035654 0.033042 0.029068 0.059150 0.049334 0.027806 0.032752 0.030013 0.048369 0.032562 ... 0.020307 0.025041 0.014835 0.032478 0.033356 0.029672 0.022385 0.045577 0.018314 0.068875

30 rows Γ— 30 columns

13) Construct efficient frontier based on robust covariance estimate.ΒΆ

In [86]:
# Reconstruct eff. frontier with shrunken covar. matrix
plot_ef(100, er, shrink_cov_ann, style='.-', legend=False, show_cml=True, riskfree_rate=rf, show_ew=True, show_gmv=True);
In [87]:
w_msr_shrink = msr(rf, er, shrink_cov_ann)
r_msr_shrink = portfolio_return(w_msr_shrink, er)
vol_msr_shrink = portfolio_vol(w_msr_shrink, shrink_cov_ann)
In [88]:
w_msr_shrink.round(4), r_msr_shrink, vol_msr_shrink
Out[88]:
(array([0.    , 0.1298, 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ,
        0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    , 0.    ,
        0.    , 0.    , 0.6248, 0.0743, 0.    , 0.    , 0.112 , 0.    ,
        0.    , 0.    , 0.    , 0.    , 0.0591, 0.    ]),
 0.3606247463636462,
 0.1758367934219637)
In [89]:
w_gmv_shrink = gmv(shrink_cov_ann)
r_gmv_shrink = portfolio_return(w_gmv_shrink, er)
vol_gmv_shrink = portfolio_vol(w_gmv_shrink, shrink_cov_ann)
In [90]:
w_gmv_shrink.round(4), r_gmv_shrink, vol_gmv_shrink
Out[90]:
(array([0.    , 0.    , 0.    , 0.    , 0.    , 0.033 , 0.    , 0.    ,
        0.    , 0.    , 0.    , 0.    , 0.0126, 0.    , 0.    , 0.0304,
        0.    , 0.1143, 0.0747, 0.    , 0.0361, 0.0527, 0.3973, 0.    ,
        0.    , 0.    , 0.0779, 0.    , 0.171 , 0.    ]),
 0.14006630956712574,
 0.1171427626203763)

14) Design Risk Parity portfolio.ΒΆ

In [91]:
def risk_contribution(w,cov):
    """
    Compute the relative contributions to risk of the constituents of a portfolio, given a set of portfolio weights 
    and a covariance matrix
    """
    total_portfolio_var = portfolio_vol(w,cov)**2
    # Marginal contribution of each constituent to portfolio variance
    marginal_contrib = cov@w
    # Relative contribution of each constituent to portfolio variance (risk)
    risk_contrib = np.multiply(marginal_contrib,w.T)/total_portfolio_var
    return risk_contrib

a) Relative Risk Contributions in equal weighted PortfolioΒΆ

In [92]:
# Relative Risk Contributions of equally weighted portfolio given sample covar. matrix (Should sum to 1)
RRC_ew = risk_contribution(weight_ew(ind_return), cov)
RRC_ew
Out[92]:
AAPL     0.041617
ADBE     0.035682
AMZN     0.031937
BA       0.057104
BAC      0.052844
BRK-A    0.029925
CMCSA    0.034925
CSCO     0.029006
CVX      0.043989
DIS      0.031075
GOOG     0.038399
HD       0.039628
INTC     0.027321
JNJ      0.025012
JPM      0.043484
KO       0.023248
MA       0.041022
MRK      0.018186
MSFT     0.031031
NVDA     0.053853
PEP      0.019423
PFE      0.022144
PG       0.012853
T        0.029522
UNH      0.031456
V        0.034847
VZ       0.016153
WFC      0.044293
WMT      0.015250
XOM      0.044769
dtype: float64
In [93]:
# Check sum to 1
sum(RRC_ew)
Out[93]:
0.9999999999999999
In [94]:
# Visualize RRC EW Portfolio
risk_contribution(weight_ew(ind_return), cov).plot.bar(title="Relative (%) Risk Contributions of an EW portfolio");
In [95]:
# Visualize constituent weights of EW Portfolio (Should be equal)
weight_ew(ind_return).plot.bar(title="Asset Weights - EW portfolio");
In [96]:
# Portfolio vol of equally weighted portfolio given sample covar. matrix
Port_vol_ew = portfolio_vol(weight_ew(ind_return), cov)
Port_vol_ew
Out[96]:
0.048232240733256285

b) Component Risk of Equal Weighted PortfolioΒΆ

In [97]:
# Risk Contributions (Component Risk) of constituents of ew portfolio (should sum to portfolio vol)
RC_ew = RRC_ew * Port_vol_ew
RC_ew.plot.bar(title="Component Risk of an EW portfolio");
In [98]:
# Check
sum(RC_ew)
Out[98]:
0.04823224073325629

c) Functions to construct Equal Risk Contribution PortfolioΒΆ

In [99]:
from scipy.optimize import minimize

def target_risk_contributions(target_risk, cov):
    """
    Returns a portfolio with constituent security weights such
    that their risk contributions to the portfolio are as close as possible to
    the target_risk contributions for a given the covariance matrix.
    """
    n = cov.shape[0]
    init_guess = np.repeat(1/n, n)
    bounds = ((0.0, 1.0),) * n # an N-tuple of 2-tuples
    # construct the constraints
    weights_sum_to_1 = {'type': 'eq',
                        'fun': lambda weights: np.sum(weights) - 1
    }
    def msd_risk(weights, target_risk, cov):
        """
        The objective function: Minimise the Sum of Squared Differences in the risk contributions to the portfolio
        and the target_risk contributions via the asset weights decision variable 
        """
        w_contribs = risk_contribution(weights, cov)
        return ((w_contribs-target_risk)**2).sum()
    
    weights = minimize(msd_risk, init_guess,
                       args=(target_risk, cov), method='SLSQP',
                       options={'disp': False},
                       constraints=(weights_sum_to_1,),
                       bounds=bounds)
    return weights.x

def equal_risk_contributions(cov):
    """
    Returns the weights of the portfolio that equalizes the risk contributions
    of the constituents based on the given covariance matrix
    """
    n = cov.shape[0]
    return target_risk_contributions(target_risk=np.repeat(1/n,n), cov=cov)

def weight_erc(r, cov_estimator=sample_cov, **kwargs):
    """
    Produces the weights of the ERC portfolio given a returns series and covariance matrix strucrure. 
    """
    est_cov = cov_estimator(r, **kwargs)
    return equal_risk_contributions(est_cov)

d) Relative Risk Contributions in ERC StrategyΒΆ

In [100]:
# RRC of ERC portfolio (Should be equal and sum to 1)
RRC_erc = risk_contribution(equal_risk_contributions(cov), cov)
RRC_erc.plot.bar(title="Relative (%) Risk Contributions of an ERC portfolio");

e) Asset weights of ERC StrategyΒΆ

In [101]:
# Portfolio composition of ERC strategy. (Numpy array)
weight_erc(ind_return, cov_estimator=sample_cov)
Out[101]:
array([0.02450239, 0.02891267, 0.03153895, 0.01812725, 0.01989404,
       0.03348078, 0.0277796 , 0.03456227, 0.02261361, 0.03184053,
       0.02624211, 0.02522825, 0.03710661, 0.037596  , 0.02381996,
       0.04090591, 0.02477875, 0.05077645, 0.0325325 , 0.02011433,
       0.04648977, 0.04229139, 0.06778456, 0.03262246, 0.03177665,
       0.02858275, 0.0540122 , 0.02321643, 0.05854719, 0.02232363])
In [102]:
# Portfolio composition of ERC strategy. (DataFrame)
numpy_weight_erc = weight_erc(ind_return, cov_estimator=sample_cov)
df_weight_erc = pd.DataFrame(data=numpy_weight_erc, index=ind_return.columns,  columns=["ERC Asset Allocation"])
df_weight_erc
Out[102]:
ERC Asset Allocation
AAPL 0.024502
ADBE 0.028913
AMZN 0.031539
BA 0.018127
BAC 0.019894
BRK-A 0.033481
CMCSA 0.027780
CSCO 0.034562
CVX 0.022614
DIS 0.031841
GOOG 0.026242
HD 0.025228
INTC 0.037107
JNJ 0.037596
JPM 0.023820
KO 0.040906
MA 0.024779
MRK 0.050776
MSFT 0.032533
NVDA 0.020114
PEP 0.046490
PFE 0.042291
PG 0.067785
T 0.032622
UNH 0.031777
V 0.028583
VZ 0.054012
WFC 0.023216
WMT 0.058547
XOM 0.022324
In [103]:
df_weight_erc.plot.bar(title="Asset Weights - ERC portfolio", legend=False);
In [104]:
# Portfolio vol of ERC strategy
Port_vol_erc = portfolio_vol(weight_erc(ind_return), cov)
Port_vol_erc
Out[104]:
0.043040285276578265

f) Component Risk of ERC PortfolioΒΆ

In [105]:
# Risk Contribution ERC strategy (Should be equal and sum to portfolio vol)
RC_erc = RRC_erc * Port_vol_erc
RC_erc.plot.bar(title="Component Risk of an ERC portfolio");
In [106]:
# Check
RC_erc.sum()
Out[106]:
0.04304028527657827

15) Design Black-Litterman optimized portfolio.ΒΆ

In [107]:
# Lookback period

BL_per_beg_1 = Start
BL_per_end_1 = End


# Market inputs: rfr. exp returns vector, sample covariance matrix
rf_1 = 0.00
ann_factor_1 = 12
er_1 = annualize_rets(ind_return[BL_per_beg_1:BL_per_end_1] , ann_factor)
ev_1 = annualize_vol(ind_return[BL_per_beg_1:BL_per_end_1], ann_factor)
corr_1 = ind_return[BL_per_beg_1:BL_per_end_1].corr()
cov_1 = ind_return[BL_per_beg_1:BL_per_end_1].cov()

# Data for Views Vector, q

View_1 = 0.20
View_2 = 0.10
View_3 = 0.05

# Data for Pick Matrix, p

Long_1 = 'T'
Short_1 = 'JPM'
Long_2 = 'V'
Short_2 = 'GOOG'
Long_3 = 'UNH'
Short_3 = 'MA'
In [108]:
# Specify investable universe.
assets = list(ind_return.columns)
assets
Out[108]:
['AAPL',
 'ADBE',
 'AMZN',
 'BA',
 'BAC',
 'BRK-A',
 'CMCSA',
 'CSCO',
 'CVX',
 'DIS',
 'GOOG',
 'HD',
 'INTC',
 'JNJ',
 'JPM',
 'KO',
 'MA',
 'MRK',
 'MSFT',
 'NVDA',
 'PEP',
 'PFE',
 'PG',
 'T',
 'UNH',
 'V',
 'VZ',
 'WFC',
 'WMT',
 'XOM']
In [109]:
# Calculate correlation matrix and convert to Dataframe
rho = corr_1
rho
Out[109]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 1.000000 0.700614 0.582240 0.380270 0.517836 0.444515 0.533227 0.494223 0.345771 0.431635 ... 0.363775 0.301593 0.385373 0.334203 0.367953 0.679045 0.096008 0.387123 0.263956 0.457414
ADBE 0.700614 1.000000 0.770998 0.484703 0.448204 0.454062 0.343541 0.560204 0.419138 0.382440 ... 0.369224 0.263297 0.163183 0.203773 0.440520 0.810876 -0.034067 0.298119 0.244133 0.537471
AMZN 0.582240 0.770998 1.000000 0.246641 0.325885 0.374145 0.324668 0.641141 0.350192 0.277179 ... 0.275921 0.310176 0.055438 0.163458 0.442242 0.688607 0.078593 0.164697 0.319126 0.385566
BA 0.380270 0.484703 0.246641 1.000000 0.629046 0.664630 0.539149 0.389265 0.596850 0.490659 ... 0.404854 0.300977 0.296816 0.553654 0.364535 0.619203 0.309924 0.678326 0.232294 0.688292
BAC 0.517836 0.448204 0.325885 0.629046 1.000000 0.810649 0.557198 0.501999 0.657566 0.590028 ... 0.236792 0.448962 0.209290 0.433659 0.600981 0.556478 0.192888 0.860774 0.206416 0.660896
BRK-A 0.444515 0.454062 0.374145 0.664630 0.810649 1.000000 0.605805 0.466224 0.624357 0.540668 ... 0.439785 0.534214 0.332900 0.592964 0.584709 0.588865 0.428866 0.791319 0.383599 0.690730
CMCSA 0.533227 0.343541 0.324668 0.539149 0.557198 0.605805 1.000000 0.319867 0.525435 0.620546 ... 0.602203 0.325992 0.581925 0.628389 0.496363 0.536353 0.478246 0.586616 0.509343 0.579077
CSCO 0.494223 0.560204 0.641141 0.389265 0.501999 0.466224 0.319867 1.000000 0.450991 0.333962 ... 0.187004 0.386280 0.208801 0.298684 0.409854 0.634858 0.180895 0.364834 0.219697 0.522599
CVX 0.345771 0.419138 0.350192 0.596850 0.657566 0.624357 0.525435 0.450991 1.000000 0.546468 ... 0.444176 0.611039 0.353074 0.636936 0.647590 0.627520 0.533327 0.619580 0.259729 0.859999
DIS 0.431635 0.382440 0.277179 0.490659 0.590028 0.540668 0.620546 0.333962 0.546468 1.000000 ... 0.438619 0.337782 0.389477 0.454865 0.416166 0.516261 0.300374 0.547780 0.273828 0.576771
GOOG 0.654312 0.693716 0.613339 0.529939 0.574704 0.508039 0.512732 0.497266 0.576110 0.441563 ... 0.518916 0.380315 0.399397 0.433029 0.468948 0.834754 0.223285 0.483629 0.284158 0.585399
HD 0.542737 0.505450 0.548984 0.529138 0.610291 0.637283 0.621764 0.511175 0.693677 0.470215 ... 0.523227 0.510073 0.376669 0.666938 0.524565 0.726324 0.389617 0.575692 0.386620 0.687365
INTC 0.514641 0.571557 0.456478 0.348978 0.415988 0.294693 0.211472 0.463874 0.406879 0.221834 ... 0.127739 0.254557 0.141305 0.263680 0.290044 0.534675 0.261725 0.341665 0.218898 0.501687
JNJ 0.503708 0.514118 0.484352 0.392479 0.460389 0.592359 0.487537 0.443044 0.569086 0.456161 ... 0.654612 0.681768 0.468864 0.408370 0.503903 0.584328 0.500497 0.377445 0.510584 0.605528
JPM 0.518329 0.427040 0.298984 0.653687 0.950845 0.859990 0.554626 0.478354 0.661235 0.649474 ... 0.342806 0.494589 0.259243 0.519959 0.589101 0.581745 0.282649 0.857182 0.218336 0.695704
KO 0.353705 0.443898 0.231510 0.566434 0.379612 0.575389 0.568677 0.136529 0.557852 0.532966 ... 0.751216 0.359273 0.588649 0.545761 0.387250 0.651386 0.411959 0.474295 0.338845 0.590943
MA 0.628146 0.800730 0.650832 0.684522 0.600044 0.596123 0.473020 0.602241 0.650400 0.482444 ... 0.531120 0.406633 0.362209 0.463902 0.489719 0.940006 0.190885 0.524186 0.236059 0.686957
MRK 0.167124 0.181567 0.177656 0.390041 0.343622 0.508330 0.461645 0.332435 0.545620 0.314324 ... 0.372490 0.525696 0.440016 0.521086 0.344102 0.459672 0.487436 0.445036 0.244548 0.563427
MSFT 0.689640 0.809427 0.755718 0.479077 0.581339 0.582706 0.445954 0.583700 0.521230 0.474292 ... 0.454040 0.410324 0.231106 0.339300 0.446632 0.842374 0.190097 0.458451 0.354887 0.548653
NVDA 0.650334 0.574116 0.543208 0.353374 0.464397 0.422272 0.400126 0.288680 0.283729 0.184797 ... 0.104767 0.096694 -0.009783 0.327762 0.363512 0.505433 0.116919 0.336889 0.253872 0.424166
PEP 0.363775 0.369224 0.275921 0.404854 0.236792 0.439785 0.602203 0.187004 0.444176 0.438619 ... 1.000000 0.422862 0.702414 0.540534 0.246574 0.568056 0.497497 0.324485 0.435136 0.477491
PFE 0.301593 0.263297 0.310176 0.300977 0.448962 0.534214 0.325992 0.386280 0.611039 0.337782 ... 0.422862 1.000000 0.291966 0.486611 0.568963 0.421027 0.489444 0.394215 0.257942 0.543688
PG 0.385373 0.163183 0.055438 0.296816 0.209290 0.332900 0.581925 0.208801 0.353074 0.389477 ... 0.702414 0.291966 1.000000 0.510042 0.162225 0.434372 0.424351 0.321915 0.298629 0.353217
T 0.334203 0.203773 0.163458 0.553654 0.433659 0.592964 0.628389 0.298684 0.636936 0.454865 ... 0.540534 0.486611 0.510042 1.000000 0.419724 0.456825 0.658508 0.505242 0.231000 0.657295
UNH 0.367953 0.440520 0.442242 0.364535 0.600981 0.584709 0.496363 0.409854 0.647590 0.416166 ... 0.246574 0.568963 0.162225 0.419724 1.000000 0.448814 0.336093 0.516818 0.299103 0.612346
V 0.679045 0.810876 0.688607 0.619203 0.556478 0.588865 0.536353 0.634858 0.627520 0.516261 ... 0.568056 0.421027 0.434372 0.456825 0.448814 1.000000 0.273975 0.500538 0.355954 0.657262
VZ 0.096008 -0.034067 0.078593 0.309924 0.192888 0.428866 0.478246 0.180895 0.533327 0.300374 ... 0.497497 0.489444 0.424351 0.658508 0.336093 0.273975 1.000000 0.360569 0.563258 0.534676
WFC 0.387123 0.298119 0.164697 0.678326 0.860774 0.791319 0.586616 0.364834 0.619580 0.547780 ... 0.324485 0.394215 0.321915 0.505242 0.516818 0.500538 0.360569 1.000000 0.301153 0.698304
WMT 0.263956 0.244133 0.319126 0.232294 0.206416 0.383599 0.509343 0.219697 0.259729 0.273828 ... 0.435136 0.257942 0.298629 0.231000 0.299103 0.355954 0.563258 0.301153 1.000000 0.364863
XOM 0.457414 0.537471 0.385566 0.688292 0.660896 0.690730 0.579077 0.522599 0.859999 0.576771 ... 0.477491 0.543688 0.353217 0.657295 0.612346 0.657262 0.534676 0.698304 0.364863 1.000000

30 rows Γ— 30 columns

In [110]:
# Calculate expected volatilities of securities
vols = pd.DataFrame(ev_1, columns=["Vols"])
vols
Out[110]:
Vols
AAPL 0.295099
ADBE 0.251604
AMZN 0.260945
BA 0.391421
BAC 0.334418
BRK-A 0.183612
CMCSA 0.239443
CSCO 0.231982
CVX 0.278542
DIS 0.238579
GOOG 0.237595
HD 0.241727
INTC 0.239499
JNJ 0.174936
JPM 0.269292
KO 0.174216
MA 0.240644
MRK 0.171822
MSFT 0.192687
NVDA 0.457953
PEP 0.164489
PFE 0.189503
PG 0.138455
T 0.220863
UNH 0.236314
V 0.201790
VZ 0.170932
WFC 0.299001
WMT 0.168523
XOM 0.262441
In [111]:
# Market weights (optimal assumimg market equilibrium)
w_eq = ind_capweight.loc[BL_per_end_1]
w_eq
Out[111]:
AAPL     0.125112
ADBE     0.016942
AMZN     0.111558
BA       0.007735
BAC      0.019287
BRK-A    0.040388
CMCSA    0.016481
CSCO     0.017546
CVX      0.015525
DIS      0.019389
GOOG     0.088141
HD       0.015132
INTC     0.005953
JNJ      0.056430
JPM      0.023215
KO       0.012934
MA       0.116730
MRK      0.007155
MSFT     0.041667
NVDA     0.019520
PEP      0.016527
PFE      0.017612
PG       0.026773
T        0.019612
UNH      0.026102
V        0.037340
VZ       0.020614
WFC      0.010003
WMT      0.031556
XOM      0.017021
Name: 2020-06, dtype: float64
In [112]:
# Define prior covariance matrix (sample annualised covar matrix here)
sigma_prior = vols.dot(vols.T) * rho
sigma_prior
Out[112]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 0.087083 0.052019 0.044835 0.043924 0.051103 0.024086 0.037678 0.033833 0.028422 0.030389 ... 0.017658 0.016866 0.015746 0.021782 0.025660 0.040436 0.004843 0.034158 0.013127 0.035425
ADBE 0.052019 0.063305 0.050620 0.047735 0.037712 0.020977 0.020697 0.032698 0.029374 0.022957 ... 0.015281 0.012554 0.005685 0.011324 0.026192 0.041169 -0.001465 0.022428 0.010351 0.035490
AMZN 0.044835 0.050620 0.068092 0.025192 0.028438 0.017926 0.020286 0.038811 0.025453 0.017256 ... 0.011843 0.015338 0.002003 0.009421 0.027271 0.036259 0.003506 0.012850 0.014034 0.026405
BA 0.043924 0.047735 0.025192 0.153210 0.082341 0.047767 0.050531 0.035346 0.065073 0.045820 ... 0.026066 0.022325 0.016086 0.047864 0.033719 0.048908 0.020736 0.079388 0.015323 0.070705
BAC 0.051103 0.037712 0.028438 0.082341 0.111835 0.049777 0.044617 0.038945 0.061252 0.047076 ... 0.013025 0.028452 0.009691 0.032030 0.047494 0.037552 0.011026 0.086070 0.011633 0.058004
BRK-A 0.024086 0.020977 0.017926 0.047767 0.049777 0.033714 0.026634 0.019859 0.031932 0.023685 ... 0.013283 0.018588 0.008463 0.024047 0.025371 0.021818 0.013460 0.043444 0.011870 0.033285
CMCSA 0.037678 0.020697 0.020286 0.050531 0.044617 0.026634 0.057333 0.017767 0.035044 0.035449 ... 0.023718 0.014792 0.019292 0.033232 0.028086 0.025915 0.019574 0.041998 0.020553 0.036389
CSCO 0.033833 0.032698 0.038811 0.035346 0.038945 0.019859 0.017767 0.053816 0.029142 0.018483 ... 0.007136 0.016981 0.006706 0.015303 0.022468 0.029719 0.007173 0.025306 0.008589 0.031817
CVX 0.028422 0.029374 0.025453 0.065073 0.061252 0.031932 0.035044 0.029142 0.077586 0.036315 ... 0.020351 0.032253 0.013617 0.039184 0.042627 0.035271 0.025393 0.051601 0.012192 0.062867
DIS 0.030389 0.022957 0.017256 0.045820 0.047076 0.023685 0.035449 0.018483 0.036315 0.056920 ... 0.017213 0.015272 0.012865 0.023968 0.023463 0.024854 0.012250 0.039076 0.011010 0.036113
GOOG 0.045877 0.041470 0.038027 0.049284 0.045664 0.022163 0.029170 0.027408 0.038127 0.025030 ... 0.020280 0.017124 0.013139 0.022724 0.026330 0.040022 0.009068 0.034358 0.011378 0.036502
HD 0.038715 0.030741 0.034628 0.050065 0.049335 0.028285 0.035988 0.028665 0.046706 0.027118 ... 0.020804 0.023365 0.012606 0.035607 0.029965 0.035429 0.016099 0.041609 0.015750 0.043606
INTC 0.036373 0.034442 0.028528 0.032715 0.033318 0.012959 0.012127 0.025773 0.027143 0.012676 ... 0.005032 0.011553 0.004686 0.013948 0.016416 0.025840 0.010715 0.024467 0.008835 0.031533
JNJ 0.026003 0.022629 0.022110 0.026875 0.026934 0.019027 0.020422 0.017980 0.027730 0.019038 ... 0.018837 0.022601 0.011356 0.015778 0.020831 0.020627 0.014966 0.019743 0.015052 0.027800
JPM 0.041191 0.028934 0.021010 0.068903 0.085629 0.042523 0.035762 0.029883 0.049599 0.041727 ... 0.015185 0.025240 0.009666 0.030925 0.037489 0.031612 0.013011 0.069019 0.009908 0.049168
KO 0.018184 0.019458 0.010525 0.038626 0.022117 0.018406 0.023722 0.005518 0.027071 0.022152 ... 0.021527 0.011861 0.014199 0.021000 0.015943 0.022900 0.012268 0.024706 0.009948 0.027019
MA 0.044607 0.048482 0.040869 0.064477 0.048289 0.026340 0.027256 0.033620 0.043596 0.027698 ... 0.021023 0.018544 0.012068 0.024656 0.027849 0.045646 0.007852 0.037717 0.009573 0.043385
MRK 0.008474 0.007849 0.007965 0.026232 0.019745 0.016037 0.018993 0.013251 0.026113 0.012885 ... 0.010528 0.017117 0.010468 0.019775 0.013972 0.015938 0.014316 0.022864 0.007081 0.025407
MSFT 0.039214 0.039242 0.037998 0.036133 0.037460 0.020616 0.020575 0.026091 0.027975 0.021804 ... 0.014391 0.014983 0.006166 0.014440 0.020337 0.032753 0.006261 0.026413 0.011524 0.027745
NVDA 0.087887 0.066151 0.064914 0.063343 0.071121 0.035507 0.043875 0.030668 0.036192 0.020191 ... 0.007892 0.008391 -0.000620 0.033151 0.039340 0.046707 0.009152 0.046130 0.019593 0.050979
PEP 0.017658 0.015281 0.011843 0.026066 0.013025 0.013283 0.023718 0.007136 0.020351 0.017213 ... 0.027057 0.013181 0.015997 0.019637 0.009585 0.018855 0.013988 0.015959 0.012062 0.020613
PFE 0.016866 0.012554 0.015338 0.022325 0.028452 0.018588 0.014792 0.016981 0.032253 0.015272 ... 0.013181 0.035912 0.007661 0.020367 0.025480 0.016100 0.015854 0.022337 0.008238 0.027040
PG 0.015746 0.005685 0.002003 0.016086 0.009691 0.008463 0.019292 0.006706 0.013617 0.012865 ... 0.015997 0.007661 0.019170 0.015597 0.005308 0.012136 0.010043 0.013327 0.006968 0.012835
T 0.021782 0.011324 0.009421 0.047864 0.032030 0.024047 0.033232 0.015303 0.039184 0.023968 ... 0.019637 0.020367 0.015597 0.048780 0.021907 0.020360 0.024860 0.033365 0.008598 0.038099
UNH 0.025660 0.026192 0.027271 0.033719 0.047494 0.025371 0.028086 0.022468 0.042627 0.023463 ... 0.009585 0.025480 0.005308 0.021907 0.055844 0.021402 0.013576 0.036517 0.011912 0.037977
V 0.040436 0.041169 0.036259 0.048908 0.037552 0.021818 0.025915 0.029719 0.035271 0.024854 ... 0.018855 0.016100 0.012136 0.020360 0.021402 0.040719 0.009450 0.030200 0.012105 0.034807
VZ 0.004843 -0.001465 0.003506 0.020736 0.011026 0.013460 0.019574 0.007173 0.025393 0.012250 ... 0.013988 0.015854 0.010043 0.024860 0.013576 0.009450 0.029218 0.018428 0.016225 0.023985
WFC 0.034158 0.022428 0.012850 0.079388 0.086070 0.043444 0.041998 0.025306 0.051601 0.039076 ... 0.015959 0.022337 0.013327 0.033365 0.036517 0.030200 0.018428 0.089402 0.015175 0.054796
WMT 0.013127 0.010351 0.014034 0.015323 0.011633 0.011870 0.020553 0.008589 0.012192 0.011010 ... 0.012062 0.008238 0.006968 0.008598 0.011912 0.012105 0.016225 0.015175 0.028400 0.016137
XOM 0.035425 0.035490 0.026405 0.070705 0.058004 0.033285 0.036389 0.031817 0.062867 0.036113 ... 0.020613 0.027040 0.012835 0.038099 0.037977 0.034807 0.023985 0.054796 0.016137 0.068875

30 rows Γ— 30 columns

In [113]:
# Compute Equilibrium-implied returns vector and convert to series

def implied_returns(delta, sigma, w):
    """
Obtain the implied expected returns by reverse engineering the weights
Inputs:
delta: Risk Aversion Coefficient (scalar)
sigma: Variance-Covariance Matrix (N x N) as DataFrame
    w: Market weights (N x 1) as Series
Returns an N x 1 vector of Returns as Series
    """
    ir = delta * sigma.dot(w).squeeze() # to get a series from a 1-column dataframe
    ir.name = 'Implied Returns'
    return ir

# Compute Pi and compare:
pi = implied_returns(delta=2.5, sigma=sigma_prior, w=w_eq)
In [114]:
(pi*100).round(2)
Out[114]:
AAPL     10.63
ADBE      9.09
AMZN      8.68
BA       11.09
BAC      10.62
BRK-A     5.92
CMCSA     7.07
CSCO      6.82
CVX       8.57
DIS       6.27
GOOG      9.15
HD        8.61
INTC      6.33
JNJ       5.52
JPM       8.67
KO        4.79
MA        9.58
MRK       3.29
MSFT      7.58
NVDA     13.08
PEP       4.17
PFE       4.46
PG        2.65
T         5.44
UNH       6.52
V         8.19
VZ        2.63
WFC       8.16
WMT       3.19
XOM       8.82
Name: Implied Returns, dtype: float64
In [115]:
# Populate views vector , Q: (X will outperform Y by Z%)
q = pd.Series([View_1]) # First view
# start with a single view and an empty Pick Matrix, to be overwritten with the specific pick(s) + view(s)
p = pd.DataFrame([0.]*len(assets), index=assets).T
In [116]:
q
Out[116]:
0    0.2
dtype: float64
In [117]:
p
Out[117]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0

1 rows Γ— 30 columns

In [118]:
# Pick 1
p.iloc[0][Long_1] = +1.
p.iloc[0][Short_1] = -1
(p*100).round(1)
Out[118]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 100.0 0.0 0.0 0.0 0.0 0.0 0.0

1 rows Γ— 30 columns

In [119]:
# Add second view
view2 = pd.Series([View_2], index=[1])
q = q.append(view2)
pick2 = pd.DataFrame([0.]*len(assets), index=assets, columns=[1]).T
p = p.append(pick2)
p.iloc[1][Long_2]=+1
p.iloc[1][Short_2]=-1
np.round(p.T, 3)*100
Out[119]:
0 1
AAPL 0.0 0.0
ADBE 0.0 0.0
AMZN 0.0 0.0
BA 0.0 0.0
BAC 0.0 0.0
BRK-A 0.0 0.0
CMCSA 0.0 0.0
CSCO 0.0 0.0
CVX 0.0 0.0
DIS 0.0 0.0
GOOG 0.0 -100.0
HD 0.0 0.0
INTC 0.0 0.0
JNJ 0.0 0.0
JPM -100.0 0.0
KO 0.0 0.0
MA 0.0 0.0
MRK 0.0 0.0
MSFT 0.0 0.0
NVDA 0.0 0.0
PEP 0.0 0.0
PFE 0.0 0.0
PG 0.0 0.0
T 100.0 0.0
UNH 0.0 0.0
V 0.0 100.0
VZ 0.0 0.0
WFC 0.0 0.0
WMT 0.0 0.0
XOM 0.0 0.0
In [120]:
# Add third view
view3 = pd.Series([View_3], index=[2])
q = q.append(view3)
pick3 = pd.DataFrame([0.]*len(assets), index=assets, columns=[2]).T
p = p.append(pick3)
p.iloc[2][Long_3]=+1
p.iloc[2][Short_3]=-1
np.round(p.T, 3)*100
Out[120]:
0 1 2
AAPL 0.0 0.0 0.0
ADBE 0.0 0.0 0.0
AMZN 0.0 0.0 0.0
BA 0.0 0.0 0.0
BAC 0.0 0.0 0.0
BRK-A 0.0 0.0 0.0
CMCSA 0.0 0.0 0.0
CSCO 0.0 0.0 0.0
CVX 0.0 0.0 0.0
DIS 0.0 0.0 0.0
GOOG 0.0 -100.0 0.0
HD 0.0 0.0 0.0
INTC 0.0 0.0 0.0
JNJ 0.0 0.0 0.0
JPM -100.0 0.0 0.0
KO 0.0 0.0 0.0
MA 0.0 0.0 -100.0
MRK 0.0 0.0 0.0
MSFT 0.0 0.0 0.0
NVDA 0.0 0.0 0.0
PEP 0.0 0.0 0.0
PFE 0.0 0.0 0.0
PG 0.0 0.0 0.0
T 100.0 0.0 0.0
UNH 0.0 0.0 100.0
V 0.0 100.0 0.0
VZ 0.0 0.0 0.0
WFC 0.0 0.0 0.0
WMT 0.0 0.0 0.0
XOM 0.0 0.0 0.0
In [121]:
# Calculate Omega as proportional to the variance of the prior
def proportional_prior(sigma, tau, p):
    """
    Returns the He-Litterman simplified Omega
    Inputs:
    sigma: N x N Covariance Matrix as DataFrame
    tau: a scalar
    p: a K x N DataFrame linking Q and Assets
    returns a P x P DataFrame, a Matrix representing Prior Uncertainties
    """
    helit_omega = p.dot(tau * sigma).dot(p.T)
    # Make a diag matrix from the diag elements of Omega
    return pd.DataFrame(np.diag(np.diag(helit_omega.values)),index=p.index, columns=p.index)
In [122]:
# Program to compute the posterior expected returns based on the original black litterman reference model

from numpy.linalg import inv

def bl(w_prior, sigma_prior, p, q,
                omega=None,
                delta=2.5, tau=.02):
    """
# Computes the posterior expected returns based on the original black litterman reference model
# W.prior must be an N x 1 vector of weights, a Series
# Sigma.prior is an N x N covariance matrix, a DataFrame
# P must be a K x N matrix linking Q and the Assets, a DataFrame
# Q must be an K x 1 vector of views, a Series
# Omega must be a K x K matrix a DataFrame, or None
# if Omega is None, we assume it is proportional to variance of the prior
# delta and tau are scalars
    """
    if omega is None:
        omega = proportional_prior(sigma_prior, tau, p)
    # Force w.prior and Q to be column vectors
    # How many assets?
    N = w_prior.shape[0]
    # How many views?
    K = q.shape[0]
    # First, reverse-engineer the weights to get pi
    pi = implied_returns(delta, sigma_prior,  w_prior)
    # Adjust (scale) Sigma by the uncertainty scaling factor
    sigma_prior_scaled = tau * sigma_prior  
    # posterior estimate of the mean, use the "Master Formula"
    # we use the versions that do not require
    # Omega to be inverted (see previous section)
    # this is easier to read if we use '@' for matrixmult instead of .dot()
    #     mu_bl = pi + sigma_prior_scaled @ p.T @ inv(p @ sigma_prior_scaled @ p.T + omega) @ (q - p @ pi)
    mu_bl = pi + sigma_prior_scaled.dot(p.T).dot(inv(p.dot(sigma_prior_scaled).dot(p.T) + omega).dot(q - p.dot(pi).values))
    # posterior estimate of uncertainty of mu.bl
    #sigma_bl = sigma_prior + sigma_prior_scaled - sigma_prior_scaled @ p.T @ inv(p @ sigma_prior_scaled @ p.T + omega) @ p @ sigma_prior_scaled
    sigma_bl = sigma_prior + sigma_prior_scaled - sigma_prior_scaled.dot(p.T).dot(inv(p.dot(sigma_prior_scaled).dot(p.T) + omega)).dot(p).dot(sigma_prior_scaled)
    return (mu_bl, sigma_bl)
In [123]:
# Specify scalars

delta = 2.5
tau = 0.05 

# Derive the Black Litterman Expected Returns
bl_mu, bl_sigma = bl(w_eq, sigma_prior, p, q, omega=None, delta=delta, tau= tau)
(bl_mu*100).round(2)
Out[123]:
AAPL     3.74
ADBE     3.90
AMZN     4.86
BA       4.56
BAC     -2.19
BRK-A    2.22
CMCSA    5.62
CSCO     3.90
CVX      5.61
DIS      2.50
GOOG    -0.23
HD       4.83
INTC     0.73
JNJ      2.95
JPM     -0.83
KO       2.72
MA       3.75
MRK      4.74
MSFT     1.56
NVDA     5.62
PEP      3.67
PFE      3.76
PG       2.93
T        7.87
UNH      4.19
V        4.37
VZ       5.45
WFC     -0.02
WMT      3.35
XOM      5.75
dtype: float64
In [124]:
(bl_sigma*100).round(2)
Out[124]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
AAPL 9.11 5.43 4.69 4.57 5.32 2.51 3.95 3.53 2.97 3.17 ... 1.85 1.77 1.65 2.30 2.70 4.22 0.52 3.55 1.38 3.70
ADBE 5.43 6.61 5.29 4.97 3.92 2.19 2.17 3.41 3.08 2.39 ... 1.60 1.32 0.59 1.20 2.77 4.29 -0.14 2.33 1.09 3.71
AMZN 4.69 5.29 7.14 2.62 2.96 1.87 2.13 4.06 2.67 1.80 ... 1.24 1.61 0.21 1.00 2.87 3.79 0.38 1.33 1.47 2.76
BA 4.57 4.97 2.62 16.03 8.60 5.00 5.30 3.68 6.82 4.79 ... 2.73 2.35 1.69 5.04 3.56 5.09 2.20 8.30 1.61 7.41
BAC 5.32 3.92 2.96 8.60 11.61 5.18 4.68 4.06 6.41 4.90 ... 1.38 2.98 1.03 3.40 4.95 3.92 1.19 8.95 1.22 6.06
BRK-A 2.51 2.19 1.87 5.00 5.18 3.53 2.79 2.07 3.34 2.47 ... 1.40 1.95 0.89 2.54 2.65 2.28 1.42 4.53 1.25 3.49
CMCSA 3.95 2.17 2.13 5.30 4.68 2.79 6.02 1.87 3.68 3.72 ... 2.49 1.55 2.03 3.49 2.94 2.72 2.06 4.40 2.16 3.82
CSCO 3.53 3.41 4.06 3.68 4.06 2.07 1.87 5.64 3.05 1.93 ... 0.75 1.78 0.70 1.62 2.36 3.10 0.76 2.64 0.90 3.33
CVX 2.97 3.08 2.67 6.82 6.41 3.34 3.68 3.05 8.14 3.81 ... 2.14 3.38 1.43 4.12 4.47 3.70 2.67 5.40 1.28 6.60
DIS 3.17 2.39 1.80 4.79 4.90 2.47 3.72 1.93 3.81 5.96 ... 1.81 1.60 1.35 2.53 2.46 2.60 1.30 4.08 1.16 3.78
GOOG 4.78 4.32 3.97 5.13 4.75 2.32 3.05 2.87 3.99 2.61 ... 2.12 1.80 1.37 2.39 2.77 4.17 0.96 3.58 1.20 3.82
HD 4.05 3.21 3.62 5.24 5.16 2.97 3.78 3.00 4.90 2.84 ... 2.18 2.46 1.32 3.74 3.15 3.70 1.70 4.36 1.66 4.57
INTC 3.79 3.60 2.98 3.41 3.47 1.35 1.27 2.70 2.84 1.32 ... 0.52 1.21 0.49 1.47 1.73 2.70 1.13 2.55 0.93 3.30
JNJ 2.72 2.37 2.32 2.81 2.81 1.99 2.14 1.88 2.91 1.99 ... 1.98 2.37 1.19 1.66 2.18 2.16 1.58 2.06 1.58 2.91
JPM 4.29 3.00 2.18 7.19 8.89 4.43 3.75 3.11 5.19 4.35 ... 1.60 2.64 1.02 3.28 3.91 3.30 1.39 7.18 1.04 5.14
KO 1.90 2.03 1.10 4.04 2.31 1.93 2.49 0.57 2.84 2.32 ... 2.25 1.25 1.49 2.21 1.68 2.39 1.29 2.59 1.05 2.83
MA 4.64 5.05 4.27 6.72 5.03 2.75 2.86 3.51 4.57 2.89 ... 2.19 1.95 1.26 2.60 2.95 4.75 0.84 3.93 1.01 4.54
MRK 0.89 0.83 0.84 2.76 2.08 1.69 2.00 1.39 2.74 1.36 ... 1.10 1.80 1.10 2.07 1.47 1.67 1.50 2.41 0.74 2.67
MSFT 4.09 4.09 3.97 3.76 3.89 2.15 2.16 2.72 2.93 2.27 ... 1.50 1.57 0.65 1.52 2.14 3.41 0.67 2.75 1.21 2.90
NVDA 9.19 6.92 6.80 6.61 7.42 3.72 4.60 3.21 3.79 2.11 ... 0.82 0.88 -0.07 3.49 4.14 4.88 0.97 4.81 2.06 5.34
PEP 1.85 1.60 1.24 2.73 1.38 1.40 2.49 0.75 2.14 1.81 ... 2.83 1.39 1.67 2.06 1.02 1.97 1.47 1.68 1.27 2.16
PFE 1.77 1.32 1.61 2.35 2.98 1.95 1.55 1.78 3.38 1.60 ... 1.39 3.77 0.81 2.14 2.66 1.70 1.67 2.34 0.86 2.84
PG 1.65 0.59 0.21 1.69 1.03 0.89 2.03 0.70 1.43 1.35 ... 1.67 0.81 2.01 1.63 0.57 1.27 1.05 1.41 0.73 1.35
T 2.30 1.20 1.00 5.04 3.40 2.54 3.49 1.62 4.12 2.53 ... 2.06 2.14 1.63 5.11 2.31 2.14 2.60 3.53 0.90 4.01
UNH 2.70 2.77 2.87 3.56 4.95 2.65 2.94 2.36 4.47 2.46 ... 1.02 2.66 0.57 2.31 5.82 2.27 1.43 3.81 1.25 3.99
V 4.22 4.29 3.79 5.09 3.92 2.28 2.72 3.10 3.70 2.60 ... 1.97 1.70 1.27 2.14 2.27 4.24 1.00 3.15 1.27 3.64
VZ 0.52 -0.14 0.38 2.20 1.19 1.42 2.06 0.76 2.67 1.30 ... 1.47 1.67 1.05 2.60 1.43 1.00 3.06 1.95 1.70 2.53
WFC 3.55 2.33 1.33 8.30 8.95 4.53 4.40 2.64 5.40 4.08 ... 1.68 2.34 1.41 3.53 3.81 3.15 1.95 9.33 1.59 5.74
WMT 1.38 1.09 1.47 1.61 1.22 1.25 2.16 0.90 1.28 1.16 ... 1.27 0.86 0.73 0.90 1.25 1.27 1.70 1.59 2.98 1.69
XOM 3.70 3.71 2.76 7.41 6.06 3.49 3.82 3.33 6.60 3.78 ... 2.16 2.84 1.35 4.01 3.99 3.64 2.53 5.74 1.69 7.23

30 rows Γ— 30 columns

In [125]:
# BL-implied Alpha : BL Exp Returns - Equilibrium Impl. Returns

((bl_mu*100) - (pi*100)).round(2)
Out[125]:
AAPL     -6.89
ADBE     -5.19
AMZN     -3.83
BA       -6.53
BAC     -12.81
BRK-A    -3.70
CMCSA    -1.44
CSCO     -2.92
CVX      -2.96
DIS      -3.76
GOOG     -9.38
HD       -3.79
INTC     -5.60
JNJ      -2.57
JPM      -9.50
KO       -2.07
MA       -5.83
MRK       1.45
MSFT     -6.02
NVDA     -7.46
PEP      -0.50
PFE      -0.71
PG        0.28
T         2.43
UNH      -2.32
V        -3.82
VZ        2.82
WFC      -8.18
WMT       0.16
XOM      -3.06
dtype: float64
In [126]:
# for convenience and readability, define the inverse of a dataframe
def inverse(d):
    """
    Invert the dataframe by inverting the underlying matrix
    """
    return pd.DataFrame(inv(d.values), index=d.columns, columns=d.index)

def w_msr(sigma, mu, scale=True):
    """
    Optimal (Tangent/Max Sharpe Ratio) Portfolio weights
    by using the Markowitz Optimization Procedure
    Mu is the vector of Excess expected Returns
    Sigma must be an N x N matrix as a DataFrame and Mu a column vector as a Series
    This implements page 188 Equation 5.2.28 of
    "The econometrics of financial markets" Campbell, Lo and Mackinlay.
    """
    w = inverse(sigma).dot(mu)
    if scale:
        w = w/sum(w) # fix: this assumes all w is +ve
    return w
In [127]:
# Optimal BL portfolio weights
bl_port = w_msr(bl_sigma,bl_mu)
bl_port.plot(kind='bar')
Out[127]:
<matplotlib.axes._subplots.AxesSubplot at 0x19810ad8da0>
In [128]:
eq_port = w_msr(sigma_prior,pi, scale=True)
eq_port.plot(kind='bar')
Out[128]:
<matplotlib.axes._subplots.AxesSubplot at 0x1980cc4d6d8>
In [129]:
sum(bl_port), sum(eq_port)
Out[129]:
(1.0, 1.0000000000000002)
In [130]:
def w_star(delta, sigma, mu):
    return (inverse(sigma).dot(mu))/delta
In [131]:
wstar = w_star(delta=delta, sigma=bl_sigma, mu=bl_mu)
In [132]:
# display w*
(wstar*100).round(4)
Out[132]:
AAPL      11.9155
ADBE       1.6135
AMZN      10.6246
BA         0.7367
BAC        1.8369
BRK-A      3.8464
CMCSA      1.5696
CSCO       1.6711
CVX        1.4786
DIS        1.8466
GOOG    -114.1597
HD         1.4412
INTC       0.5669
JNJ        5.3743
JPM      -71.5303
KO         1.2318
MA       -18.8899
MRK        0.6815
MSFT       3.9682
NVDA       1.8590
PEP        1.5740
PFE        1.6773
PG         2.5498
T         75.6091
UNH       32.4929
V        126.1102
VZ         1.9633
WFC        0.9526
WMT        3.0053
XOM        1.6210
dtype: float64
In [133]:
sum(wstar)
Out[133]:
0.9523809523809543
In [134]:
# Name BL optimal portfolio
alt_wstar = (w_msr(sigma=bl_sigma, mu=bl_mu,scale=True)*100).round(4)
alt_wstar
Out[134]:
AAPL      12.5112
ADBE       1.6942
AMZN      11.1558
BA         0.7735
BAC        1.9287
BRK-A      4.0388
CMCSA      1.6481
CSCO       1.7546
CVX        1.5525
DIS        1.9389
GOOG    -119.8677
HD         1.5132
INTC       0.5953
JNJ        5.6430
JPM      -75.1068
KO         1.2934
MA       -19.8344
MRK        0.7155
MSFT       4.1667
NVDA       1.9520
PEP        1.6527
PFE        1.7612
PG         2.6773
T         79.3896
UNH       34.1176
V        132.4157
VZ         2.0614
WFC        1.0003
WMT        3.1556
XOM        1.7021
dtype: float64
In [135]:
sum(alt_wstar)
Out[135]:
99.99999999999999
In [136]:
# Transpose & Export for Backtesting purposes
df_alt_wstar = pd.DataFrame(alt_wstar, columns=[ind_return.index[-1]]).T
#df_alt_wstar.to_excel("BL_WEIGHTS4.5.xlsx", sheet_name=End)
df_alt_wstar 
Out[136]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
2020-06 12.5112 1.6942 11.1558 0.7735 1.9287 4.0388 1.6481 1.7546 1.5525 1.9389 ... 1.6527 1.7612 2.6773 79.3896 34.1176 132.4157 2.0614 1.0003 3.1556 1.7021

1 rows Γ— 30 columns

In [137]:
# Test: Market inputs should give market weights as output
w_eq_check  = w_msr(delta*sigma_prior, pi, scale=False)
w_eq_check
Out[137]:
AAPL     0.125112
ADBE     0.016942
AMZN     0.111558
BA       0.007735
BAC      0.019287
BRK-A    0.040388
CMCSA    0.016481
CSCO     0.017546
CVX      0.015525
DIS      0.019389
GOOG     0.088141
HD       0.015132
INTC     0.005953
JNJ      0.056430
JPM      0.023215
KO       0.012934
MA       0.116730
MRK      0.007155
MSFT     0.041667
NVDA     0.019520
PEP      0.016527
PFE      0.017612
PG       0.026773
T        0.019612
UNH      0.026102
V        0.037340
VZ       0.020614
WFC      0.010003
WMT      0.031556
XOM      0.017021
dtype: float64
In [138]:
np.round((w_eq - w_eq_check), 6)*100
Out[138]:
AAPL    -0.0
ADBE     0.0
AMZN    -0.0
BA      -0.0
BAC     -0.0
BRK-A   -0.0
CMCSA    0.0
CSCO    -0.0
CVX     -0.0
DIS     -0.0
GOOG     0.0
HD       0.0
INTC     0.0
JNJ      0.0
JPM      0.0
KO      -0.0
MA       0.0
MRK      0.0
MSFT     0.0
NVDA    -0.0
PEP      0.0
PFE     -0.0
PG      -0.0
T       -0.0
UNH      0.0
V       -0.0
VZ       0.0
WFC     -0.0
WMT      0.0
XOM      0.0
dtype: float64
In [139]:
# BL-implied Alpha : BL Exp Returns - Equilibrium Impl. Returns

Exp_Active_ret = (((bl_mu) - (pi))*(100)).round(2)
Exp_Active_ret.plot(kind='bar', title = "BL-implied Active Return");
In [140]:
np.round(wstar - w_eq/(1+tau), 3)
Out[140]:
AAPL    -0.000
ADBE     0.000
AMZN    -0.000
BA      -0.000
BAC     -0.000
BRK-A   -0.000
CMCSA    0.000
CSCO     0.000
CVX      0.000
DIS     -0.000
GOOG    -1.226
HD       0.000
INTC     0.000
JNJ     -0.000
JPM     -0.737
KO      -0.000
MA      -0.300
MRK      0.000
MSFT    -0.000
NVDA     0.000
PEP     -0.000
PFE      0.000
PG       0.000
T        0.737
UNH      0.300
V        1.226
VZ       0.000
WFC      0.000
WMT      0.000
XOM     -0.000
dtype: float64
In [141]:
# Display the difference in Posterior and Prior weights 
Active_weight = np.round(wstar - w_eq/(1+tau), 3)*100

Active_weight.plot(kind='bar', title = "BL-implied Active Weight");
In [142]:
d_r =  {'BL': (bl_mu*100), 'Equilibrium': (pi*100)}
plotdata = pd.DataFrame(data=d_r, index=assets)

plotdata.plot(kind="bar", figsize=(16,8))
plt.title("Expected Returns");
In [143]:
d_w =  {'BL': (wstar*100), 'Equilibrium': (w_eq*100)}
plotdata = pd.DataFrame(data=d_w, index=assets)

plotdata.plot(kind="bar", figsize=(16,8))
plt.title("Asset Weighting");

16) Create security weighting scheme for Black-Litterman portfolios.ΒΆ

In [144]:
# Create Security Weighting Scheme for Black-Litterman Portfolios
ind_blcap = pd.read_excel("mktcap_2008_2020.xlsx", sheet_name='BL_WTS', index_col=0, parse_dates=True)
ind_blcap =ind_blcap.loc[Start:End]
ind_blcap.index = pd.to_datetime(ind_blcap.index, format="%Y%m").to_period('M')
total_blcap = ind_blcap.sum(axis="columns")
In [145]:
pd.set_option('display.max_rows', None)
ind_blweight = ind_blcap.divide(total_blcap, axis="rows")
ind_blweight = ind_blweight.iloc[0:]
ind_blweight.tail()
Out[145]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2020-02 0.115823 0.014922 0.643962 0.020452 -0.523426 0.054925 0.435096 0.018883 0.457777 0.027708 ... 0.018883 0.021132 0.031373 0.026015 0.02683 -0.375503 0.024598 0.021763 0.03411 0.028136
2020-03 0.115823 0.014922 0.643962 0.020452 -0.523426 0.054925 0.435096 0.018883 0.457777 0.027708 ... 0.018883 0.021132 0.031373 0.026015 0.02683 -0.375503 0.024598 0.021763 0.03411 0.028136
2020-04 0.115823 0.014922 0.643962 0.020452 -0.523426 0.054925 0.435096 0.018883 0.457777 0.027708 ... 0.018883 0.021132 0.031373 0.026015 0.02683 -0.375503 0.024598 0.021763 0.03411 0.028136
2020-05 0.115823 0.014922 0.643962 0.020452 -0.523426 0.054925 0.435096 0.018883 0.457777 0.027708 ... 0.018883 0.021132 0.031373 0.026015 0.02683 -0.375503 0.024598 0.021763 0.03411 0.028136
2020-06 0.115823 0.014922 0.643962 0.020452 -0.523426 0.054925 0.435096 0.018883 0.457777 0.027708 ... 0.018883 0.021132 0.031373 0.026015 0.02683 -0.375503 0.024598 0.021763 0.03411 0.028136

5 rows Γ— 30 columns

In [ ]:
 
In [146]:
ind_return.tail()
Out[146]:
AAPL ADBE AMZN BA BAC BRK-A CMCSA CSCO CVX DIS ... PEP PFE PG T UNH V VZ WFC WMT XOM
Date
2020-02 0.027668 0.070478 0.055948 -0.051962 -0.074914 -0.021624 -0.055288 -0.039033 -0.124763 -0.046424 ... 0.049257 -0.031855 0.019798 -0.036163 -0.063180 0.050701 -0.039245 -0.123348 -0.039263 -0.143442
2020-03 -0.029614 0.006369 -0.025072 -0.079142 -0.109191 -0.030938 -0.003282 -0.115196 -0.080552 -0.151005 ... -0.034594 -0.070114 -0.044361 0.005953 -0.003321 -0.040842 -0.012576 -0.093572 0.014089 -0.100058
2020-04 -0.193770 -0.163956 -0.023670 -0.548173 -0.322569 -0.194915 -0.232562 -0.068982 -0.290196 -0.208868 ... -0.135648 -0.089738 -0.085564 -0.245563 -0.127282 -0.203920 -0.076762 -0.371274 -0.010657 -0.303451
2020-05 0.199910 0.141529 0.198323 0.020428 0.167424 0.048708 0.140654 0.077693 0.304551 0.111462 ... 0.101761 0.185513 0.075634 0.084705 0.198846 0.146692 0.085434 0.038392 0.076924 0.149481
2020-06 0.116412 0.133318 0.080926 0.135113 0.066294 0.005931 0.086533 0.131477 0.052686 0.125782 ... 0.021900 -0.048528 0.003681 0.034450 0.075287 0.108820 -0.018476 0.001828 0.012897 0.093586

5 rows Γ— 30 columns

In [147]:
total_bl_return = (ind_blweight * ind_return).sum(axis="columns")
total_bl_return.tail()
Out[147]:
Date
2020-02   -0.003475
2020-03    0.023346
2020-04   -0.020194
2020-05    0.240182
2020-06    0.068084
Freq: M, dtype: float64
In [148]:
total_bl_index = drawdown(total_bl_return).Wealth
total_bl_index.plot(title="BL Weighted Index");

17) Generate strategy backtest returns applying security weighting schemes.ΒΆ

In [149]:
def backtest_ws(r, estimation_window=60, weighting=weight_ew, verbose=False, **kwargs):
    """
    Backtests a given weighting scheme, given some parameters.
    r : asset returns series
    estimation_window: the lookback period to use to estimate parameters
    weighting: the weighting scheme to use, must be a function that takes "r", and a variable number of keyword-value arguments
    """
    # No of periods in returns series
    n_periods = r.shape[0]
    # return windows
    windows = [(start, start+estimation_window) for start in range(n_periods-estimation_window)]
    weights = [weighting(r.iloc[win[0]:win[1]], **kwargs) for win in windows]
    # convert List of weights to DataFrame
    weights = pd.DataFrame(weights, index=r.iloc[estimation_window:].index, columns=r.columns)
    returns = (weights * r).sum(axis="columns",  min_count=1) #mincount is to generate NAs if all inputs are NAs
    return returns
In [150]:
def weight_ew(r, cap_weights=None, max_cw_mult=None, microcap_threshold=None, **kwargs):
    """
    Returns the weights of the EW portfolio based on the asset returns "r" as a DataFrame
    If supplied a set of capweights and a capweight tether, it is applied and reweighted 
    """
    n = len(r.columns)
    ew = pd.Series(1/n, index=r.columns)
    if cap_weights is not None:
        cw = cap_weights.loc[r.index[0]] # starting cap weight
        ## exclude microcaps
        if microcap_threshold is not None and microcap_threshold > 0:
            microcap = cw < microcap_threshold
            ew[microcap] = 0
            ew = ew/ew.sum()
        #limit weight to a multiple of capweight
        if max_cw_mult is not None and max_cw_mult > 0:
            ew = np.minimum(ew, cw*max_cw_mult)
            ew = ew/ew.sum() #reweight
    return ew

def weight_cw(r, cap_weights, **kwargs):
    """
    Returns the weights of the CW portfolio based on the time series of capweights
    """
    w = cap_weights.loc[r.index[11]]# Index number Must match Estimation Window!!!
    return w/w.sum()

def weight_gmv(r, cov_estimator=sample_cov, **kwargs):
    """
    Produces the weights of the GMV portfolio given a covariance matrix of the returns 
    """
    est_cov = cov_estimator(r, **kwargs)
    return gmv(est_cov)

def weight_erc(r, cov_estimator=sample_cov, **kwargs):
    """
    Produces the weights of the ERC portfolio given a covariance matrix of the returns 
    """
    est_cov = cov_estimator(r, **kwargs)
    return equal_risk_contributions(est_cov)
In [151]:
def backtest_ws(r, estimation_window=60, weighting=weight_ew, verbose=False, **kwargs):
    """
    Backtests a given weighting scheme, given some parameters.
    r : asset returns series
    estimation_window: the lookback period to use to estimate parameters
    weighting: the weighting scheme to use, must be a function that takes "r", and a variable number of keyword-value arguments
    """
    # No of periods in returns series
    n_periods = r.shape[0]
    # return windows
    windows = [(start, start+estimation_window) for start in range(n_periods-estimation_window)]
    weights = [weighting(r.iloc[win[0]:win[1]], **kwargs) for win in windows]
    # convert List of weights to DataFrame
    weights = pd.DataFrame(weights, index=r.iloc[estimation_window:].index, columns=r.columns)
    returns = (weights * r).sum(axis="columns",  min_count=1) #mincount is to generate NAs if all inputs are NAs
    return returns


def gmv(cov):
    """
    Returns the weights of the Global Minimum Volatility portfolio
    given a covariance matrix
    """
    n = cov.shape[0]
    return msr(0, np.repeat(1, n), cov)

def weight_gmv(r, cov_estimator=sample_cov, **kwargs):
    """
    Produces the weights of the GMV portfolio given a covariance matrix of the returns 
    """
    est_cov = cov_estimator(r, **kwargs)
    return gmv(est_cov)

def weight_msr(r, cov_estimator=sample_cov, **kwargs):
    """
    Produces the weights of the MSR portfolio given a ret series and covariance matrix structure 
    """
    est_cov = cov_estimator(r, **kwargs)
    exp_ret = annualize_rets(r, 12,**kwargs)
    return msr(0,exp_ret, est_cov)
In [152]:
# Specify Estimation Window
estimation_window=12
In [153]:
# Equal-Weighted Returns
ewr = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_ew)
# Cap-Weighted Returns
cwr = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_cw, cap_weights=ind_capweight)
In [154]:
# BL Returns
blr = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_cw, cap_weights=ind_blweight)
In [155]:
# MSR Returns (sample cov)
MSRr_sample = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_msr, cov_estimator=sample_cov)
# MSR Returns (shrink cov)
MSRr_shrink = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_msr, cov_estimator=shrinkage_cov)
In [156]:
# GMV Returns (sample cov)
GMVr_sample = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_gmv, cov_estimator=sample_cov)
# GMV Returns (shrink cov)
GMVr_shrink = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_gmv, cov_estimator=shrinkage_cov)
In [157]:
# ERC Returns (sample cov)
ERCr_sample = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_erc, cov_estimator=sample_cov)
# ERC Returns (shrink cov)
ERCr_shrink = backtest_ws(ind_return, estimation_window=estimation_window, weighting=weight_erc, cov_estimator=shrinkage_cov)
In [158]:
# Collect Sample Backtest Returns in DataFrame
btr_outsample = pd.DataFrame({
                    "Eq. Weighted": ewr['2017-07':], 
                    "Cap Weighted": cwr['2017-07':], 
                    "Max SR-Sample Cov": MSRr_sample['2017-07':], 
                    "Max SR-Shrunk Cov": MSRr_shrink['2017-07':],
                    "Min Var Sample Cov": GMVr_sample['2017-07':], 
                    "Min Var Shrunk Cov": GMVr_shrink['2017-07':], 
                    "Risk Parity": ERCr_sample['2017-07':],
                    "Black Litterman": total_bl_return['2017-07':]
                    })
In [159]:
# View DataFrame
btr_outsample
Out[159]:
Eq. Weighted Cap Weighted Max SR-Sample Cov Max SR-Shrunk Cov Min Var Sample Cov Min Var Shrunk Cov Risk Parity Black Litterman
Date
2017-07 -0.003602 -0.009813 0.003818 -0.001541 -0.006943 -0.012649 -0.008416 0.012639
2017-08 0.041464 0.035737 0.071621 0.107293 0.047118 0.040159 0.041887 0.018240
2017-09 0.004507 0.008928 0.030657 0.028713 0.017894 -0.000830 0.004375 0.001310
2017-10 0.023165 0.015451 -0.006443 0.002202 -0.007048 0.006142 0.014643 0.147167
2017-11 0.038381 0.045365 0.103741 0.081193 0.077864 0.023190 0.046758 0.092607
2017-12 0.035770 0.030756 0.044291 0.045311 0.041129 0.040243 0.037755 0.058529
2018-01 0.030436 0.027470 0.011958 0.013966 0.006955 0.004220 0.025205 0.013655
2018-02 0.065244 0.067925 0.098169 0.111665 0.053453 0.037539 0.059681 0.007793
2018-03 -0.054892 -0.045016 -0.040414 -0.047149 -0.092310 -0.085965 -0.061449 -0.043629
2018-04 -0.033555 -0.040109 -0.043295 -0.038444 -0.031703 -0.027289 -0.029166 0.022435
2018-05 0.034504 0.038284 0.036459 0.051654 0.031838 0.010320 0.031405 0.052618
2018-06 0.032047 0.038955 0.069661 0.080640 0.057733 0.035892 0.036896 -0.038365
2018-07 0.004666 0.006218 -0.023298 -0.024204 0.001094 0.010808 0.003957 0.025385
2018-08 0.045525 0.051397 0.017740 0.016968 0.044849 0.077381 0.048983 0.105498
2018-09 0.037542 0.050763 0.066866 0.079017 0.056767 0.050459 0.040969 0.040007
2018-10 0.016798 0.012671 0.034085 0.025704 0.014473 0.033053 0.018320 -0.065001
2018-11 -0.038923 -0.058341 -0.073484 -0.097280 0.021589 -0.016127 -0.030648 0.038472
2018-12 0.027377 0.019063 0.043320 0.031533 0.051955 0.045591 0.028522 0.032864
2019-01 -0.092838 -0.098839 -0.068855 -0.067991 -0.078542 -0.067330 -0.084193 -0.183988
2019-02 0.060070 0.063229 0.019728 0.012581 0.045256 0.035179 0.054814 0.123495
2019-03 0.039658 0.036999 0.052911 0.053945 0.049788 0.038002 0.039301 0.024473
2019-04 0.029765 0.035798 0.036082 0.033476 0.042547 0.036493 0.029227 0.049085
2019-05 0.020192 0.030505 -0.025030 -0.030634 0.016076 0.010821 0.019171 0.176977
2019-06 -0.055106 -0.067811 -0.006522 -0.008175 -0.033513 -0.002594 -0.037077 -0.149503
2019-07 0.083217 0.088208 0.064666 0.064430 0.058820 0.053727 0.070132 0.009826
2019-08 -0.003312 0.001774 0.034021 0.043109 0.003230 0.011622 -0.004006 0.015987
2019-09 -0.006926 -0.009179 0.029923 0.039062 0.038175 0.046540 0.008374 -0.068398
2019-10 0.016816 0.013433 0.002591 0.014673 0.011156 0.022260 0.014175 0.035992
2019-11 0.043191 0.046514 0.005511 0.006208 0.023845 0.015093 0.033405 0.061091
2019-12 0.019295 0.020596 -0.004126 -0.014245 0.013088 -0.002555 0.014578 0.056174
2020-01 0.046092 0.056119 0.006189 0.004493 0.011749 0.013793 0.034829 0.028006
2020-02 -0.008806 0.011992 -0.024866 0.012045 -0.021025 -0.012366 -0.017375 -0.003475
2020-03 -0.044536 -0.044414 -0.027726 -0.031914 -0.044528 -0.033350 -0.042147 0.023346
2020-04 -0.187816 -0.179236 -0.184575 -0.178614 -0.145892 -0.115261 -0.175488 -0.020194
2020-05 0.132380 0.152043 0.092382 0.089414 0.089461 0.080167 0.123629 0.240182
2020-06 0.068236 0.073608 0.020651 0.019046 0.014991 0.004447 0.053706 0.068084
In [160]:
# Compute Cumulative Return
cum_ret_outsample = (1+btr_outsample).cumprod()
cum_ret_outsample
Out[160]:
Eq. Weighted Cap Weighted Max SR-Sample Cov Max SR-Shrunk Cov Min Var Sample Cov Min Var Shrunk Cov Risk Parity Black Litterman
Date
2017-07 0.996398 0.990187 1.003818 0.998459 0.993057 0.987351 0.991584 1.012639
2017-08 1.037713 1.025574 1.075713 1.105586 1.039848 1.027002 1.033118 1.031109
2017-09 1.042390 1.034730 1.108691 1.137330 1.058455 1.026150 1.037638 1.032459
2017-10 1.066537 1.050718 1.101547 1.139835 1.050995 1.032453 1.052832 1.184404
2017-11 1.107471 1.098384 1.215823 1.232382 1.132829 1.056396 1.102061 1.294088
2017-12 1.147085 1.132166 1.269673 1.288222 1.179421 1.098909 1.143669 1.369830
2018-01 1.181997 1.163266 1.284856 1.306213 1.187624 1.103547 1.172495 1.388535
2018-02 1.259115 1.242281 1.410989 1.452071 1.251107 1.144973 1.242471 1.399356
2018-03 1.190000 1.186359 1.353966 1.383607 1.135617 1.046545 1.166123 1.338304
2018-04 1.150069 1.138775 1.295345 1.330416 1.099615 1.017986 1.132111 1.368329
2018-05 1.189752 1.182371 1.342573 1.399137 1.134625 1.028492 1.167665 1.440328
2018-06 1.227879 1.228430 1.436097 1.511964 1.200130 1.065406 1.210747 1.385069
2018-07 1.233609 1.236068 1.402639 1.475369 1.201443 1.076922 1.215538 1.420228
2018-08 1.289770 1.299599 1.427521 1.500403 1.255327 1.160255 1.275078 1.570059
2018-09 1.338190 1.365570 1.522974 1.618961 1.326588 1.218800 1.327316 1.632873
2018-10 1.360670 1.382873 1.574884 1.660575 1.345788 1.259084 1.351633 1.526735
2018-11 1.307708 1.302195 1.459155 1.499034 1.374842 1.238779 1.310208 1.585472
2018-12 1.343509 1.327018 1.522366 1.546303 1.446271 1.295255 1.347578 1.637576
2019-01 1.218781 1.195857 1.417543 1.441169 1.332678 1.208046 1.234121 1.336281
2019-02 1.291993 1.271471 1.445508 1.459300 1.392990 1.250544 1.301768 1.501305
2019-03 1.343231 1.318513 1.521992 1.538022 1.462345 1.298067 1.352929 1.538046
2019-04 1.383212 1.365714 1.576909 1.589509 1.524563 1.345437 1.392470 1.613542
2019-05 1.411141 1.407375 1.537439 1.540816 1.549072 1.359997 1.419166 1.899101
2019-06 1.333380 1.311940 1.527412 1.528220 1.497157 1.356469 1.366547 1.615180
2019-07 1.444340 1.427663 1.626184 1.626684 1.585220 1.429347 1.462385 1.631051
2019-08 1.439556 1.430195 1.681508 1.696809 1.590341 1.445959 1.456527 1.657126
2019-09 1.429586 1.417067 1.731823 1.763091 1.651051 1.513253 1.468723 1.543781
2019-10 1.453626 1.436103 1.736311 1.788961 1.669471 1.546939 1.489542 1.599345
2019-11 1.516409 1.502902 1.745880 1.800067 1.709279 1.570287 1.539300 1.697050
2019-12 1.545668 1.533855 1.738676 1.774425 1.731650 1.566276 1.561740 1.792380
2020-01 1.616912 1.619934 1.749437 1.782398 1.751995 1.587879 1.616134 1.842578
2020-02 1.602673 1.639361 1.705936 1.803866 1.715159 1.568243 1.588053 1.836175
2020-03 1.531297 1.566550 1.658638 1.746298 1.638787 1.515943 1.521122 1.879042
2020-04 1.243695 1.285768 1.352494 1.434385 1.399702 1.341214 1.254183 1.841097
2020-05 1.408336 1.481260 1.477440 1.562638 1.524921 1.448735 1.409236 2.283296
2020-06 1.504435 1.590293 1.507951 1.592400 1.547781 1.455178 1.484921 2.438752
In [161]:
# Plot Compunded Return
(1+btr_outsample).cumprod().plot(figsize=(16,12), title="Strategies Cumulative Return");

18) Generate risk-adjusted performance metrics for strategies.ΒΆ

In [164]:
def summary_stats(r, riskfree_rate=rf):
    """
    Return a DataFrame that contains aggregated summary stats for the returns in the columns of r
    For each column which are having numeric values, the user-defined function is applied
    """
    ann_r = r.aggregate(annualize_rets, periods_per_year=12)
    ann_vol = r.aggregate(annualize_vol, periods_per_year=12)
    ann_sr = r.aggregate(sharpe_ratio, riskfree_rate=riskfree_rate, periods_per_year=12)
    dd = r.aggregate(lambda r: drawdown(r).Drawdown.min())
    skew = r.aggregate(skewness)
    kurt = r.aggregate(kurtosis)
    ann_semi_dev = r.aggregate(semideviation) * math.sqrt(ann_factor)
    cf_gvar5 = r.aggregate(var_gaussian, modified=False)
    cf_var5 = r.aggregate(var_gaussian, modified=True)
    hist_var5 = r.aggregate(var_historic)
    hist_cvar5 = r.aggregate(cvar_historic)
    rovol = ann_r/ann_vol
    ann_sortino = ann_r/ann_semi_dev
    rovar_cvar = ann_r/hist_cvar5
    rocvar_cfvar = ann_r/cf_var5
    radd = ann_r/-dd
    return pd.DataFrame({
        "Annualized Return": ann_r,
        "Annualized Volatility": ann_vol,
        "Ann. Semi-Dev.": ann_semi_dev,
        "Skewness": skew,
        "Kurtosis": kurt,
        "Gaussian VaR (5%)": cf_gvar5,
        "Modified VaR (5%)": cf_var5,
        "Historic VaR (5%)": hist_var5,
        "Historic CVaR (5%)": hist_cvar5,
        "Max Drawdown": dd,
        "Sharpe Ratio": ann_sr,
        "Sortino Ratio": ann_sortino,
         })
In [165]:
# Display Results
Perf_summary_samp = summary_stats(btr_outsample.dropna())
Perf_summary_samp.style.set_precision(4).set_caption("Performance Summary").set_table_styles([{'selector': 'caption',
                                                                         'props': [('color', 'red'),
                                                                                   ('text-align', 'center'),
                                                                                   ('font-weight', 'bold'),
                                                                                   ('font-size', '22px')]}])
Out[165]:
Performance Summary
Annualized Return Annualized Volatility Ann. Semi-Dev. Skewness Kurtosis Gaussian VaR (5%) Modified VaR (5%) Historic VaR (5%) Historic CVaR (5%) Max Drawdown Sharpe Ratio Sortino Ratio
Eq. Weighted 0.1458 0.1905 0.1783 -1.3371 6.6521 0.0763 0.0911 0.0645 0.1403 -0.2308 0.7655 0.8178
Cap Weighted 0.1672 0.2000 0.1702 -0.9863 5.5790 0.0790 0.0910 0.0756 0.1390 -0.2157 0.8362 0.9824
Max SR-Sample Cov 0.1467 0.1912 0.1646 -1.1664 5.8743 0.0765 0.0900 0.0700 0.1290 -0.2269 0.7674 0.8916
Max SR-Shrunk Cov 0.1678 0.1997 0.1683 -0.9963 5.0489 0.0788 0.0915 0.0753 0.1379 -0.2048 0.8402 0.9965
Min Var Sample Cov 0.1567 0.1667 0.1504 -1.3334 5.1215 0.0647 0.0791 0.0820 0.1191 -0.2011 0.9400 1.0423
Min Var Shrunk Cov 0.1332 0.1412 0.1270 -1.1358 4.7386 0.0548 0.0654 0.0720 0.1006 -0.1553 0.9431 1.0490
Risk Parity 0.1409 0.1762 0.1661 -1.3985 6.8758 0.0701 0.0843 0.0671 0.1298 -0.2240 0.7995 0.8482
Black Litterman 0.3460 0.2721 0.2047 -0.0809 4.7004 0.0994 0.0985 0.0887 0.1667 -0.1871 1.2716 1.6908