σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft AcademySkills
Ctrl K
AO
+1,2 Tsd. Lernende
AnmeldenBeitreten ↗
Skills
AO
+1,2 Tsd. Lernende
Anmelden
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python-Skill›Modul 5 · Portfoliooptimierung›Thema 5.2·~45 Min.Mittelstufe

Rendite und Varianz eines Portfolios

Position in der SkillModul 5 von 11 · Thema 2 von 5
5.2 Rendite und Varianz eines Portfolios
—Lab-Punkte— / 100XP gesamt—Serie—

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.05

Die 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.1

Woher 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))
Die Eingaben zählen mehr als die FormelDie Formeln sind exakt, aber 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 Form w @ cov @ w mit n * n Termen und Kreuztermen, durch die eine Korrelation unter 1 das Risiko senkt.
  • Die Volatilität ist sqrt(variance * periods); die Annualisierung muss zur Periode von cov passen.
  • Die Risikobeiträge w_i * (cov @ w)_i / sigma_p zerlegen 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_return die erwartete Rendite aufsummieren25 Pkt.
  • Mit portfolio_variance das Risiko messen25 Pkt.
  • Mit portfolio_vol die Volatilität angeben25 Pkt.
  • Mit risk_contributions das Risiko auf die Assets verteilen25 Pkt.
Explorer · lab-83-1
▾ lab-83-1
…
bash · im Browser
learner@quantcraft:~/lab-83-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-83-1 wird auf die Startdateien zurückgesetzt und das Terminal geleert. Ihre aktuelle Lösung geht verloren – das lässt sich nicht rückgängig machen.

Wird zurückgesetzt
  • main.py → Startcode
  • Terminal-Verlauf und Testausgabe
  • Nicht eingereichte Änderungen
Bleibt erhalten
  • Beste Lab-Punktzahl
  • Ihre XP und Ihre Serie
  • Vorlesungsfortschritt und Notizen

Melde dich an, um deinen Code auszuführen.

Alle Lektionen kannst du kostenlos lesen. Erstelle ein Konto oder melde dich an, um Code auszuführen, Tests zu starten und dieses Lab abzugeben.

  • IDE im Browser mit Bash-Terminal — nichts zu installieren
  • Sofortige Bewertung, XP und dein Platz auf der Skill
Konto erstellenAnmelden
ODER
Weiter mit GitHub