Capital Asset Pricing Model

CAPM

Kapitalmarktgleichgewichtsmodell

CAPM - Capital Asset Pricing Model

Entwickelt in den 1960er Jahren von William F. Sharpe, John Lintner und Jan Mossin.

Auf der Portefeuilletheorie (Portfolio Selection) basierendes Modell des Kapitalmarktes

  • zur Erklärung von Wertpapierrenditen und
  • zur Ableitung von Handlungsempfehlungen;
  • theoretische Alternative u.a. zur Arbitrage Pricing Theory (APT)

CAPM - introduction

Based on Markowitz' modern portfolio theory
aka. mean-variance analysis

Drawing Harry Markowitz, 1927
Nobel Memorial Prize in Economic Sciences, 1990

Problemstellung Portfoliooptimierung

$$\begin{align} \text{maximiere}_{x\in\mathbb R^J}\ & \mathbb E(x^\top \xi) \\ \text{wobei }\ & \mathsf{var}(x^\top\xi)\le q & \text{risk constraint}\\ & x^\top \mathbb 1 = 1\,€ & \text{budget constraint} \\ & (x \ge 0) & \text{ no shortselling constraint} \end{align}$$

Dabei ist:

  • $\xi_j=e_j^\top \xi $ return des assets $j$ ($j=1,\dots,J$),
  • $x=(x_1,\dots,x_J)$ der Allokationsvektor,
  • $q>0$ eine obere Schranke für das Risiko, ein Modellparameter.
  • $\mathbb 1=(1,\dots,1)$ der Einsvektor.

Problemstellung von Markowitz

$$\begin{align} \text{minimiere}_{x\in\mathbb R^J}\ & \mathsf{var}(x^\top\xi) & \text{ minimiere Risiko}\\ \text{wobei }\ & \mathbb E(x^\top \xi)\ge \mu & \text{ untere Schranke für den return}\\ & x^\top \mathbb 1 = 1\,€ & \text{budget constraint}\\ &(x \ge 0) & \text{ no shortselling constraint} \end{align}$$

Dabei ist:

  • $\xi$ Vekter aller returns; $\xi_j:=e_j^\top \xi $ return des assets $j$ ($j=1,\dots,J$),
  • $x=(x_1,\dots,x_J)$ der Allokationsvektor,
  • $\mu\in\mathbb R$ ein Parameter für den Return des Modelles.
  • $\mathbb 1=(1,\dots,1)$ der Einsvektor.

Data

import stock data from quandl first:

In [1]:
import quandl
import pandas as pd               # time series
import datetime
import numpy as np
import matplotlib.pyplot as plt   # Import matplotlib

#quandl.ApiConfig.api_key = "..." - this is the personal Quandl API key
quandlList= [["Microsoft", "Close", "EOD/MSFT"], 
             ["SAP", "Close", "FSE/SAP_X"],
             ["gold", "Value", "WGC/GOLD_DAILY_EUR"], 
             ["oil", "Value", "EIA/PET_RWTC_D"], 
             ["E.ON", "Close", "FSE/EON_X"],
             ["deutsche Bank", "Close", "FSE/DBK_X"],
             ["Allianz", "Close", "FSE/ALV_X"],
             ["Munich Re", "Close", "FSE/MUV2_X"], 
             ["€/$", "Value", "ECB/EURUSD"]
            ]

# We look at stock prices over the past year
start = datetime.datetime(2018,1,2)
#start = datetime.datetime(2018,1,2)
end = datetime.date.today()

stocks = pd.DataFrame() 
for s in quandlList:            # this call includes the personal Quandl API key
    tmp= quandl.get(s[2], start_date=start, end_date=end, authtoken="...")
    stocks= pd.concat([stocks, pd.DataFrame({s[0]: tmp[s[1]]})], axis=1, sort=True)

