σμ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 2 · NumPy & pandas für Marktdaten›Thema 2.10·~35 Min.Mittelstufe

Einfache Renditen

Position in der SkillModul 2 von 11 · Thema 10 von 20
2.10 Einfache Renditen
—Lab-Punkte— / 100XP gesamt—Serie—

Die prozentuale Veränderung

Preise lassen sich schwer vergleichen: Eine Bewegung von 5 $ bedeutet bei einer 20-$-Aktie etwas anderes als bei einer 500-$-Aktie. Eine einfache Rendite nimmt die Skala heraus. Sie ist die Preisänderung als Bruchteil des vorherigen Preises, sodass +2 % bei jedem Wert dasselbe bedeutet.

r_t = (P_t - P_{t-1}) / P_{t-1} = P_t / P_{t-1} - 1

In pandas verschiebt prices.shift(1) jeden Wert um einen Schritt nach unten, sodass jede Zeile den vorherigen Preis sieht. Die Division durch ihn berechnet alle Renditen auf einmal, und die erste ist NaN, weil es keinen Vorgängerpreis gibt. prices.pct_change() tut dasselbe in einem Aufruf.

import pandas as pd

prices = pd.Series([100.0, 102.0, 100.98, 103.0], index=["Mon", "Tue", "Wed", "Thu"])

returns = prices / prices.shift(1) - 1
print(returns.round(4))
# Mon     NaN
# Tue    0.02
# Wed   -0.01
# Thu    0.02
# dtype: float64

print(prices.pct_change().round(4).tolist())   # [nan, 0.02, -0.01, 0.02]

Renditen verketten sich, sie addieren sich nicht

Ein Tag mit +2 % und danach einer mit -1 % ergibt nicht +1 % in zwei Tagen. Jede Rendite gilt für einen anderen Ausgangspreis, daher multiplizieren sich die Wachstumsfaktoren 1 + r: Die Gesamtrendite ist (1 + r1) * (1 + r2) * ... - 1. Lassen Sie das NaN der ersten Zeile weg (prod ignoriert es), dann entspricht das Ergebnis dem Endpreis geteilt durch den Anfangspreis minus eins. Die Renditen zu addieren kommt nah heran, ist aber falsch, und die Lücke wächst mit der Volatilität.

# Compounding the returns gives the same total as the end price over the start price
returns = prices.pct_change().dropna()

print(round((1 + returns).prod() - 1, 6))            # 0.03
print(round(prices.iloc[-1] / prices.iloc[0] - 1, 6))   # 0.03
print(round(returns.sum(), 6))                       # 0.030004   close, but not the same

print((1 + returns).cumprod().round(4).tolist())     # [1.02, 1.0098, 1.03]   the growth of 1 dollar
# Gains and losses are not symmetric: +10% then -10% does not get you back
up, down = 0.10, -0.10
print(round((1 + up) * (1 + down) - 1, 4))   # -0.01

# After a -50% loss you need +100% to recover
print(1 / (1 - 0.5) - 1)   # 1.0

Über Werte und über Jahre

Einfache Renditen addieren sich über Werte hinweg: Die Rendite eines Portfolios in einer Periode ist die Summe von Gewicht * Rendite seiner Positionen. Bei Series ordnet weights * returns die Einträge nach Label zu, die Reihenfolge der Symbole spielt also keine Rolle (mit .values verlieren Sie diesen Schutz). Über die Zeit addieren sie sich nicht, sondern verketten sich: Für eine Jahresrate aus einem kürzeren Zeitraum wird der Wachstumsfaktor mit Handelstage / Tage potenziert.

# Weights times returns, matched by label (the order of the symbols differs on purpose)
weights = pd.Series({"AAPL": 0.5, "MSFT": 0.3, "TSLA": 0.2})
day = pd.Series({"TSLA": -0.03, "AAPL": 0.012, "MSFT": 0.004})

print(round((weights * day).sum(), 4))               # 0.0012   correct: AAPL with AAPL, TSLA with TSLA
print(round((weights.values * day.values).sum(), 4))   # -0.0106  wrong: position by position, TSLA met AAPL's weight
# Annualising: 5% in 60 trading days, if it kept compounding at that pace for a year of 252 days
total, days = 0.05, 60
print(round((1 + total) ** (252 / days) - 1, 4))   # 0.2274
Eine Rendite bezieht sich auf den AusgangspreisNennen Sie bei einer Rendite immer die Periode (täglich, monatlich, jährlich) und mischen Sie Perioden nicht: 1 % pro Tag und 1 % pro Jahr sind sehr verschiedene Zahlen. Schreiben Sie die Periode in den Variablennamen, etwa daily_returns.
  • Eine einfache Rendite ist Preis / Vorgängerpreis - 1: prices / prices.shift(1) - 1 oder prices.pct_change(); der erste Eintrag ist NaN.
  • Über die Zeit verketten sich Renditen: (1 + returns).prod() - 1, nie returns.sum().
  • Über Werte hinweg addieren sie sich mit Gewichten: (weights * returns).sum(), nach Label zugeordnet.

Als Nächstes: Log-Renditen, eine Alternative, die sich über die Zeit addiert und die übliche Wahl für Statistik ist.

Lab: Was bewertet wird

  • Mit simple_returns Preise in Periodenrenditen umwandeln25 Pkt.
  • Mit cumulative_return die Renditen zu einer Gesamtrendite verketten25 Pkt.
  • Mit portfolio_return die Renditen der Werte zu einer Zahl gewichten25 Pkt.
  • Mit annualized_return eine Rendite als Jahresrate ausdrücken25 Pkt.
Explorer · lab-43-1
▾ lab-43-1
…
bash · im Browser
learner@quantcraft:~/lab-43-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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