Entwickelt in den 1960er Jahren von William F. Sharpe, John Lintner und Jan Mossin.
Auf der Portefeuilletheorie (Portfolio Selection) basierendes Modell des Kapitalmarktes
Harry Markowitz, 1927
Nobel Memorial Prize in Economic Sciences, 1990
Dabei ist:
Dabei ist:
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
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')
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')
print('Annualized return, average: ')
print(logReturnXi.mean())
pd.DataFrame.describe(logReturnXi)
Don't put all your eggs in one basket. (Don Quixote)
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= 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()
# 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()))))
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')
# 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')
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).$
# 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)
# 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')
(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).
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)}.$$
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 |
# print β coefficients
(r-riskFree) / (muMarket-riskFree)
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')
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.