stocks['Microsoft']= stocks['Microsoft']/ stocks['€/$'] 
stocks['€/$']=1/stocks['€/$']
stocks   # stocks.head(); stocks
Out[1]:
Microsoft SAP gold oil E.ON deutsche Bank Allianz Munich Re €/$
Date
2018-01-02 71.239121 92.80 1089.29 60.37 9.080 15.960 192.70 180.20 0.828844
2018-01-03 71.820677 94.07 1093.61 61.61 NaN NaN NaN 181.50 0.831739
2018-01-04 72.200580 NaN 1088.57 61.98 NaN NaN NaN 184.55 0.828844
2018-01-05 73.217103 NaN 1094.30 61.49 NaN NaN NaN 184.75 0.830220
2018-01-08 73.732565 NaN 1102.12 61.73 NaN NaN NaN 185.55 0.835213
2018-01-09 73.935635 NaN 1098.91 62.92 NaN NaN NaN 186.65 0.838082
2018-01-10 73.232155 NaN 1101.49 63.60 NaN NaN NaN 185.95 0.833889
2018-01-11 73.296164 91.43 1098.33 63.81 8.900 15.350 200.80 187.05 0.832154
2018-01-12 73.823844 90.73 1092.33 64.22 8.910 15.290 202.00 190.00 0.823927
2018-01-15 NaN 90.06 1091.22 NaN 8.930 15.350 202.10 190.25 0.814531
2018-01-16 72.240392 90.97 1090.59 63.82 9.050 15.230 202.05 190.15 0.817661
2018-01-17 73.867082 90.47 1090.99 63.92 8.930 15.100 202.45 190.55 0.819471
2018-01-18 73.641193 91.18 1088.44 63.96 8.880 15.180 203.40 191.65 0.817327
2018-01-19 73.439412 92.30 1092.03 63.38 8.920 15.330 205.45 192.25 0.815993
2018-01-22 74.850887 91.78 1087.70 63.66 9.010 15.780 205.25 192.10 0.817060
2018-01-23 75.026533 92.91 1084.68 64.45 9.080 15.880 205.75 192.80 0.816393
2018-01-24 74.336140 92.27 1093.28 65.69 8.800 15.880 204.80 191.75 0.809585
2018-01-25 74.417667 90.80 1083.70 65.62 8.660 15.800 203.90 191.50 0.805997
2018-01-26 75.635252 91.72 1088.31 66.27 8.620 15.650 203.90 191.05 0.804117
2018-01-29 75.870426 92.09 1087.57 65.71 8.590 15.490 204.40 191.80 0.807820
2018-01-30 74.663876 90.13 1083.59 64.64 8.510 14.790 203.75 190.85 0.805088
2018-01-31 76.270370 90.83 1079.71 64.82 8.460 14.790 203.50 189.55 0.802761
2018-02-01 75.656152 89.79 1075.62 65.92 8.370 14.770 201.45 189.20 0.802633
2018-02-02 73.471021 88.00 1070.32 65.50 8.240 13.860 200.35 189.45 0.800512
2018-02-05 70.739550 87.44 1073.75 64.18 8.290 13.650 198.24 190.50 0.803859
2018-02-06 74.077379 85.29 1078.54 63.48 8.100 13.170 190.70 180.35 0.811096
2018-02-07 72.629275 86.28 1077.52 61.91 8.230 13.110 195.06 180.45 0.810504
2018-02-08 69.384590 84.08 1073.18 61.30 8.080 12.800 188.58 177.80 0.816193
2018-02-09 71.848774 82.86 1072.87 59.20 7.992 12.514 185.16 177.45 0.814797
2018-02-12 72.682052 83.28 1077.14 59.41 8.018 13.018 187.78 181.30 0.815461
... ... ... ... ... ... ... ... ... ...
2019-03-25 103.894040 98.64 1165.42 58.71 9.981 7.225 196.20 207.70 0.883002
2019-03-26 104.428306 100.86 1166.88 59.87 9.973 7.305 197.58 208.00 0.885661
2019-03-27 103.694166 100.24 1163.97 59.39 9.980 7.514 198.00 208.30 0.888021
2019-03-28 104.234266 101.44 1152.78 59.29 9.932 7.257 197.44 209.20 0.891424
2019-03-29 104.975523 103.00 1153.67 60.19 9.912 7.260 198.28 211.00 0.890076
2019-04-01 105.927376 103.00 1152.75 61.59 9.826 7.526 199.94 211.80 0.889996
2019-04-02 106.419643 103.10 1153.03 62.53 9.917 7.578 201.55 214.00 0.892857
2019-04-03 106.706395 103.84 1149.16 62.46 10.050 7.645 205.60 214.80 0.889442
2019-04-04 106.390944 103.64 1143.98 62.12 10.022 7.582 206.60 215.70 0.891345
2019-04-05 106.730170 102.50 1148.04 63.10 10.016 7.492 206.60 216.00 0.890234
2019-04-08 106.642362 101.88 1154.38 64.37 10.042 7.349 205.40 214.50 0.889205
2019-04-09 105.772812 98.38 1155.86 64.05 10.040 7.295 205.65 214.40 0.886761
2019-04-10 106.560865 99.70 1160.30 64.62 10.076 7.242 206.50 214.50 0.886603
2019-04-11 106.827060 99.67 1152.13 63.61 10.048 7.452 207.95 215.60 0.887784
2019-04-12 106.836852 99.39 1143.98 63.86 9.918 7.615 208.30 214.20 0.883314
2019-04-15 107.000796 99.76 1136.79 63.43 9.873 7.648 209.80 215.10 0.883939
2019-04-16 106.828837 99.47 1129.51 64.01 9.730 7.775 212.00 219.40 0.884564
2019-04-17 107.751526 99.37 1128.82 63.74 9.762 7.825 213.90 219.90 0.884877
2019-04-18 109.662222 100.48 1134.61 64.02 9.830 7.783 214.85 221.50 0.888889
2019-04-19 NaN NaN 1134.61 NaN NaN NaN NaN NaN NaN
2019-04-22 NaN NaN 1133.45 65.66 NaN NaN NaN NaN NaN
2019-04-23 111.551801 101.84 1132.77 66.24 9.820 7.658 214.30 222.60 0.889284
2019-04-24 111.526452 114.62 1135.15 65.96 9.603 7.592 211.95 221.10 0.892140
2019-04-25 116.110761 115.04 1149.32 65.23 9.669 7.479 213.30 222.60 0.899038
2019-04-26 116.671158 114.34 1150.46 63.29 9.648 7.341 213.85 223.50 0.898230
2019-04-29 116.385650 115.00 NaN 63.39 9.598 7.395 213.90 221.80 0.896861
2019-04-30 116.420039 114.58 NaN NaN 9.568 7.369 214.80 223.00 0.891424
2019-05-01 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2019-05-02 112.566893 113.10 NaN NaN 9.428 7.389 214.80 212.80 0.891902
2019-05-03 115.553563 113.66 NaN NaN 9.380 7.346 215.05 212.60 0.896459

