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')