Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and...

19
Day-in-the-life: return and risk calculations Copyright © The Spaulding Group, Inc. 2019 1

Transcript of Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and...

Page 1: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day-in-the-life: return and risk

calculations

Copyright © The Spaulding Group, Inc. 2019 1

Page 2: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk• Consider this project:

• We have daily returns for the S&P 500 and Russell 1000

• The daily returns are for the period starting 12/01/2016 ending 01/30/2020

• Lets use Python to find the following:

• Average return

• Standard deviation

• One year return

• Cumulative return

• Annualized return

• Tracking error

• Information ratio

Page 3: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk

Load the data

Organize the data

Analyze the data

Page 4: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskLoad the Data Date S&P 500 Russell 1000

12/1/2016 4181.149902 1216.06005912/2/2016 4182.810059 1216.54003912/5/2016 4207.569824 1224.189941…....... …....... ….......…....... …....... ….......…....... …....... ….......1/28/2020 6652.299805 1811.6199951/29/2020 6646.689941 1810.1500241/30/2020 6668.52002 1816

Data sources include:

• SQL server

• API

• HTML table

• Flat file – “returns.csv”

Daily returns for the S&P 500 and Russell 1000 for the period starting December 1st, 2016

through January 30th, 2020.

Page 5: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk1.# lets allow this script to gain access to the modules and attributes in Pandas2.# lets assign the modules and attributes in Pandas to the variable pd3.import pandas as pd4.5.# lets convert the file "returns.csv" to a Pandas dataframe6.df = pd.read_csv('returns.csv')7.8.# lets assign the datetime date type to the values in column "Date"9.df['Date'] = pd.to_datetime(df['Date'], errors='coerce')10.11.# lets set column "Date" as the dataframe's index12.df.set_index('Date', inplace=True)

Page 6: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskLoad the Data – final result

Page 7: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskOrganize the data

We want to:

• Convert from a daily frequency to a monthly frequency

• Calculate the month over month return for each index

• Calculate the cumulative return factors

• Calculate the excess return of S&P 500 relative to Russell 1000

Page 8: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk1.# this function returns the last value of a series2.def lastday(days):3. return days[-1:]4.5.# lets tell resample to use the lastday to return the last value in the month6.df = df.resample('M').apply(lastday)7.8.# lets calculate some values for our dataframe9.df['S&P 500 RoR'] = df['S&P 500'] / df['S&P 500'].shift(1) - 110.df['Russell 1000 RoR'] = df['Russell 1000'] / df['Russell 1000'].shift(1) - 111.12.# second create new columns to support future calculations13.df['S&P 500 UV'] = df['S&P 500 RoR'] + 114.df['Russell 1000 UV'] = df['Russell 1000 RoR'] + 115.16.# lets calculate the difference in the rates of returns of both indices17.df['EXCESS RETURN'] = df['S&P 500 RoR'] - df['Russell 1000 RoR']

Page 9: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskOrganize the data – final result

Page 10: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskAnalyze the data – Part One

We want to calculate:

• Average return

• Standard deviation

𝐴𝑣𝑒𝑟𝑎𝑔𝑒 =(𝑎1+ 𝑎2+ 𝑎3+ … .+𝑎𝑛)

𝑛

𝑆𝑡𝑎𝑛𝑑𝑎𝑟𝑑 𝐷𝑒𝑣𝑖𝑎𝑡𝑖𝑜𝑛 =Σ(𝑥 − ҧ𝑥)2

𝑛

Page 11: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk1.# remove the monthly return for 01/31/20202.df.drop(df.tail(1).index, inplace=True)3.4.# calculate monthly rate of return averages5.spy_avg = df['S&P 500 RoR'].mean()6.russ_avg = df['Russell 1000 RoR'].mean()7.8.# calculate monthly standard deviation (population)9.spy_std = df['S&P 500 RoR'].std(ddof=0)10.russ_std = df['Russell 1000 RoR'].std(ddof=0)11.12.# lets see what the values are13.print('spy avg return: ' + str(spy_avg * 100))14.print('russell avg return: ' + str(russ_avg * 100))15.print('spy standard deviation (population): ' + str(spy_std * 100))16.print('russell standard deviation (population): ' + str(russ_std * 100))