349 rows × 9 columns

Visualize stock data

In [2]:
import plotly                     #import plotly.plotly as py
import plotly.graph_objs as go

# Must enable in order to use plotly off-line (vs. in the cloud... hate cloud)
plotly.offline.init_notebook_mode()

stock_return = stocks.apply(lambda x: (x / x[0] ))
data = [go.Scatter( x=stock_return.index, y=stock_return[x[0]], name= x[0]) for x in quandlList]

fig = go.Figure(data=data, layout = go.Layout(title=go.layout.Title(text='assets, S')))
plotly.offline.iplot(fig, filename='stock data')

Compute annualized log-returns

In [3]:
logReturnXi= stocks.copy() # logarithmic returns
logReturnXi.iloc[0]= float('NaN')
for j in range(1, len(logReturnXi)):
    logReturnXi.iloc[j]= np.log(stocks.iloc[j]/ stocks.iloc[j-1]) * 365 \
                                / (stocks.index[j]-stocks.index[j-1]).days


data = [go.Scatter( x=logReturnXi.index, y=logReturnXi[x[0]], name= x[0]) for x in quandlList]
fig = go.Figure(data=data, layout = go.Layout(title=go.layout.Title(text='log returns, ξ')))
plotly.offline.iplot(fig, filename='log returns')

