σμ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.5·~55 Min.Mittelstufe

Die Effizienzlinie

Position in der SkillModul 5 von 11 · Thema 5 von 5
5.5 Die Effizienzlinie
—Lab-Punkte— / 100XP gesamt—Serie—

Das Risiko für jedes Renditeniveau

Das vorige Thema fand für eine Zielrendite die Gewichte mit der kleinsten Varianz. Tut man das für jedes Ziel und trägt die Volatilität horizontal gegen die Rendite vertikal auf, bilden die Punkte eine Kurve, die Effizienzlinie. Jedes Portfolio aus diesen Assets liegt darauf oder rechts davon. Ein Portfolio innerhalb der Kurve ist verschwenderisch, denn ein anderes bietet dieselbe Rendite mit weniger Risiko oder mehr Rendite bei gleichem Risiko. Markowitz' Einsicht: Anleger sollten nur die Kurve betrachten.

import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])

def target_return_weights(mu, cov, target):
    ones = np.ones(len(mu))
    s1, sm = np.linalg.solve(cov, ones), np.linalg.solve(cov, mu)
    a, b, c = ones @ s1, ones @ sm, mu @ sm
    d = a * c - b ** 2
    return ((c - b * target) * s1 + (a * target - b) * sm) / d

for target in (0.05, 0.06, 0.07, 0.08, 0.09, 0.10):
    w = target_return_weights(mu, cov, target)
    print(target, round(float(np.sqrt(w @ cov @ w)), 4))

Ihre Form und ihre Spitze

Die Linie ist eine Parabel in (Rendite, Varianz) und eine Hyperbel, wenn man die Volatilität aufträgt. Die Varianz bei Zielrendite t ist (a * t**2 - 2 * b * t + c) / (a * c - b**2), mit denselben vier Zahlen a, b, c wie zuvor. Ihr tiefster Punkt ist das globale Minimum-Varianz-Portfolio bei Rendite b / a: die Spitze der Kurve, das Minimum-Varianz-Portfolio von vor zwei Themen. Nur der Teil von der Spitze aufwärts ist die Effizienzlinie; der untere Ast ist ein Spiegelbild mit weniger Rendite bei gleichem Risiko.

# The tip of the curve: the minimum-variance portfolio and its return
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])
ones = np.ones(3)
x = np.linalg.solve(cov, ones)
w = x / x.sum()
print(np.round(w, 4), round(float(w @ mu), 4), round(float(np.sqrt(w @ cov @ w)), 4))     # the tip: return, volatility

def closed_form_vol(target):
    s1, sm = x, np.linalg.solve(cov, mu)
    a, b, c = ones @ s1, ones @ sm, mu @ sm
    return float(np.sqrt((a * target ** 2 - 2 * b * target + c) / (a * c - b ** 2)))

for target in (0.05, 0.0642, 0.07):
    print(target, round(closed_form_vol(target), 4))

Effiziente und ineffiziente Punkte

Dasselbe Risiko erscheint auf der Kurve bei zwei Renditen, eine auf jedem Ast, und nur die höhere lohnt das Halten. Ein Ziel ist also genau dann effizient, wenn es mindestens der Minimum-Varianz-Rendite entspricht. Der Test ist ein einziger Vergleich, entscheidet aber, welche Ziele in eine Auswahlgrafik gehören. Die Suche nach dem besten Kompromiss auf der Linie wird dann zur Wahl eines Punkts, und eine übliche Antwort ist der mit der meisten Rendite je Risikoeinheit über dem risikolosen Zins.

# The point with the highest Sharpe ratio among candidate targets
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])
rf = 0.02
ones = np.ones(3)
s1, sm = np.linalg.solve(cov, ones), np.linalg.solve(cov, mu)
a, b, c = ones @ s1, ones @ sm, mu @ sm
d = a * c - b ** 2

targets = np.linspace(0.05, 0.10, 11)
vols = np.sqrt((a * targets ** 2 - 2 * b * targets + c) / d)
sharpe = (targets - rf) / vols
for t, v, s in zip(targets, vols, sharpe):
    print(round(float(t), 3), round(float(v), 4), round(float(s), 4))
print("best target:", round(float(targets[np.argmax(sharpe)]), 3))
# Efficient or not: compare a target with the return of the minimum-variance portfolio
import numpy as np

mu = np.array([0.08, 0.05, 0.10])
cov = np.array([[0.0400, 0.0060, 0.0100],
                [0.0060, 0.0100, 0.0020],
                [0.0100, 0.0020, 0.0225]])
x = np.linalg.solve(cov, np.ones(3))
tip = float((x / x.sum()) @ mu)
for target in (0.05, 0.06, 0.07, 0.08):
    print(target, "efficient" if target >= tip else "inefficient")
Eine geschätzte Effizienzlinie ist ein unscharfes BandDie Kurve wird aus mu und cov gezeichnet, beide geschätzt, ist also selbst eine Schätzung, und eine schmeichelhafte: Der Optimierer hat unter allen Mischungen jene gewählt, deren geschätzte Renditen zufällig hoch und Risiken niedrig sind. Reale Ergebnisse landen rechts und unterhalb der sichtbaren Linie. Resampling der Daten oder der Vergleich der Linie der ersten Stichprobenhälfte mit ihrer Wertentwicklung in der zweiten zeigt, wie viel der Kurve Glück war. Sehen Sie die Effizienzlinie als Karte der Zielkonflikte, nicht als Versprechen.
  • Die Effizienzlinie liefert für jede Zielrendite die kleinste Volatilität: sqrt(w @ cov @ w) mit w = target_return_weights(...); Portfolios darin sind verschwenderisch.
  • Ihre Spitze ist das globale Minimum-Varianz-Portfolio bei Rendite b / a; nur Ziele auf oder über dieser Rendite sind effizient.
  • Wählen Sie einen Punkt nach einem Kriterium wie der höchsten Sharpe-Ratio (target - rf) / volatility; die Kurve entsteht aus Schätzungen und ist optimistisch.

Als Nächstes: ein vektorisierter Backtester, eine Handelsregel an historischen Kursen testen.

Lab: Was bewertet wird

  • Mit frontier_vols die Effizienzlinie zeichnen25 Pkt.
  • Mit min_variance_return die Spitze der Kurve finden25 Pkt.
  • Mit is_efficient die gute von der schlechten Hälfte unterscheiden25 Pkt.
  • Mit max_sharpe_target den besten Punkt wählen25 Pkt.
Explorer · lab-86-1
▾ lab-86-1
…
bash · im Browser
learner@quantcraft:~/lab-86-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

Alles in lab-86-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