Sequence of return risk analysis for the S&P 500 Index from 1871 to 2020¶
Author:
Travel-Lars
Introduction¶
Statistical analysis of sequence of return risk for the S&P 500 index. Based on historical data in the period between year 1871 and 2020. The analysis is based on convolution of probability mass functions for each period (year) to give a resulting multi-period probability mas function (pmf). This is done for number of periods ranging from 1 to 15.
Assumptions:
- Each period is statistically independent (a stochastic variable).
- The logarithm of a normally distributed stochastic variable is approximated by a fitted normal distribution for simplicity (Could use Weibull distribution or logistic distribution, but little is gained qualitatively).
Note: Numerical convolution of pmf's is not neccessary for normal/gauss distribution as the analytical expression is straight forward, but this method is more generic and can be transferred to other more accurate distributions for ln(X), where X is a normally distributed stochastic variable representing returns of a financial instrument.
import pandas as pd
import matplotlib.pyplot as plt
import pickle
import os
import yaml
import numpy as np
from IPython.display import HTML, Image, Math, Latex
from scipy import signal, stats
from functools import reduce
from scipy.interpolate import interp1d
pd.options.display.max_columns = None
pd.options.display.max_rows = None
pd.options.display.max_colwidth = 50
plt.rcParams["figure.figsize"] = (12,8)
# pd.options.display.notebook_repr_html = True
# Using sp500 data from R. Schiller. Source: http://www.econ.yale.edu/~shiller/data.htm
df = pd.read_excel('ie_data.xls', sheet_name='Data', header=7)
df = df[['Date', 'P', 'D', 'CPI', 'Price', 'Dividend', 'Price.1']]\
.rename(columns={'Date':'Time', 'Price':'RP', 'Dividend':'RD', 'Price.1':'RTRP' })
'''
Time: year.month
P: Price,
D: Dividend
CPI: Consumer price index,
RP: real price (cpi adj. rel. to last date)
RD: real dividend (cpi adj. rel. to last date)
RTRP: Real total return price ((RP[n]+RD[n])/RP[n-1] )
'''
df = df.apply(lambda x: pd.to_numeric(x, errors = 'coerce')).dropna()
print(type(df.loc[df.index[-2], 'Time']))
df['Time'] = pd.to_datetime(df['Time'].astype(str), format='%Y.%m')
display("Head and tail of modified dataset")
display(df.head(), df.tail())
<class 'numpy.float64'>
'Head and tail of modified dataset'
Time | P | D | CPI | RP | RD | RTRP | |
---|---|---|---|---|---|---|---|
0 | 1871-01-01 | 4.44 | 0.26 | 12.464061 | 92.657383 | 5.425883 | 92.657383 |
1 | 1871-02-01 | 4.50 | 0.26 | 12.844641 | 91.127019 | 5.265117 | 91.565779 |
2 | 1871-03-01 | 4.61 | 0.26 | 13.034972 | 91.991449 | 5.188238 | 92.868805 |
3 | 1871-04-01 | 4.74 | 0.26 | 12.559226 | 98.168484 | 5.384769 | 99.557763 |
4 | 1871-05-01 | 4.86 | 0.26 | 12.273812 | 102.994361 | 5.509986 | 104.917601 |
Time | P | D | CPI | RP | RD | RTRP | |
---|---|---|---|---|---|---|---|
1795 | 2020-08-01 | 3391.710000 | 59.126667 | 259.9180 | 3394.212175 | 59.170286 | 2.131463e+06 |
1796 | 2020-09-01 | 3365.516667 | 58.850000 | 260.2800 | 3363.315271 | 58.811506 | 2.115138e+06 |
1797 | 2020-01-01 | 3418.701364 | 58.659615 | 260.3880 | 3415.048147 | 58.596932 | 2.150743e+06 |
1798 | 2020-11-01 | 3548.992500 | 58.469231 | 260.2290 | 3547.366173 | 58.442437 | 2.237142e+06 |
1799 | 2020-12-01 | 3695.310000 | 58.278846 | 260.1495 | 3694.745369 | 58.269941 | 2.333149e+06 |
# RTR: Real total return (i.e. including dividend and appreciation after CPI adjustment)
# RTR%: Real total return percent
df['RTR'] = df['RTRP'].divide(df['RTRP'].shift(1))
df['RTR%'] = (df['RTR']-1)*100
df.head()
df_m = df.copy() # store df with months
# plt.hist(df['RTR%'], bins=25, density=True, alpha=0.6, color='#1f77b4')
p = plt.hist(df['RTR'].dropna(), bins=100, density=True)
mu, std = stats.norm.fit(df['RTR'].dropna())
print(f'mu:{mu}',f'std:{std}')
# Plot the PDF.
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
pdf = stats.norm.pdf(x, mu, std)
plt.plot(x, pdf, 'k', linewidth=2)
title = f"Fit results: mu = {mu:.2f}, std = {std:.2f}"
display('Dataset Histogram - Monthly real total return')
plt.title(title)
plt.show()
display(df['RTR'].describe())
display(df['RTR%'].describe())
mu:1.006481997134708 std:0.0409835548366386
'Dataset Histogram - Monthly real total return'
count 1799.000000 mean 1.006482 std 0.040995 min 0.738121 25% 0.986561 50% 1.009414 75% 1.029351 max 1.524294 Name: RTR, dtype: float64
count 1799.000000 mean 0.648200 std 4.099495 min -26.187924 25% -1.343922 50% 0.941420 75% 2.935114 max 52.429354 Name: RTR%, dtype: float64
df = df_m.copy()
# Gouping by year
df.head()
df = df.groupby(df.Time.dt.year).mean().reset_index()
df['Time'] = pd.to_datetime(df['Time'].astype(str), format='%Y')
df['RTR'] = df['RTRP'].divide(df['RTRP'].shift(1))
df['RTR%'] = (df['RTR']-1)*100
df.dropna(inplace=True)
display('Full dataset grouped by year')
display(df)
'Full dataset grouped by year'
Time | P | D | CPI | RP | RD | RTRP | RTR | RTR% | |
---|---|---|---|---|---|---|---|---|---|
1 | 1872-01-01 | 5.029167 | 0.281667 | 12.923959 | 101.216974 | 5.668623 | 1.096682e+02 | 1.084918 | 8.491771 |
2 | 1873-01-01 | 4.801667 | 0.316250 | 12.678156 | 98.397148 | 6.500842 | 1.131627e+02 | 1.031864 | 3.186386 |
3 | 1874-01-01 | 4.570000 | 0.330000 | 11.940774 | 99.578099 | 7.193391 | 1.230706e+02 | 1.087555 | 8.755485 |
4 | 1875-01-01 | 4.447500 | 0.313750 | 11.266841 | 102.671512 | 7.242468 | 1.362662e+02 | 1.107220 | 10.721991 |
5 | 1876-01-01 | 4.060833 | 0.300000 | 10.505661 | 100.534026 | 7.433366 | 1.429557e+02 | 1.049091 | 4.909103 |
6 | 1877-01-01 | 3.135833 | 0.240417 | 10.117150 | 80.786730 | 6.159364 | 1.247544e+02 | 0.872679 | -12.732125 |
7 | 1878-01-01 | 3.383333 | 0.184583 | 8.642385 | 102.053245 | 5.559691 | 1.677894e+02 | 1.344958 | 34.495776 |
8 | 1879-01-01 | 4.122500 | 0.190833 | 8.523458 | 125.536585 | 5.836174 | 2.170507e+02 | 1.293590 | 29.359006 |
9 | 1880-01-01 | 5.209167 | 0.232500 | 9.538343 | 142.159020 | 6.357266 | 2.568277e+02 | 1.183261 | 18.326134 |
10 | 1881-01-01 | 6.254167 | 0.292500 | 9.776215 | 166.636689 | 7.777194 | 3.146592e+02 | 1.225176 | 22.517619 |
11 | 1882-01-01 | 5.900000 | 0.320000 | 10.307447 | 148.929243 | 8.077578 | 2.964040e+02 | 0.941984 | -5.801556 |
12 | 1883-01-01 | 5.634167 | 0.325417 | 9.562134 | 153.327483 | 8.866197 | 3.224721e+02 | 1.087948 | 8.794761 |
13 | 1884-01-01 | 4.740833 | 0.319167 | 8.816821 | 139.696836 | 9.421693 | 3.125916e+02 | 0.969360 | -3.063978 |
14 | 1885-01-01 | 4.596667 | 0.272083 | 8.087382 | 147.967125 | 8.746078 | 3.544878e+02 | 1.134029 | 13.402857 |
15 | 1886-01-01 | 5.364167 | 0.229167 | 7.754368 | 180.006576 | 7.687897 | 4.524870e+02 | 1.276453 | 27.645308 |
16 | 1887-01-01 | 5.534167 | 0.236250 | 8.039808 | 179.076656 | 7.644041 | 4.686682e+02 | 1.035761 | 3.576062 |
17 | 1888-01-01 | 5.204167 | 0.239167 | 8.182529 | 165.449686 | 7.603551 | 4.534111e+02 | 0.967446 | -3.255421 |
18 | 1889-01-01 | 5.323333 | 0.224583 | 7.738511 | 178.994874 | 7.549806 | 5.125387e+02 | 1.130406 | 13.040605 |
19 | 1890-01-01 | 5.269167 | 0.220000 | 7.794014 | 176.038461 | 7.345936 | 5.248016e+02 | 1.023926 | 2.392589 |
20 | 1891-01-01 | 5.028333 | 0.220000 | 7.770226 | 168.540943 | 7.368635 | 5.256750e+02 | 1.001664 | 0.166416 |
21 | 1892-01-01 | 5.550000 | 0.230833 | 7.270711 | 198.675195 | 8.259961 | 6.455672e+02 | 1.228073 | 22.807294 |
22 | 1893-01-01 | 4.775000 | 0.245417 | 7.445146 | 166.411280 | 8.595336 | 5.659383e+02 | 0.876653 | -12.334719 |
23 | 1894-01-01 | 4.386667 | 0.228333 | 6.660196 | 171.363818 | 8.918769 | 6.154875e+02 | 1.087552 | 8.755222 |
24 | 1895-01-01 | 4.525000 | 0.199167 | 6.802913 | 172.935849 | 7.621585 | 6.517070e+02 | 1.058847 | 5.884699 |
25 | 1896-01-01 | 4.233333 | 0.184583 | 6.461975 | 170.394823 | 7.433826 | 6.700273e+02 | 1.028111 | 2.811119 |
26 | 1897-01-01 | 4.450833 | 0.180000 | 6.493690 | 178.143763 | 7.214459 | 7.315825e+02 | 1.091870 | 9.186971 |
27 | 1898-01-01 | 5.052500 | 0.190833 | 6.747412 | 194.934149 | 7.361178 | 8.321073e+02 | 1.137407 | 13.740730 |
28 | 1899-01-01 | 6.288333 | 0.205417 | 7.286570 | 225.001009 | 7.345795 | 9.932979e+02 | 1.193714 | 19.371379 |
29 | 1900-01-01 | 6.147500 | 0.258750 | 7.809870 | 204.814018 | 8.631727 | 9.388499e+02 | 0.945185 | -5.481538 |
30 | 1901-01-01 | 7.842500 | 0.310833 | 7.690938 | 265.330948 | 10.513668 | 1.268147e+03 | 1.350746 | 35.074557 |
31 | 1902-01-01 | 8.416667 | 0.325417 | 8.182521 | 267.809226 | 10.352602 | 1.330267e+03 | 1.048984 | 4.898441 |
32 | 1903-01-01 | 7.211667 | 0.340833 | 8.285602 | 226.042564 | 10.708586 | 1.169880e+03 | 0.879432 | -12.056764 |
33 | 1904-01-01 | 7.049167 | 0.328333 | 8.277667 | 221.397741 | 10.321087 | 1.207730e+03 | 1.032354 | 3.235391 |
34 | 1905-01-01 | 8.985833 | 0.320833 | 8.356963 | 279.700823 | 9.987176 | 1.586164e+03 | 1.313343 | 31.334294 |
35 | 1906-01-01 | 9.621667 | 0.367917 | 8.571018 | 292.025712 | 11.161361 | 1.716784e+03 | 1.082350 | 8.235008 |
36 | 1907-01-01 | 7.840000 | 0.421667 | 9.070534 | 224.984072 | 12.095361 | 1.381411e+03 | 0.804650 | -19.534957 |
37 | 1908-01-01 | 7.775833 | 0.418333 | 8.737544 | 231.209657 | 12.461483 | 1.510317e+03 | 1.093315 | 9.331476 |
38 | 1909-01-01 | 9.712500 | 0.421667 | 9.435274 | 267.603786 | 11.627576 | 1.829931e+03 | 1.211620 | 21.162039 |
39 | 1910-01-01 | 9.351667 | 0.456250 | 9.768285 | 249.119863 | 12.166983 | 1.782009e+03 | 0.973812 | -2.618811 |
40 | 1911-01-01 | 9.235000 | 0.470000 | 9.007118 | 266.941347 | 13.578440 | 2.007641e+03 | 1.126617 | 12.661694 |
41 | 1912-01-01 | 9.535000 | 0.475417 | 9.601766 | 258.286734 | 12.884063 | 2.044321e+03 | 1.018270 | 1.826994 |
42 | 1913-01-01 | 8.507500 | 0.480000 | 9.883333 | 223.999507 | 12.634331 | 1.867194e+03 | 0.913357 | -8.664334 |
43 | 1914-01-01 | 7.945000 | 0.447500 | 10.016667 | 206.439314 | 11.627052 | 1.821460e+03 | 0.975507 | -2.449328 |
44 | 1915-01-01 | 8.305000 | 0.425417 | 10.108333 | 213.562025 | 10.947579 | 1.993990e+03 | 1.094721 | 9.472073 |
45 | 1916-01-01 | 9.466667 | 0.500417 | 10.883333 | 226.284612 | 11.944036 | 2.219424e+03 | 1.113057 | 11.305668 |
46 | 1917-01-01 | 8.495000 | 0.630417 | 12.825000 | 173.444467 | 12.780329 | 1.804974e+03 | 0.813262 | -18.673751 |
47 | 1918-01-01 | 7.539167 | 0.625000 | 15.041667 | 130.573642 | 10.878908 | 1.482942e+03 | 0.821586 | -17.841365 |
48 | 1919-01-01 | 8.782500 | 0.548333 | 17.333333 | 131.815264 | 8.255354 | 1.608429e+03 | 1.084620 | 8.462030 |
49 | 1920-01-01 | 7.977500 | 0.519167 | 20.041667 | 103.606378 | 6.742577 | 1.343135e+03 | 0.835060 | -16.493975 |
50 | 1921-01-01 | 6.857500 | 0.482917 | 17.850000 | 99.974150 | 7.036973 | 1.391293e+03 | 1.035854 | 3.585425 |
51 | 1922-01-01 | 8.410833 | 0.487083 | 16.750000 | 130.646943 | 7.564437 | 1.938932e+03 | 1.393620 | 39.361955 |
52 | 1923-01-01 | 8.573333 | 0.520833 | 17.050000 | 130.879903 | 7.945767 | 2.054366e+03 | 1.059534 | 5.953448 |
53 | 1924-01-01 | 9.045833 | 0.540833 | 17.125000 | 137.375588 | 8.214910 | 2.297172e+03 | 1.118190 | 11.819045 |
54 | 1925-01-01 | 11.150000 | 0.577083 | 17.541667 | 165.224876 | 8.556017 | 2.920020e+03 | 1.271137 | 27.113688 |
55 | 1926-01-01 | 12.586667 | 0.648750 | 17.700000 | 185.033278 | 9.536774 | 3.441383e+03 | 1.178548 | 17.854755 |
56 | 1927-01-01 | 15.343333 | 0.733333 | 17.358333 | 229.973351 | 10.989973 | 4.501182e+03 | 1.307957 | 30.795748 |
57 | 1928-01-01 | 19.953333 | 0.813333 | 17.158333 | 302.468434 | 12.329846 | 6.185195e+03 | 1.374127 | 37.412676 |
58 | 1929-01-01 | 26.018333 | 0.915000 | 17.158333 | 394.340964 | 13.868753 | 8.355748e+03 | 1.350927 | 35.092720 |
59 | 1930-01-01 | 21.026667 | 0.975417 | 16.700000 | 326.908019 | 15.197761 | 7.206573e+03 | 0.862469 | -13.753114 |
60 | 1931-01-01 | 13.659167 | 0.893333 | 15.208333 | 232.660984 | 15.268963 | 5.419954e+03 | 0.752085 | -24.791515 |
61 | 1932-01-01 | 6.928333 | 0.646667 | 13.641667 | 132.037109 | 12.293222 | 3.373293e+03 | 0.622384 | -37.761602 |
62 | 1933-01-01 | 8.958333 | 0.467500 | 12.933333 | 179.733325 | 9.411618 | 4.955213e+03 | 1.468954 | 46.895435 |
63 | 1934-01-01 | 9.844167 | 0.445417 | 13.383333 | 191.436883 | 8.657013 | 5.505938e+03 | 1.111140 | 11.114049 |
64 | 1935-01-01 | 10.599167 | 0.448333 | 13.725000 | 200.830269 | 8.496476 | 6.068605e+03 | 1.102193 | 10.219272 |
65 | 1936-01-01 | 15.468333 | 0.574167 | 13.866667 | 290.014493 | 10.760603 | 9.089645e+03 | 1.497815 | 49.781463 |
66 | 1937-01-01 | 15.405833 | 0.783333 | 14.383333 | 278.972645 | 14.163804 | 9.102045e+03 | 1.001364 | 0.136425 |
67 | 1938-01-01 | 11.488333 | 0.696667 | 14.091667 | 212.127787 | 12.853317 | 7.403036e+03 | 0.813338 | -18.666234 |
68 | 1939-01-01 | 12.061667 | 0.548333 | 13.908333 | 225.506013 | 10.252941 | 8.255160e+03 | 1.115105 | 11.510462 |
69 | 1940-01-01 | 11.020833 | 0.650833 | 14.008333 | 204.674211 | 12.084455 | 7.885960e+03 | 0.955276 | -4.472357 |
70 | 1941-01-01 | 9.824167 | 0.691667 | 14.725000 | 173.855373 | 12.224816 | 7.153102e+03 | 0.907068 | -9.293194 |
71 | 1942-01-01 | 8.673333 | 0.650000 | 16.333333 | 138.087813 | 10.369496 | 6.138369e+03 | 0.858141 | -14.185919 |
72 | 1943-01-01 | 11.504167 | 0.595833 | 17.308333 | 172.813890 | 8.954948 | 8.163021e+03 | 1.329836 | 32.983551 |
73 | 1944-01-01 | 12.468333 | 0.630000 | 17.591667 | 184.315957 | 9.314680 | 9.162591e+03 | 1.122451 | 12.245097 |
74 | 1945-01-01 | 15.155833 | 0.653333 | 17.991667 | 219.007283 | 9.445490 | 1.141729e+04 | 1.246077 | 24.607682 |
75 | 1946-01-01 | 17.080833 | 0.685833 | 19.516667 | 229.654944 | 9.167396 | 1.242928e+04 | 1.088636 | 8.863609 |
76 | 1947-01-01 | 15.165833 | 0.766667 | 22.325000 | 176.829317 | 8.926640 | 1.003556e+04 | 0.807413 | -19.258655 |
77 | 1948-01-01 | 15.532500 | 0.867500 | 24.041667 | 167.988142 | 9.385870 | 1.006911e+04 | 1.003343 | 0.334253 |
78 | 1949-01-01 | 15.230000 | 1.027500 | 23.808333 | 166.408245 | 11.227579 | 1.061500e+04 | 1.054214 | 5.421415 |
79 | 1950-01-01 | 18.400000 | 1.265000 | 24.066667 | 198.752393 | 13.654466 | 1.356705e+04 | 1.278102 | 27.810230 |
80 | 1951-01-01 | 22.335000 | 1.507500 | 25.958333 | 223.762985 | 15.110170 | 1.636617e+04 | 1.206317 | 20.631742 |
81 | 1952-01-01 | 24.497500 | 1.432500 | 26.550000 | 239.975878 | 14.034372 | 1.867301e+04 | 1.140952 | 14.095178 |
82 | 1953-01-01 | 24.731667 | 1.421667 | 26.766667 | 240.379682 | 13.815260 | 1.978655e+04 | 1.059633 | 5.963333 |
83 | 1954-01-01 | 29.689167 | 1.475000 | 26.850000 | 287.665627 | 14.289688 | 2.506602e+04 | 1.266822 | 26.682155 |
84 | 1955-01-01 | 40.493333 | 1.589167 | 26.775000 | 393.295152 | 15.437477 | 3.578282e+04 | 1.427543 | 42.754281 |
85 | 1956-01-01 | 46.623333 | 1.769167 | 27.183333 | 446.138629 | 16.927219 | 4.211574e+04 | 1.176982 | 17.698203 |
86 | 1957-01-01 | 44.380000 | 1.748333 | 28.091667 | 411.034026 | 16.188529 | 4.030258e+04 | 0.956948 | -4.305187 |
87 | 1958-01-01 | 46.238333 | 1.748333 | 28.858333 | 416.663685 | 15.759224 | 4.259236e+04 | 1.056815 | 5.681486 |
88 | 1959-01-01 | 57.379167 | 1.793333 | 29.150000 | 511.981600 | 16.001580 | 5.406317e+04 | 1.269316 | 26.931611 |
89 | 1960-01-01 | 55.850000 | 1.937500 | 29.575000 | 491.228037 | 17.039812 | 5.359774e+04 | 0.991391 | -0.860910 |
90 | 1961-01-01 | 66.272500 | 1.959167 | 29.891667 | 576.629816 | 17.047825 | 6.501486e+04 | 1.213015 | 21.301503 |
91 | 1962-01-01 | 62.382500 | 2.068333 | 30.250000 | 536.568158 | 17.784204 | 6.231782e+04 | 0.958517 | -4.148341 |
92 | 1963-01-01 | 69.865000 | 2.197500 | 30.625000 | 593.288997 | 18.662885 | 7.130197e+04 | 1.144167 | 14.416656 |
93 | 1964-01-01 | 81.368333 | 2.394167 | 31.016667 | 682.297452 | 20.076212 | 8.450628e+04 | 1.185189 | 18.518857 |
94 | 1965-01-01 | 88.170000 | 2.616667 | 31.508333 | 727.828231 | 21.598968 | 9.282619e+04 | 1.098453 | 9.845317 |
95 | 1966-01-01 | 85.256667 | 2.830000 | 32.458333 | 683.741663 | 22.677168 | 8.987824e+04 | 0.968242 | -3.175773 |
96 | 1967-01-01 | 91.928333 | 2.905833 | 33.358333 | 716.655329 | 22.659407 | 9.748289e+04 | 1.084611 | 8.461061 |
97 | 1968-01-01 | 98.694167 | 2.997500 | 34.783333 | 737.696629 | 22.414843 | 1.035126e+05 | 1.061854 | 6.185365 |
98 | 1969-01-01 | 97.840000 | 3.127500 | 36.683333 | 694.356791 | 22.179643 | 1.003819e+05 | 0.969756 | -3.024413 |
99 | 1970-01-01 | 83.220000 | 3.171667 | 38.825000 | 557.783337 | 21.254096 | 8.357905e+04 | 0.832611 | -16.738934 |
100 | 1971-01-01 | 98.283333 | 3.098333 | 40.491667 | 631.433357 | 19.906345 | 9.797109e+04 | 1.172197 | 17.219667 |
101 | 1972-01-01 | 109.208333 | 3.085833 | 41.816667 | 679.165057 | 19.195377 | 1.086055e+05 | 1.108546 | 10.854611 |
102 | 1973-01-01 | 107.423333 | 3.240833 | 44.400000 | 630.499320 | 18.988311 | 1.036613e+05 | 0.954475 | -4.552456 |
103 | 1974-01-01 | 82.552500 | 3.514167 | 49.308333 | 437.875061 | 18.546485 | 7.453522e+04 | 0.719027 | -28.097317 |
104 | 1975-01-01 | 86.155833 | 3.685833 | 53.816667 | 416.242067 | 17.820291 | 7.432172e+04 | 0.997136 | -0.286448 |
105 | 1976-01-01 | 102.021667 | 3.806667 | 56.908333 | 466.315845 | 17.395446 | 8.656677e+04 | 1.164757 | 16.475740 |
106 | 1977-01-01 | 98.210000 | 4.378333 | 60.608333 | 421.837974 | 18.782673 | 8.149951e+04 | 0.941464 | -5.853586 |
107 | 1978-01-01 | 96.020000 | 4.916667 | 65.233333 | 382.763642 | 19.606019 | 7.773994e+04 | 0.953870 | -4.612993 |
108 | 1979-01-01 | 103.022500 | 5.376667 | 72.575000 | 369.367363 | 19.273221 | 7.895649e+04 | 1.015649 | 1.564888 |
109 | 1980-01-01 | 118.783333 | 5.950000 | 82.408333 | 374.438127 | 18.783683 | 8.438136e+04 | 1.068707 | 6.870717 |
110 | 1981-01-01 | 128.041667 | 6.415833 | 90.925000 | 366.840896 | 18.356080 | 8.665965e+04 | 1.027000 | 2.699991 |
111 | 1982-01-01 | 119.725000 | 6.792500 | 96.500000 | 322.582175 | 18.310360 | 8.067519e+04 | 0.930943 | -6.905707 |
112 | 1983-01-01 | 160.425000 | 6.966667 | 99.600000 | 418.799169 | 18.194695 | 1.099787e+05 | 1.363228 | 36.322807 |
113 | 1984-01-01 | 160.466667 | 7.313333 | 103.883333 | 401.779944 | 18.310481 | 1.102328e+05 | 1.002311 | 0.231060 |
114 | 1985-01-01 | 186.850000 | 7.754167 | 107.566667 | 451.682731 | 18.750056 | 1.295006e+05 | 1.174792 | 17.479188 |
115 | 1986-01-01 | 236.358333 | 8.125833 | 109.608333 | 560.871528 | 19.282726 | 1.669557e+05 | 1.289227 | 28.922702 |
116 | 1987-01-01 | 286.841667 | 8.538333 | 113.625000 | 656.794349 | 19.544224 | 2.016217e+05 | 1.207636 | 20.763587 |
117 | 1988-01-01 | 265.783333 | 9.267500 | 118.258333 | 584.509542 | 20.379222 | 1.855095e+05 | 0.920087 | -7.991289 |
118 | 1989-01-01 | 322.833333 | 10.404167 | 123.966667 | 676.894127 | 21.823455 | 2.223038e+05 | 1.198342 | 19.834219 |
119 | 1990-01-01 | 334.587500 | 11.642500 | 130.658333 | 666.617302 | 23.174462 | 2.260379e+05 | 1.016797 | 1.679712 |
120 | 1991-01-01 | 376.177500 | 12.178333 | 136.191667 | 718.309063 | 23.259953 | 2.522358e+05 | 1.115900 | 11.590033 |
121 | 1992-01-01 | 415.744167 | 12.339167 | 140.316667 | 770.670489 | 22.874615 | 2.789898e+05 | 1.106068 | 10.606753 |
122 | 1993-01-01 | 451.406667 | 12.508333 | 144.458333 | 812.725072 | 22.522890 | 3.027850e+05 | 1.085291 | 8.529059 |
123 | 1994-01-01 | 460.329167 | 12.863333 | 148.225000 | 807.871561 | 22.572260 | 3.093248e+05 | 1.021599 | 2.159892 |
124 | 1995-01-01 | 541.638333 | 13.427500 | 152.383333 | 924.068271 | 22.918773 | 3.637009e+05 | 1.175790 | 17.578962 |
125 | 1996-01-01 | 670.828333 | 14.390000 | 156.850000 | 1112.092964 | 23.860728 | 4.476192e+05 | 1.230734 | 23.073414 |
126 | 1997-01-01 | 872.673333 | 15.212500 | 160.516667 | 1413.660730 | 24.650455 | 5.802936e+05 | 1.296400 | 29.640025 |
127 | 1998-01-01 | 1084.310833 | 15.927500 | 163.008333 | 1730.012660 | 25.414075 | 7.212184e+05 | 1.242851 | 24.285083 |
128 | 1999-01-01 | 1326.060833 | 16.516667 | 166.575000 | 2070.300301 | 25.791273 | 8.747962e+05 | 1.212942 | 21.294217 |
129 | 2000-01-01 | 1427.007500 | 16.555000 | 172.200000 | 2155.810991 | 25.011138 | 9.217115e+05 | 1.053630 | 5.363003 |
130 | 2001-01-01 | 1192.078333 | 15.829167 | 177.066667 | 1751.609654 | 23.254626 | 7.580886e+05 | 0.822479 | -17.752080 |
131 | 2002-01-01 | 995.630000 | 15.882500 | 179.875000 | 1440.795714 | 22.967456 | 6.325391e+05 | 0.834387 | -16.561319 |
132 | 2003-01-01 | 963.689167 | 16.482500 | 183.958333 | 1362.329061 | 23.304578 | 6.091505e+05 | 0.963024 | -3.697577 |
133 | 2004-01-01 | 1130.547500 | 18.634167 | 188.883333 | 1556.966180 | 25.655876 | 7.074465e+05 | 1.161366 | 16.136568 |
134 | 2005-01-01 | 1207.060833 | 20.980833 | 195.291667 | 1607.722235 | 27.937281 | 7.430362e+05 | 1.050307 | 5.030732 |
135 | 2006-01-01 | 1310.670000 | 23.578333 | 201.591667 | 1691.239921 | 30.419747 | 7.957286e+05 | 1.070915 | 7.091500 |
136 | 2007-01-01 | 1476.633333 | 26.355000 | 207.342417 | 1852.301273 | 33.055559 | 8.871022e+05 | 1.114830 | 11.483008 |
137 | 2008-01-01 | 1220.888333 | 28.507500 | 215.302500 | 1474.353831 | 34.444111 | 7.197843e+05 | 0.811388 | -18.861180 |
138 | 2009-01-01 | 946.735833 | 25.288333 | 214.537000 | 1146.983675 | 30.678804 | 5.770453e+05 | 0.801692 | -19.830799 |
139 | 2010-01-01 | 1139.307500 | 22.228333 | 218.055500 | 1358.937679 | 26.514954 | 6.982031e+05 | 1.209962 | 20.996235 |
140 | 2011-01-01 | 1268.890000 | 24.536667 | 224.939167 | 1467.693579 | 28.366850 | 7.682912e+05 | 1.100384 | 10.038358 |
141 | 2012-01-01 | 1379.563333 | 28.725833 | 229.593917 | 1562.752505 | 32.538971 | 8.351916e+05 | 1.087077 | 8.707688 |
142 | 2013-01-01 | 1642.511667 | 33.380833 | 232.957083 | 1833.690353 | 37.268337 | 1.000846e+06 | 1.198343 | 19.834348 |
143 | 2014-01-01 | 1930.667500 | 37.514167 | 236.736167 | 2121.215738 | 41.216790 | 1.180691e+06 | 1.179693 | 17.969276 |
144 | 2015-01-01 | 2061.199167 | 41.783333 | 237.017000 | 2262.101831 | 45.851303 | 1.283796e+06 | 1.087325 | 8.732535 |
145 | 2016-01-01 | 2091.844167 | 44.575000 | 240.007167 | 2266.476775 | 48.306295 | 1.314227e+06 | 1.023705 | 2.370459 |
146 | 2017-01-01 | 2448.217500 | 47.405833 | 245.119583 | 2597.455370 | 50.301092 | 1.536871e+06 | 1.169410 | 16.941004 |
147 | 2018-01-01 | 2744.680000 | 51.368333 | 251.106833 | 2843.033672 | 53.205350 | 1.713580e+06 | 1.114980 | 11.497978 |
148 | 2019-01-01 | 2912.500987 | 56.245152 | 255.657417 | 2962.466603 | 57.219308 | 1.820881e+06 | 1.062618 | 6.261792 |
149 | 2020-01-01 | 3218.500956 | 59.094125 | 258.784125 | 3233.751586 | 59.400564 | 2.026169e+06 | 1.112741 | 11.274143 |
## Plotting ten year returns
display('Plotting 10 year trailing returns for each year')
s = pd.Series(df['RTRP'].shift(-10).divide(df['RTRP']).values, index=df.Time)\
.subtract(1).multiply(100).dropna()
ax = s.plot(figsize=(12,8), grid=True)
# xtick = pd.date_range( start=ts.index.min( ), end=ts.index.max( ), freq='W' )
# ax.set_xticks( xtick, minor=True )
ytick = np.linspace(s.min()*0.8,s.max()*1.2,40)
_ = ax.set_yticks(ytick, minor=True)
# ax.grid('on', which='minor', axis='x' )
# ax.grid('off', which='major', axis='x' )
'Plotting 10 year trailing returns for each year'
##RTR-percent norm distr
# plt.hist(df['RTR%'], bins=25, density=True, alpha=0.6, color='#1f77b4')
plt.hist(df['RTR%'].dropna(), bins=60, density=True)
mu, std = stats.norm.fit(df['RTR%'].dropna())
print(f'mu:{mu}',f'std:{std}')
# Plot the PDF.
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
pdf = stats.norm.pdf(x, mu, std)
plt.plot(x, pdf, 'k', linewidth=2)
title = f"Fit results: mu = {mu:.2f}, std = {std:.2f}"
display('Plotting histogram of real total returns percent for each year with fitted normal distribution')
plt.title(title)
plt.show()
df['RTR%'].describe()
mu:8.04282911117305 std:15.642863800785406
'Plotting histogram of real total returns percent for each year with fitted normal distribution'
count 149.000000 mean 8.042829 std 15.695622 min -37.761602 25% -2.449328 50% 8.707688 75% 17.854755 max 49.781463 Name: RTR%, dtype: float64
##RTR norm distr
# plt.hist(df['RTR%'], bins=25, density=True, alpha=0.6, color='#1f77b4')
p_h = plt.hist(df['RTR'].dropna(), bins=60, density=True)
mu, std = stats.norm.fit(df['RTR'].dropna())
print(f'mu:{mu}',f'std:{std}')
# Plot the PDF.
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 1000)
pdf = stats.norm.pdf(x, mu, std)
plt.plot(x, pdf, 'k', linewidth=2)
display('Plotting histogram of real total returns with fitted normal distribution')
title = f"Fit results: mu = {mu:.2f}, std = {std:.2f}"
plt.title(title)
plt.show()
display(df['RTR'].describe())
mu:1.0804282911117304 std:0.15642863800785406
'Plotting histogram of real total returns with fitted normal distribution'
count 149.000000 mean 1.080428 std 0.156956 min 0.622384 25% 0.975507 50% 1.087077 75% 1.178548 max 1.497815 Name: RTR, dtype: float64
Multiple year total returns as probability density fucntion (PDF) based on the normal distribution of single year total returns. Let Z be a stochastic variable defined by Z(n) = X^n where X is a stochastic variable with known distribution norm(mu,std) and n is the number of periods. To find the PDF of Z we take the logarithm of both sides. ln(Z(n)) = n*ln(X) = ln(X1) + ln(X2) +..+ ln(Xn) ln(X) To find the sum of ln(X)'s we need to find the convolution of the pdf's of ln(X). Formally: $$P(Z=z)=\sum _{k=-\infty }^{\infty }P(X=k)P(Y=z-k)$$
ln(evn) = ln(v1) + ln(v2) + ... + ln(vn) Ex ante, each of the variables on the right-hand side is unknown. Each will be drawn from a distribution (that of ln(v)) and each draw will, by assumption, be independent of every other draw.
Recall the central limit theorem, which holds that the sum of a set of independent random variables will have a distribution that will be closer and closer to normal, the greater the number of variables in the sum. For a sufficiently large value of n, ln(evn) will be normally distributed, or nearly so.
# Norm distr fit to log(x) values
# print(df['RTR'])
rtr_ln = np.log(df['RTR'])
# print(rtr_ln)
p = plt.hist(rtr_ln, bins=60, density=True)
mu, std = stats.norm.fit(rtr_ln)
print(f'mu:{mu}',f'std:{std}')
# # print(np.trapz(p_h[0], p_h[1]))
# # print(p_h)
# print(len(p_h[0]))
# print(len(p_h[1]))
# delta = p_h[1][1]-p_h[1][0]
# print(delta)
# print(f'sum:{np.trapz(p[0],dx=delta)}')
# Plot the PDF.
display('Histogram of ln(x) and fitted normal probability distribution (for simplicity)')
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 400)
delta = x[1]-x[0]
# x = np.arange(xmin, xmax, delta)
pdf = stats.norm.pdf(x, mu, std)
plt.plot(x, pdf, 'k', linewidth=2)
title = f"Fit results: mu = {mu:.2f}, std = {std:.2f}"
plt.title(title)
plt.show()
# print(pdf)
len(pdf)
print(f'sum:{np.trapz(pdf,dx=delta)}')
mu:0.06648122140397093 std:0.14934188764105333
'Histogram of ln(x) and fitted normal probability distribution (for simplicity)'
sum:0.9946308975353584
## Setting up convolution calc funcs
def multi_conv(*arrs, conv = lambda x,y: np.convolve(x, y, mode='same')):
return reduce(conv, arrs)
def convolute_list_of_pmfs(lst):
return multi_conv(*lst)
def create_pdf_x_params_from_norm_pdf_lnx_params(mu_x, std_x):
mu_y = np.exp(mu_x+(0.5*std_x**2))
v_y = np.exp(2*mu_x+std_x**2)*(np.exp(std_x**2)-1)
std_y = np.sqrt(v_y)
return mu_y, std_y
# def create_pdf_x_params_from_norm_pdf_lnx_params(mu_x, std_x):
# mu_y = np.log((mu_x**2)/np.sqrt(mu_x**2+std_x**2))
# std_y = np.sqrt(np.log(((std_x**2)/(mu_x**2))+1))
# v_y = std_y**2
# return mu_y, std_y
def mean_and_std_from_pmf(x, pmf):
mu = sum(np.multiply(x, pmf)) # expected value
var = sum(np.multiply(x**2, pmf))-mu**2 #variance
std = np.sqrt(var)
return mu, std
## Setting up convolution calc params
# mu_check = []
# for res in [1000, 20000, 50000, 100000, 150000, 200000]:
# print(res)
# x = np.linspace(-40, 40, res)
x = np.linspace(-20, 20, 10000) # for the convolution to work, need to have to be symmetric, large x vector and cover practial range as n->
# need high resolution to avoid border effects during convolution
delta = x[1]-x[0]
pdf = stats.norm.pdf(x, mu, std)
pmf = pdf*delta
print(sum(pmf))
print(sum(pdf)*delta)
print(len(pmf))
# plt.plot(x, pmf, 'k', linewidth=2)
# title = f"Fit results for pmf"
# plt.title(title)
print()
n=5
pmf_conv = convolute_list_of_pmfs(n*[pmf])
print(sum(pmf_conv))
plt.plot(x, pmf_conv, 'k', linewidth=2)
plt.xlim([-2, 15])
title = f"Convolution of {n} pdf(ln(x))'s with mu = {mu:.4f}, std = {std:.4f}"
plt.title(title)
# mu_, std_ = mean_and_std_from_pmf(x, pmf_conv)
# print(mu_, std_)
# mu_check.append(mu_)
# print(mu_check)
0.9999999999996151 0.9999999999996145 10000 0.9999999999980757
Text(0.5, 1.0, "Convolution of 5 pdf(ln(x))'s with mu = 0.0665, std = 0.1493")
mu_conv, std_conv = mean_and_std_from_pmf(x, pmf_conv)
# mu_test, std_test = create_pdf_x_params_from_norm_pdf_lnx_params(mu_conv, std_conv)
cdf_log_test = stats.lognorm.cdf(x, std_conv, scale=np.exp(mu_conv))
print(mu_conv, std_conv )
# print(mu_test, std_test )
pdf_log_test = stats.lognorm.pdf(x, std_conv, scale=np.exp(mu_conv))
pmf_log_test = pdf_log_test*delta
plt.plot(x, pdf_log_test, 'k', linewidth=2)
title = f"Fit results: mu = {mu:.2f}, std = {std:.2f}"
plt.title(title)
# stats.rv_continuous.cdf
cd = interp1d(cdf_log_test, x)(0.5)
print(cd)
# fig4, ax4 = plt.subplots()
plt.plot(x, cdf_log_test, linewidth=2, label=f'n: {n}')
plt.xlim([-2, 10])
0.34040690709920685 0.3339386126535441 1.4055201326759459
(-2.0, 10.0)
def create_all_pmfs_pdfs_from_periods_and_pmf_lnx(x, pmf, n):
d = {}
delta = x[1]-x[0]
d['pmfs_x'] = [convolute_list_of_pmfs(i*[pmf]) for i in range(1,n+1)]
d['pdfs_x'] = d['pmfs_x']/delta
d['pdfs_x_params'] = [mean_and_std_from_pmf(x, pmf) for pmf in d['pmfs_x']]
d['pdfs_y_params'] = [create_pdf_x_params_from_norm_pdf_lnx_params(mu_x, std_x) for (mu_x, std_x) in d['pdfs_x_params']] # not used
# d['pdf_lognorms'] = [stats.lognorm.pdf(x, std_y, loc=mu_y) for std_y,mu_y in d['pdfs_y_params']]
d['pdf_lognorms'] = [stats.lognorm.pdf(x, std_x, scale=np.exp(mu_x)) for mu_x,std_x, in d['pdfs_x_params']]
d['pmf_lognorms'] = [i*delta for i in d['pdf_lognorms']]
# d['cdf_lognorms'] = [stats.lognorm.cdf(x, std_y, loc=mu_y) for std_y,mu_y in d['pdfs_y_params']] # cumulative distr functions for real total returns
d['cdf_lognorms'] = [stats.lognorm.cdf(x, std_x, scale=np.exp(mu_x)) for mu_x,std_x, in d['pdfs_x_params']]
# d['geom_mean_RTR'] = []
return d
# Checking the sums
n = 15 # periods
d = create_all_pmfs_pdfs_from_periods_and_pmf_lnx(x, pmf, n)
## Checking sums etc
# print(d['pdfs_x_params'])
print([sum(x) for x in d['pmfs_x']])
print([sum(x) for x in d['pmf_lognorms']])
print(len(d['pdfs_x'][0]))
print(len(d['pmf_lognorms']))
print(d['pdfs_x_params'])
# cd = interp1d(d['cdf_lognorms'][4], x)(0.5)
# print(cd)
[0.9999999999996151, 0.999999999999232, 0.9999999999988464, 0.999999999998461, 0.9999999999980757, 0.9999999999976912, 0.9999999999973074, 0.9999999999969211, 0.9999999999965368, 0.9999999999961505, 0.9999999999957668, 0.9999999999953835, 0.9999999999949963, 0.9999999999946122, 0.9999999999942278] [0.9999999999996144, 0.9999999999996135, 0.9999999999996113, 0.9999999999996132, 0.9999999999996082, 0.9999999999988489, 0.9999999999074742, 0.9999999966860107, 0.9999999468297688, 0.9999995153210108, 0.9999970726632039, 0.9999870193028821, 0.9999546249290051, 0.9998684434556131, 0.9996716089041499] 10000 15 [(0.06648122140394527, 0.14934188764103035), (0.13496264282783968, 0.21120132293232838), (0.20344406425168168, 0.2586677370924898), (0.2719254856754708, 0.29868377528206747), (0.34040690709920685, 0.3339386126535441), (0.4088883285228915, 0.3658114219447424), (0.4773697499465226, 0.3951214950234223), (0.5458511713701005, 0.4224026458651896), (0.614332592793626, 0.4480256629238434), (0.6828140142170988, 0.4722605150156683), (0.7512954356405186, 0.4953110067901523), (0.8197768570638863, 0.5173354741868987), (0.8882582784872016, 0.5384598334667182), (0.9567396999104634, 0.5587861770498187), (1.025221121333671, 0.5783986437285568)]
print(d['pdfs_x_params'])
print('Checking last value for cumulative distribution')
print([x[-1] for x in d['cdf_lognorms']])
[(0.06648122140394527, 0.14934188764103035), (0.13496264282783968, 0.21120132293232838), (0.20344406425168168, 0.2586677370924898), (0.2719254856754708, 0.29868377528206747), (0.34040690709920685, 0.3339386126535441), (0.4088883285228915, 0.3658114219447424), (0.4773697499465226, 0.3951214950234223), (0.5458511713701005, 0.4224026458651896), (0.614332592793626, 0.4480256629238434), (0.6828140142170988, 0.4722605150156683), (0.7512954356405186, 0.4953110067901523), (0.8197768570638863, 0.5173354741868987), (0.8882582784872016, 0.5384598334667182), (0.9567396999104634, 0.5587861770498187), (1.025221121333671, 0.5783986437285568)] Checking last value for cumulative distribution [1.0, 1.0, 1.0, 1.0, 0.9999999999999991, 0.9999999999992338, 0.9999999999077037, 0.9999999966817138, 0.9999999467649179, 0.999999514798856, 0.9999970698634604, 0.9999870081995157, 0.9999545899913687, 0.9998683517724888, 0.9996714007933173]
## Plotting probability distributions
fig,ax = plt.subplots()
fig2, ax2 = plt.subplots()
fig5, ax5 = plt.subplots()
plot_nums = 14
for i in range(0,plot_nums-1,1):
ax.plot(x, d['pmfs_x'][i], linewidth=2, label=f'n: {i}')
ax.set_xlim([-2, 3])
ax2.plot(x, d['pmf_lognorms'][i], linewidth=2, label=f'n: {i}')
ax2.set_xlim([0, 8])
ax5.plot(x, d['cdf_lognorms'][i], linewidth=2, label=f'n: {i}')
ax5.set_xlim([0, 10])
# ax2.set_yscale('log')
fig.suptitle("pmf from convolution of n number of pdf(ln(x)) distributions")
fig2.suptitle("Resulting probability mass function\n for the SP500 real total return over n periods")
fig.legend(loc='right')
fig2.legend(loc='right')
fig5.legend(loc='right')
fig5.suptitle("Cumulative probability distribution \n for the SP500 real total return over n periods")
# Single plots example
plot_num = 0
fig3, ax3 = plt.subplots()
ax3.plot(x, d['pmf_lognorms'][plot_num], linewidth=2, label=f'n: {n}')
ax3.set_xlim([0, 20])
fig3.suptitle(f"Single plot of probability mass function for {plot_num} periods")
fig4, ax4 = plt.subplots()
ax4.plot(x, d['cdf_lognorms'][plot_num], linewidth=2, label=f'n: {n}')
ax4.set_xlim([0, 2])
fig4.suptitle(f"Single plot of cumulative probability distribution for {plot_num} periods")
Text(0.5, 0.98, 'Single plot of cumulative probability distribution for 0 periods')
# Check cumulative distribution
cd = interp1d(d['cdf_lognorms'][9], x)
print(cd(0.5))
print(cd(0.05))
1.979440941172524 0.9102949906270474
Summary Table¶
## DATAFRAME for norm(pdf(ln(x))) dataset
# params_log = [mean_and_std_from_pmf(x, d['pmf_lognorms'][n]) for i in range(1,n)]
df_res = pd.DataFrame(index = range(1,n+1))
df_res.index.name= 'year'
# display(df_res)
# print(n)
all_cd = [interp1d(d['cdf_lognorms'][i], x) for i in range(0,n)]
# df_res['ev_rtr'] = [np.exp(x[0]) for x in d['pdfs_x_params']]
df_res['ev_rtr'] = [x[0] for x in d['pdfs_y_params']]
df_res['ev_return%'] = df_res['ev_rtr'].subtract(1).multiply(100)
# s_ev = pd.Series([x[0] for x in d['pdfs_y_params']])
df_res['gmean_ev_rtr_pa'] = [x**(1/(i+1)) for i,x in enumerate(df_res['ev_rtr'].values)]
df_res['gmean_ev_rtr%_pa'] = df_res['gmean_ev_rtr_pa'].subtract(1).multiply(100)
df_res['ar_mean_rtr_pa'] = [((x-1)/(i+1))+1 for i,x in enumerate(df_res['ev_rtr'].values)]
# df_res['median_rtr'] = [interp1d(d['cdf_lognorms'][i], x)(0.5) for i in range(0,n)]
df_res['median_rtr'] = [all_cd[i](0.5) for i in range(0,n)]
df_res['median_rtr%'] = df_res['median_rtr'].subtract(1).multiply(100)
df_res['gmean_median_rtr'] = [x**(1/(i+1)) for i,x in enumerate(df_res['median_rtr'].values)]
df_res['5_conf_rtr'] = [all_cd[i](0.05) for i in range(0,n)]
df_res['95_conf_rtr'] = [all_cd[i](0.95) for i in range(0,n)]
df_res['5_conf_gain%'] = df_res['5_conf_rtr'].subtract(1).multiply(100)
df_res['95_conf_gain%'] = df_res['95_conf_rtr'].subtract(1).multiply(100)
df_res['5_conf_gmean_rtr_pa'] = [x**(1/(i+1)) for i,x in enumerate(df_res['5_conf_rtr'].values)]
df_res['95_conf_gmean_rtr_pa'] = [x**(1/(i+1)) for i,x in enumerate(df_res['95_conf_rtr'].values)]
df_res['5_conf_gmean%'] = df_res['5_conf_gmean_rtr_pa'].subtract(1).multiply(100)
df_res['95_conf_gmean%'] = df_res['95_conf_gmean_rtr_pa'].subtract(1).multiply(100)
#Finne x hvor cd(x)=1.04 (hvor sannsynlig det er å gå under 4% swr)?
display('Summary table of S&P 500 sequence of return risk analysis')
display('Including confidence intervals for real total returns and geometric means (annualized returns)')
display(df_res)
# display(pd.DataFrame(d['cdf_lognorms']))
'Summary table of S&P 500 sequence of return risk analysis'
'Including confidence intervals for real total returns and geometric means (annualized returns)'
ev_rtr | ev_return% | gmean_ev_rtr_pa | gmean_ev_rtr%_pa | ar_mean_rtr_pa | median_rtr | median_rtr% | gmean_median_rtr | 5_conf_rtr | 95_conf_rtr | 5_conf_gain% | 95_conf_gain% | 5_conf_gmean_rtr_pa | 95_conf_gmean_rtr_pa | 5_conf_gmean% | 95_conf_gmean% | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
year | ||||||||||||||||
1 | 1.080726 | 8.072566 | 1.080726 | 8.072566 | 1.080726 | 1.0687425484466184 | 6.874255 | 1.068743 | 0.8359446595273184 | 1.3663311151931927 | -16.405534 | 36.633112 | 0.835945 | 1.366331 | -16.405534 | 36.633112 |
2 | 1.170306 | 17.030646 | 1.081807 | 8.180703 | 1.085153 | 1.1444957051761664 | 14.449571 | 1.069811 | 0.8085991512099215 | 1.6199001057332936 | -19.140085 | 61.990011 | 0.899221 | 1.272753 | -10.077859 | 27.275296 |
3 | 1.267313 | 26.731256 | 1.082168 | 8.216773 | 1.089104 | 1.225617312810981 | 22.561731 | 1.070167 | 0.8008829228688485 | 1.8755808989875855 | -19.911708 | 87.55809 | 0.928659 | 1.233233 | -7.134085 | 23.323337 |
4 | 1.372359 | 37.235945 | 1.082348 | 8.234813 | 1.093090 | 1.3124906708418103 | 31.249067 | 1.070346 | 0.8030199941542211 | 2.145169914906644 | -19.698001 | 114.516991 | 0.946633 | 1.210223 | -5.336711 | 21.022306 |
5 | 1.486114 | 48.611362 | 1.082456 | 8.245638 | 1.097223 | 1.4055201326759459 | 40.552013 | 1.070453 | 0.8114892696278552 | 2.434368272514935 | -18.851073 | 143.436827 | 0.959084 | 1.194751 | -4.091620 | 19.475060 |
6 | 1.609297 | 60.929682 | 1.082529 | 8.252855 | 1.101549 | 1.5051446277525273 | 50.514463 | 1.070524 | 0.824624254972193 | 2.7472368805353073 | -17.537575 | 174.723688 | 0.968373 | 1.183448 | -3.162697 | 18.344847 |
7 | 1.742691 | 74.269061 | 1.082580 | 8.258011 | 1.106099 | 1.6118305155631831 | 61.183052 | 1.070575 | 0.8415148350807242 | 3.087271111170197 | -15.848516 | 208.727111 | 0.975651 | 1.174733 | -2.434890 | 17.473323 |
8 | 1.887141 | 88.714135 | 1.082619 | 8.261877 | 1.110893 | 1.7260770523749975 | 72.607705 | 1.070613 | 0.861618593823186 | 3.4578328954876 | -13.838141 | 245.78329 | 0.981554 | 1.167752 | -1.844558 | 16.775168 |
9 | 2.043566 | 104.356553 | 1.082649 | 8.264885 | 1.115952 | 1.8484236037934767 | 84.84236 | 1.070643 | 0.8846082283047615 | 3.862324743738213 | -11.539177 | 286.232474 | 0.986469 | 1.161998 | -1.353100 | 16.199811 |
10 | 2.212956 | 121.295563 | 1.082673 | 8.267291 | 1.121296 | 1.979440941172524 | 97.944094 | 1.070667 | 0.9102949906270474 | 4.304297391684142 | -8.970501 | 330.429739 | 0.990645 | 1.157152 | -0.935463 | 15.715151 |
11 | 2.396386 | 139.638639 | 1.082693 | 8.269260 | 1.126944 | 2.1197451235285514 | 111.974512 | 1.070686 | 0.9385484559794547 | 4.787507061785577 | -6.145154 | 378.750706 | 0.994251 | 1.152997 | -0.574894 | 15.299687 |
12 | 2.595022 | 159.502163 | 1.082709 | 8.270900 | 1.132918 | 2.2699934416817706 | 126.999344 | 1.070702 | 0.969313491644992 | 5.315984694867353 | -3.068651 | 431.598469 | 0.997406 | 1.149384 | -0.259390 | 14.938443 |
13 | 2.810122 | 181.012165 | 1.082723 | 8.272289 | 1.139240 | 2.430892472911008 | 143.089247 | 1.070716 | 1.0025722697488175 | 5.894065486208251 | 0.257227 | 489.406549 | 1.000198 | 1.146206 | 0.019763 | 14.620603 |
14 | 3.043051 | 204.305120 | 1.082735 | 8.273479 | 1.145932 | 2.603195975684832 | 160.319598 | 1.070728 | 1.0383339406280772 | 6.526437318724925 | 3.833394 | 552.643732 | 1.002691 | 1.143381 | 0.269057 | 14.338148 |
15 | 3.295288 | 229.528816 | 1.082745 | 8.274510 | 1.153019 | 2.7877124751089823 | 178.771248 | 1.070738 | 1.076631353918203 | 7.218176061183046 | 7.663135 | 621.817606 | 1.004935 | 1.140850 | 0.493461 | 14.084987 |
Conclusion¶
From statistical analysis of empirical data we have made quantitative estimation of the sequence of return risk in future years expressed by 95% confidence intervals. The 5% confidence column in the summary tables quantify a worst case scenario at which 5% of cases will igve lower returns than this. The 95% confidence column in the summary table quantify a best case scenario, where 5% of cases with be give higher returns than this. 90% of all cases in future years is estimated to lie between the 5% and 95% confidence values.
Share the love ☮
If you find this site useful, consider sharing on your favorite social media.