Summary statistics

In [4]:
print('Annualized return, average: ')
print(logReturnXi.mean())
pd.DataFrame.describe(logReturnXi)
Annualized return, average: 
Microsoft        0.478369
SAP              0.365137
gold             0.090276
oil              0.108264
E.ON             0.065520
deutsche Bank   -1.046040
Allianz          0.013374
Munich Re        0.141922
€/$              0.098937
dtype: float64
Out[4]:
Microsoft SAP gold oil E.ON deutsche Bank Allianz Munich Re €/$
count 315.000000 317.000000 343.000000 323.000000 316.000000 316.000000 316.000000 325.000000 333.000000
mean 0.478369 0.365137 0.090276 0.108264 0.065520 -1.046040 0.013374 0.141922 0.098937
std 5.488508 5.092087 1.533694 6.409532 4.040269 6.827275 3.811055 3.704642 1.437152
min -22.461526 -22.350860 -3.901745 -28.020425 -12.968122 -27.072186 -16.778043 -19.984767 -4.261149
25% -2.000929 -1.786786 -0.746142 -2.580284 -2.057454 -3.824114 -1.485049 -1.293798 -0.678521
50% 0.662054 0.329944 -0.050158 0.484682 -0.032685 -0.722122 0.368059 0.466795 0.086006
75% 2.706356 2.875560 0.868823 3.431441 2.027754 2.770119 2.016499 2.101000 0.937180
max 19.867714 43.150065 5.687641 26.769606 13.872353 20.628036 11.584559 9.995202 4.339068

CAPM - diversification

Don't put all your eggs in one basket. (Don Quixote)

Markowitz - explicit solution

The explicit asset allocation of the Markowitz problem is $$x^*(\mu)=\frac{a}{d} C^{-1}\mathbb 1-\frac b d C^{-1}r+\mu\left(\frac{c}{d} C^{-1}r-\frac b d C^{-1}\mathbb 1\right);$$ here

  • $r:=\mathbb E \xi$ is the vector of returns,
  • $C:=\mathsf{cov}(\xi)$ is the covariance matrix,
    auxiliary quantities include
  • $a:=r^\top C^{-1} r$, $b:=r^\top C^{-1} \mathbb 1$, $c:=\mathbb 1^\top C^{-1} \mathbb 1$ and $d:=a c- b^2$

Returns and covariance matrix

auxiliary quantities

In [5]:
r=          logReturnXi.mean()
print('returns: r=')
print(r)

# auxiliary quantities
CovMatrix = logReturnXi.cov()          # covariance matrix
CovInv=     np.linalg.inv(CovMatrix)   # its inverse

J= np.size(logReturnXi, axis=1)
a= np.matmul(r.values,   np.matmul(CovInv, r.values));   print(); print('a= ', a)
b= np.matmul(r.values,   np.matmul(CovInv, np.ones(J))); print('b= ', b)
c= np.matmul(np.ones(J), np.matmul(CovInv, np.ones(J))); print('c= ', c)
# print('d= ', a*c-b*b)

print(); print('correllation matrix:')
logReturnXi.corr()
returns: r=
Microsoft        0.478369
SAP              0.365137
gold             0.090276
oil              0.108264
E.ON             0.065520
deutsche Bank   -1.046040
Allianz          0.013374
Munich Re        0.141922
€/$              0.098937
dtype: float64

a=  0.05741508509361845
b=  0.07312937286631957
c=  1.1620643896001883

