σμ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 8 · Stochastische Modelle und Machine Learning›Thema 8.4·~55 Min.Fortgeschritten

Asiatische Optionen

Position in der SkillModul 8 von 11 · Thema 4 von 10
8.4 Asiatische Optionen
—Lab-Punkte— / 100XP gesamt—Serie—

Auszahlung auf den Durchschnitt

Ein Standard-Call hängt vom Preis an einem einzigen Tag ab, dem letzten. Eine asiatische Option hängt vom Durchschnittspreis über eine Reihe von Terminen ab: Ein asiatischer Call zahlt max(Durchschnitt - K, 0). Unternehmen nutzen sie, um Kosten abzusichern, die laufend anfallen, etwa einen monatlichen Ölkauf, und sie sind bei Verfall schwer zu manipulieren. Sie sind *pfadabhängig*, für den arithmetischen Durchschnitt gibt es also keine einfache Black-Scholes-Formel, und das übliche Werkzeug ist die Monte-Carlo-Simulation.

import numpy as np

# Two simulated paths: the starting price, then monthly prices; the last column is expiry
paths = np.array([[100.0, 90.0, 110.0, 130.0],
                  [100.0, 70.0,  80.0,  90.0]])
average = paths[:, 1:].mean(axis=1)                      # the monitoring dates only, not the starting price
print(average)                                           # [110.  80.]
print(np.maximum(average - 100.0, 0.0))                  # Asian call payoffs: [10.  0.]
print(np.maximum(paths[:, -1] - 100.0, 0.0))             # European call payoffs on the same paths: [30.  0.]

Die Pfade simulieren

Die Pfade stammen aus der geometrischen Brownschen Bewegung mit risikoneutralem Drift: Der Zins r ersetzt mu. Man zieht eine Matrix standardnormaler Zahlen mit einer Zeile je Pfad und einer Spalte je Beobachtungstermin, wandelt sie in Log-Preisbewegungen um und bildet längs jeder Zeile die kumulative Summe. Ein Array enthält dann alle Pfade, und jeder weitere Schritt (Durchschnitte, Auszahlungen) ist eine vektorisierte Operation entlang der Zeilen, ohne Schleife über Pfade.

import numpy as np

def simulate_paths(s0, rate, sigma, t, steps, n_paths, rng):
    dt = t / steps
    z = rng.standard_normal((n_paths, steps))
    log_moves = (rate - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * z
    return s0 * np.exp(np.hstack([np.zeros((n_paths, 1)), np.cumsum(log_moves, axis=1)]))

rng = np.random.default_rng(1)
paths = simulate_paths(100.0, 0.05, 0.2, 1.0, 12, 50000, rng)       # monthly monitoring for a year
print(paths.shape)                                                   # (50000, 13)
print(round(float(paths[:, -1].mean()), 2), round(100 * np.exp(0.05), 2))      # the risk-neutral mean of the final price

Der Preis und sein Fehlerbalken

Der Preis der Option ist die abgezinste mittlere Auszahlung: exp(-r * T) * mean(payoffs). Ein Monte-Carlo-Preis ist eine Schätzung, geben Sie also stets den Standardfehler an, std(payoffs) / sqrt(Zahl der Pfade) (abgezinst), der zeigt, wie weit die Zahl von der Wahrheit entfernt sein kann: Viermal so viele Pfade halbieren ihn. Ein asiatischer Call ist billiger als ein europäischer auf dieselbe Aktie, weil die Mittelung den Preis glättet und die effektive Volatilität senkt.

import numpy as np

def simulate_paths(s0, rate, sigma, t, steps, n_paths, rng):
    dt = t / steps
    z = rng.standard_normal((n_paths, steps))
    log_moves = (rate - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * z
    return s0 * np.exp(np.hstack([np.zeros((n_paths, 1)), np.cumsum(log_moves, axis=1)]))

def asian_price(paths, strike, rate, t):
    payoff = np.maximum(paths[:, 1:].mean(axis=1) - strike, 0.0)
    discount = np.exp(-rate * t)
    return discount * payoff.mean(), discount * payoff.std(ddof=1) / np.sqrt(len(payoff))

rng = np.random.default_rng(1)
paths = simulate_paths(100.0, 0.05, 0.2, 1.0, 12, 100000, rng)
price, error = asian_price(paths, 100.0, 0.05, 1.0)
european = np.exp(-0.05) * np.maximum(paths[:, -1] - 100.0, 0.0).mean()
print(round(float(price), 3), "+/-", round(float(error), 3))
print(round(float(european), 3), "European call on the same paths")
# Geometric and arithmetic averages of the same monitoring prices
import numpy as np

prices = np.array([90.0, 110.0, 130.0])
arithmetic = prices.mean()
geometric = np.exp(np.log(prices).mean())
print(round(float(arithmetic), 3), round(float(geometric), 3))        # 110.0 108.774: the geometric average is never larger
Der geometrische Durchschnitt hat eine FormelEin Produkt von Lognormalverteilungen ist lognormal, daher lässt sich eine asiatische Option auf den geometrischen Durchschnitt mit einer Formel im Black-Scholes-Stil bewerten. Das macht sie zur Kontrolle nützlich und mehr noch als Kontrollvariable für die arithmetische: Beide Auszahlungen sind stark korreliert, sodass der bekannte exakte Preis der geometrischen Option einen großen Teil des Monte-Carlo-Rauschens aufheben kann. Ein späteres Thema, die Kontrollvariablen, nutzt genau diese Idee.
  • Eine asiatische Option zahlt auf den Durchschnitt der Beobachtungstermine: max(Durchschnitt - K, 0); pfadabhängig, also keine einfache Formel, Monte Carlo ist das Werkzeug.
  • Simulieren Sie alle Pfade in einem Array (Zeilen = Pfade, Spalten = Termine) mit risikoneutralem Drift; Durchschnitte und Auszahlungen sind dann zeilenweise vektorisiert.
  • Preis = exp(-r * T) * mean(payoffs) mit Standardfehler std / sqrt(paths); die Mittelung macht ihn billiger als einen europäischen Call, die geometrische Version ist eine Kontrollvariable.

Als Nächstes: Barrier-Optionen, die entstehen oder verfallen, wenn der Preis ein Niveau berührt.

Lab: Was bewertet wird

  • Mit average_price entlang jedes Pfads mitteln25 Pkt.
  • Mit geometric_average den geometrischen Durchschnitt probieren25 Pkt.
  • Mit asian_call_payoff auf den Durchschnitt auszahlen25 Pkt.
  • Mit asian_price bewerten, samt Fehlerbalken25 Pkt.
Explorer · lab-105-1
▾ lab-105-1
…
bash · im Browser
learner@quantcraft:~/lab-105-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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