Ein Portfolio ist ein Gewichtsvektor
Ein Portfolio wird durch ein Gewicht je Asset beschrieben: den Anteil seines Werts, der dort angelegt ist. Die Gewichte summieren sich zu 1, und ein negatives Gewicht ist eine Short-Position, die die anderen finanziert. Die Rendite über eine Periode ist der gewichtete Mittelwert der Asset-Renditen, die erwartete Rendite also ein Skalarprodukt w @ mu. Die Rendite ist die einfache Hälfte: linear, ohne Wechselwirkung zwischen Assets. Das Risiko nicht.
import numpy as np
weights = np.array([0.6, 0.4]) # 60% in asset A, 40% in asset B
mu = np.array([0.08, 0.05]) # expected annual returns
print(weights.sum()) # 1.0
print(weights @ mu) # 0.068 = 0.6 * 0.08 + 0.4 * 0.05Die Varianz ist eine quadratische Form
Für zwei Assets ist die Varianz von w1 * A + w2 * B gleich w1**2 * var(A) + w2**2 * var(B) + 2 * w1 * w2 * cov(A, B): die Eigenvarianz jedes Assets plus ein Kreuzterm. Bei n Assets gibt es n * n Terme w_i * w_j * cov[i, j], und die ganze Summe ist die quadratische Form w @ cov @ w, eine Zeile in NumPy. Die Kreuzterme sind der Kern: Sind zwei Assets nicht perfekt korreliert, heben sie sich teilweise auf, und das Portfolio ist weniger riskant als der gewichtete Mittelwert der Risiken.
# The variance two ways: the explicit formula and the matrix form
import numpy as np
weights = np.array([0.6, 0.4])
cov = np.array([[0.04, 0.006], [0.006, 0.01]]) # variances 0.04 and 0.01 (volatilities 20% and 10%), covariance 0.006
explicit = weights[0] ** 2 * cov[0, 0] + weights[1] ** 2 * cov[1, 1] + 2 * weights[0] * weights[1] * cov[0, 1]
matrix_form = weights @ cov @ weights
print(round(explicit, 6), round(matrix_form, 6)) # 0.01888 0.01888
print(round(float(np.sqrt(matrix_form)), 4)) # 0.1374 a 13.7% volatility, below 0.6*20% + 0.4*10% = 16%# Diversification: 50/50 in two assets of 20% volatility, for several correlations
import numpy as np
weights = np.array([0.5, 0.5])
for rho in (1.0, 0.5, 0.0, -0.5):
cov = 0.2 * 0.2 * np.array([[1.0, rho], [rho, 1.0]])
print(rho, round(float(np.sqrt(weights @ cov @ weights)), 4)) # 1.0: 0.2, 0.5: 0.1732, 0.0: 0.1414, -0.5: 0.1Woher kommt das Risiko?
Ein Manager will wissen, welche Positionen das Risiko treiben. Der Risikobeitrag von Asset i ist w_i * (cov @ w)_i / sigma_p: sein Gewicht mal die Stärke, mit der es sich mit dem Gesamtportfolio bewegt, geteilt durch die Portfoliovolatilität sigma_p. Die Beiträge summieren sich genau zu sigma_p und zerlegen so die Gesamtsumme in Teile. Ein Asset mit kleinem Gewicht, aber hoher Kovarianz zum Rest kann weit mehr beitragen, als sein Gewicht vermuten lässt, und ein Hedge kann negativ beitragen.
# Risk contributions of a three-asset portfolio: they add up to the volatility
import numpy as np
weights = np.array([0.5, 0.3, 0.2])
cov = np.array([[0.0400, 0.0060, 0.0100],
[0.0060, 0.0100, 0.0020],
[0.0100, 0.0020, 0.0225]])
variance = weights @ cov @ weights
contributions = weights * (cov @ weights) / np.sqrt(variance)
print(np.round(contributions, 4), round(float(contributions.sum()), 4))
print(round(float(np.sqrt(variance)), 4))mu und cov sind Schätzungen, und die Varianz ist die verlässlichere: Erwartete Renditen sind sehr verrauscht, Kovarianzen weit weniger. Gewichte, mu und cov müssen außerdem dieselbe Periode haben: Eine Tageskovarianz mit Jahresrenditen ist ein häufiger Fehler; die Varianz skaliert man mit der Periodenzahl, die Volatilität mit deren Wurzel.- Die Portfoliorendite ist linear:
w @ mu. Die Varianz ist die quadratische Formw @ cov @ wmitn * nTermen und Kreuztermen, durch die eine Korrelation unter 1 das Risiko senkt. - Die Volatilität ist
sqrt(variance * periods); die Annualisierung muss zur Periode voncovpassen. - Die Risikobeiträge
w_i * (cov @ w)_i / sigma_pzerlegen die Volatilität exakt nach Assets; ein Hedge kann negativ beitragen.
Als Nächstes: das Minimum-Varianz-Portfolio, die Gewichte wählen, die dieses Risiko so klein wie möglich machen.
Lab: Was bewertet wird
- Mit
portfolio_returndie erwartete Rendite aufsummieren25 Pkt. - Mit
portfolio_variancedas Risiko messen25 Pkt. - Mit
portfolio_voldie Volatilität angeben25 Pkt. - Mit
risk_contributionsdas Risiko auf die Assets verteilen25 Pkt.