correllation matrix:
Out[5]:
Microsoft SAP gold oil E.ON deutsche Bank Allianz Munich Re €/$
Microsoft 1.000000 0.328719 0.006790 0.126168 0.075760 0.176355 0.128975 0.086191 0.207350
SAP 0.328719 1.000000 -0.041838 0.201074 0.237079 0.292289 0.443678 0.343766 0.021835
gold 0.006790 -0.041838 1.000000 0.007056 -0.015530 -0.185832 -0.216460 -0.140408 0.039761
oil 0.126168 0.201074 0.007056 1.000000 0.128123 0.161423 0.183008 0.167050 -0.110095
E.ON 0.075760 0.237079 -0.015530 0.128123 1.000000 0.239490 0.337682 0.268253 0.011373
deutsche Bank 0.176355 0.292289 -0.185832 0.161423 0.239490 1.000000 0.550549 0.445582 -0.143260
Allianz 0.128975 0.443678 -0.216460 0.183008 0.337682 0.550549 1.000000 0.742268 -0.088917
Munich Re 0.086191 0.343766 -0.140408 0.167050 0.268253 0.445582 0.742268 1.000000 -0.106053
€/$ 0.207350 0.021835 0.039761 -0.110095 0.011373 -0.143260 -0.088917 -0.106053 1.000000

The efficient portfolio: example

In [6]:
# efficient asset allocation following Markowitz
def xEfficient(mu, r0=None, a=a, b=b, c=c):
    d= a*c- b*b
    if r0==None:
        xs= mu* ( c/d* np.matmul(CovInv,r) -         b/d*np.matmul(CovInv, np.ones(J))) \
                + a/d* np.matmul(CovInv,np.ones(J))- b/d*np.matmul(CovInv, r)
    else:
        mu0= (a-r0*b)/ (b-r0*c)
        xs=  (mu-r0) / (mu0-r0) * (np.matmul(CovInv,r)-r0*np.matmul(CovInv, np.ones(J)))/(b-r0*c)
        xs['risk free']= (mu0-mu)/(mu0-r0)
    return xs


# example
mu= 0.01
xsBsp= xEfficient(mu)
print(xsBsp); print()
print("σ= ", np.sqrt(np.matmul(xsBsp.values, np.matmul(CovMatrix.values, xsBsp.values.transpose()))))
Microsoft       -0.028124
SAP             -0.017103
gold             0.417599
oil              0.018184
E.ON             0.013585
deutsche Bank    0.057649
Allianz          0.052282
Munich Re        0.015537
€/$              0.470392
dtype: float64

σ=  0.9558168758336628

Efficient asset allocations

Visualization for varying $\mu$.

In [7]:
mux = np.linspace(0.0, .5, 101)
s1= [xEfficient(muy) for muy in mux]

data=  [go.Scatter( x=mux, y=[s1[i][x[0]] for i in range(len(mux))], name= x[0]) for x in quandlList]
data+= [go.Scatter( x=mux, y= (mux*mux*c-2*mux*b+a)/(a*c-b*b), name= 'σ(μ)', yaxis='y2')]
fig = go.Figure(data=data, layout=go.Layout(xaxis=dict(title='μ'), 
                                              yaxis=dict(title='allocation'),
                                              yaxis2=dict(overlaying='y', side='right', showticklabels=False, showgrid=False),
                                              title=go.layout.Title(text='efficient asset allocations')))
plotly.offline.iplot(fig, filename='asset allocations')

CAPM

Tangency portfolio (das Marktportfolio)

The mean-variance plot

In [8]:
# sigma as a function of mu
def sigma(mu, a=a, b=b, c=c):
    return np.sqrt(c*mu*mu-2*mu*b+a)/(a*c-b*b)

# the tangecny portfolio
riskFree= 0.02              # set the risk free rate
muMarket= (a - riskFree*b) / (b - riskFree*c)

print('Tangency portfolio: σ(CAPM)= ', sigma(muMarket))
print('                    μ(CAPM)= ', muMarket)