Page 12: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskAnalyze the data – Part One Result

Page 13: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskAnalyze the data – Part Two

We want to calculate:

• One year return

Page 14: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk1.# create a list of the years that we want an annual return for2.years = [2017, 2018, 2019]3.4.# go through each year in the list "years"5.# assign the year to the value y6.for y in years:7. # keep only the return values for the year8. # calculate the cumulative product for each month in the vear9. # keep only the last cumulative product10. r = (df.loc[df.index.year==y, 'S&P 500 UV'].cumprod()[-1:].values[0] - 1)11. # show the values12. print(str(y) + ' SPY return: ' + str(r * 100))13.14. r = (df.loc[df.index.year==y, 'Russell 1000 UV'].cumprod()[-1:].values[0] - 1)15. print(str(y) + ' Russell return: ' + str(r * 100))

Page 15: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk

Analyze the data – Part Two Result

Page 16: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and RiskAnalyze the data – Part Three

We want to calculate:

• Cumulative return

• Annualized return

• Tracking error

• Information ratio

𝑇𝑟𝑎𝑐𝑘𝑖𝑛𝑔 𝐸𝑟𝑟𝑜𝑟σ𝑖=1𝑛 𝑅𝑝 − 𝑅𝑏 2

𝑛

𝐼𝑛𝑓𝑜𝑟𝑚𝑎𝑡𝑖𝑜𝑛 𝑅𝑎𝑡𝑖𝑜 =(𝐴𝑣𝑔𝑅𝑒𝑡𝑝 − 𝐴𝑣𝑔𝑅𝑒𝑡𝑏)

𝑇𝑟𝑎𝑐𝑘𝑖𝑛𝑔 𝐸𝑟𝑟𝑜𝑟

𝐴𝑛𝑛𝑢𝑎𝑙𝑖𝑧𝑒𝑑 𝑅𝑎𝑡𝑒 𝑜𝑓 𝑅𝑒𝑡𝑢𝑟𝑛 = (𝐸𝑛𝑑𝑖𝑛𝑔 𝑉𝑎𝑙𝑢𝑒

𝐵𝑒𝑔𝑖𝑛𝑛𝑖𝑛𝑔 𝑉𝑎𝑙𝑢𝑒) ൗ1 𝑛−1

Page 17: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk1.# lets calculate the remaining values of interest2.cum_spy = (df['S&P 500 UV'].cumprod()[-1:].values[0]) - 13.cum_russ = (df['Russell 1000 UV'].cumprod()[-1:].values[0]) - 14.annualized_spy = ((1 + cum_spy)**(1/3) - 1)5.annualized_russ = ((1 + cum_russ)**(1/3) - 1)6.tracking_error = df['EXCESS RETURN'].std(ddof=0)7.information_ratio = (spy_avg - russ_avg) / tracking_error8.9.# lets show the values we just calculated10.print('3 year Cumulative SPY Return: ' + str(cum_spy * 100))11.print('3 year Cumulative Russell 1000 Return: ' + str(cum_russ * 100))12.print('3 year Annualized SPY Return: ' + str(annualized_spy * 100))13.print('3 year Annualized Russell 1000 Return: ' + str(annualized_russ * 100))14.print('Tracking Error: ' + str(tracking_error * 100))15.print('Information Ratio: ' + str(information_ratio))

Page 18: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Day in the Life – Return and Risk

Analyze the data – Part Three Result

Page 19: Day-in-the-life: return and risk calculations · 2020. 10. 20. · Day in the Life –Return and Risk Load the Data e 0 0 6 2 9 6 9 9 6 4 1. . .. . .. . . 0 5 5 0 1 4 0 2 1816 Data

Speaker contact Info

Vikram Gokhale

[email protected]

https://www.linkedin.com/in/vikramgokhale/

Jonnathan De Jesus, CFA

[email protected]

https://www.linkedin.com/in/jonnathandejesus/

https://memberstrust.com/