# plot the efficient frontier and tangency
muy=   np.linspace(.0, muMarket+.1, 201)
data=  [go.Scatter( y=muy, x=[sigma(mu, a, b, c) for mu in muy], name= 'μ(σ)', fill='tozeroy')]
data+= [go.Scatter( y=[muMarket, muMarket], x=[sigma(muMarket), sigma(muMarket)], 
                                            name= 'tangency portfolio', marker= dict(size=15))]
data+= [go.Scatter( y=muy, x=[sigma(muMarket) * (mu-riskFree)/(muMarket-riskFree) for mu in muy], name= 'capital market line')]
fig = go.Figure(data=data, layout=go.Layout(xaxis=dict(title='σ (variance)'), 
                                            yaxis=dict(title='mean, μ'),
                                            title=go.layout.Title(text='mean-variance plot')))
plotly.offline.iplot(fig, filename='mean variance plot')
Tangency portfolio: σ(CAPM)=  18.967939840384627
                    μ(CAPM)=  1.1215603395669007

Tangency portfolio

The tangency portfolio is the market portfolio

$$\begin{align} \mu_m =&r_0+ s_m \cdot\sigma_m=\frac{a-r_0\, b}{b-r_0\,c} & \text{return of the market portfolio}\\ \sigma_m=& \frac{\mu_m-r_0}{s_m} & \text{variance of the market portfolio}\\ s_m:=&\frac{\mu_m-r_0}{\sigma_m}& \text{Sharpe ratio of the market portfolio} \end{align}$$

Here, $r_0$ is the return of the risk free asset. The market portfolio is $x_m:=\frac{\sigma_m}{s_m}C^{-1}\left(r-r_0\mathbb 1\right).$

CAPM

Market portfolio (das Marktportfolio)

In [9]:
# Parameter des tangency portfolios
print('marktet portfolio: σ(CAPM)= ', sigma(muMarket))
print('                   μ(CAPM)= ', muMarket)
print('Sharpe ratio:      s(CAPM)= ', (muMarket- riskFree)/ sigma(muMarket))
print('the market portfolio:')
xEfficient(muMarket)
marktet portfolio: σ(CAPM)=  18.967939840384627
                   μ(CAPM)=  1.1215603395669007
Sharpe ratio:      s(CAPM)=  0.05807485414001416
the market portfolio:
Out[9]:
Microsoft        0.332382
SAP              0.242649
gold             0.255103
oil              0.027915
E.ON             0.070434
deutsche Bank   -0.718743
Allianz          0.108501
Munich Re        0.524757
€/$              0.157002
dtype: float64

Asset allocation: one fund theorem

In [10]:
# Visualization One Fund Theorem

mux = np.linspace(0.0, muMarket+.1, 21)
s1= [xEfficient(muy, riskFree) for muy in mux]
minimum= min([min(s1[i]) for i in range(len(s1))])
maximum= max([max(s1[i]) for i in range(len(s1))])

data=  [go.Scatter( x=mux, y=[s1[i][x[0]] for i in range(len(mux))], name= x[0]) for x in quandlList]
data+= [go.Scatter( x=mux, y=[s1[i]['risk free'] for i in range(len(mux))], name= 'risk free')]
data+= [go.Scatter( x=mux, y= (mux*mux*c-2*mux*b+a)/(a*c-b*b), name= 'σ(μ)', yaxis='y2')]
data+= [go.Scatter( x=[riskFree, riskFree], y=[minimum, maximum], name= 'risk free portfolio')]
data+= [go.Scatter( x=[muMarket, muMarket], y=[minimum, maximum], name= 'market portfolio')]

fig = go.Figure(data=data, layout=go.Layout(xaxis=dict(title='μ'), 
                                              yaxis=dict(title='allocation', zerolinewidth= 6),
                                              yaxis2=dict(overlaying='y', side='right', showticklabels=False, showgrid=False),
                                              title=go.layout.Title(text=' Tobin-Separation or „Two Fund Separation“ ')))
plotly.offline.iplot(fig, filename='asset allocations, risk free')

CAPM - single-index-model

(Ein-Faktor Modell; idiosyncratic vs. systematic risk) $$\begin{align} \mathbb \mu(\sigma)=&r_0+ \frac{\sigma}{\sigma_m}\cdot(\mu_m-r_0) & \text{ capital market line}\\ \mathbb E e_j^\top\xi=r_j=&r_0+ \beta_j\cdot(\mu_m-r_0) & \text{ security market line} \end{align}$$
where $$\beta_j=\frac{\mathsf{cov}(x_m^\top\xi,e_j^\top\xi)}{\mathsf{var}(x_m^\top\xi)} = \frac{\sigma_j}{\sigma_m} \cdot \rho_{j,m}.$$

$\beta_j$ is an indicator of asset $j$'s vulnerability to systematic risk. Note that $\beta_m=1$ (i.e., the market portfolio $x_m$ has only systemic risk, but no specific risk, aka. unsystematic or idiosyncratic).

CAPM - statistical interpretation

For asset $j$ consider the regression problem $$e_j^\top \xi=\alpha_j + \beta_j\cdot x_m^\top \xi+\varepsilon.$$ Then the estimator is $$\beta_j=\frac{\mathsf{cov}(x_m^\top\xi,e_j^\top\xi)}{\mathsf{var}(x_m^\top\xi)}.$$

$\beta$ coefficients

value                   interpretation example
$1<\beta$ asset moves in the same direction microsoft
$\beta=1$ representative stock index
$0<\beta<1$ asset moves in same direction, but in lesser amount staple stock
$ \beta=0$ uncorrelated fixed yield asset
$ -1< \beta<0$ moves in opposite direction inverse exchange trade fund
$ \beta<-1$ opposite direction, in greater amount inverse fund
In [11]:
# print β coefficients
(r-riskFree) / (muMarket-riskFree)
Out[11]:
Microsoft        0.416108
SAP              0.313316
gold             0.063797
oil              0.080126
E.ON             0.041323
deutsche Bank   -0.967754
Allianz         -0.006015
Munich Re        0.110681
€/$              0.071659
dtype: float64
In [15]:
j=5    # pick the asset
xs= xEfficient(muMarket)
xiMarket= [np.matmul(xs.values, row.values) for index, row in logReturnXi.iterrows()]
xij=      [row[quandlList[j][0]] for index, row in logReturnXi.iterrows()]
betaj=    (r[quandlList[j][0]]-riskFree) / (muMarket-riskFree)

data = [go.Scatter( x=xiMarket, y=xij, mode='markers',  name= quandlList[j][0])]
data+= [go.Scatter( x=[np.nanmin(xiMarket), np.nanmax(xiMarket)], 
                    y=r[quandlList[j][0]] - muMarket*betaj 
                           + [betaj*np.nanmin(xiMarket), betaj*np.nanmax(xiMarket)], 
                           name= 'regression')]

layout = go.Layout(xaxis=dict(title='ξ (market)', zeroline= False),
                   yaxis=dict(title= 'ξ ('+ quandlList[j][0]+')', zeroline=False),
                   title = quandlList[j][0]+'<br>(β=' + str(betaj) +')')

plotly.offline.iplot(dict(data=data, layout=layout), filename='basic-scatter')

CAPM - Treynor ratio (reward-to-volatility ratio)

Recall that $$T_j:=\frac{r_j-r_0}{\beta_j}=\mu_m-r_0$$ is independent of $j$.

Treynor stock picking rule:

$$T_j>1.$$

The risk free rate is $$r_0=\frac{\mu_m \beta_j-r_j}{\beta_j-1}.$$

CAPM - discussion

Despite it failing numerous empirical tests and the existence of more modern approaches to asset pricing and portfolio selection (such as arbitrage pricing theory and Merton's portfolio problem), the CAPM still remains popular due to its simplicity and utility in a variety of situations.