σμ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 6 · Backtesting und Handelskosten›Thema 6.6·~55 Min.Fortgeschritten

Realistische Orderausführung

Position in der SkillModul 6 von 11 · Thema 6 von 6
6.6 Realistische Orderausführung
—Lab-Punkte— / 100XP gesamt—Serie—

Eine Ausführung ist keine Gewissheit

Ein naiver Backtest nimmt an, dass eine Order beliebiger Größe zum Preis in den Daten ausgeführt wird. Echte Orders stehen vor drei Fragen. Wie tief ist das Orderbuch: Eine Market-Order nimmt zuerst das beste Angebot, dann das nächste, eine große Order zahlt also einen schlechteren Durchschnittspreis. Hat der Markt mein Limit erreicht: Eine Limit-Order bekommt den verlangten Preis oder besser, aber nur, wenn gehandelt wird. Und wie viel kann ich nehmen: Eine große Order kann nur ein Bruchteil des Bar-Volumens sein, sie wird also in Teilen über die Zeit ausgeführt.

def fill_market_order(book, quantity):
    remaining = quantity
    cost = 0.0
    filled = 0
    for price, size in book:                      # cheapest offer first
        if remaining <= 0:
            break
        take = min(size, remaining)
        cost += take * price
        filled += take
        remaining -= take
    if filled == 0:
        return 0.0, 0
    return cost / filled, filled

book = [(50.00, 300), (50.02, 500), (50.05, 1000)]
print(fill_market_order(book, 200))        # (50.0, 200)           inside the first level
print(fill_market_order(book, 600))        # (50.01, 600)          300 at 50.00 and 300 at 50.02
print(fill_market_order(book, 5000))       # (50.0333, 1800)      the whole book; 3,200 shares stay unfilled
# The average price and the slippage against the best offer grow with the size
def average_price(book, quantity):
    remaining, cost, filled = quantity, 0.0, 0
    for price, size in book:
        take = min(size, remaining)
        cost += take * price
        filled += take
        remaining -= take
    return cost / filled

book = [(50.00, 300), (50.02, 500), (50.05, 1000)]
for quantity in (100, 300, 800, 1800):
    avg = average_price(book, quantity)
    print(quantity, round(avg, 4), round((avg - 50.00) / 50.00 * 10000, 2), "bps above the best offer")

Limit-Orders und Kurslücken

Mit Bar-Daten (Eröffnung, Tief, Hoch) sieht man nicht den Weg innerhalb der Bar, nur ihre Extreme. Ein Buy-Limit bei L wird ausgeführt, wenn das Tief der Bar L oder darunter erreichte. Der Preis ist L, es sei denn, die Bar eröffnete unter L: Dann ist der Markt durch Ihr Limit gesprungen, und Sie werden zur Eröffnung ausgeführt, was besser ist. Ein Sell-Limit ist das Spiegelbild. Eine nur berührte Limit-Order wird in Wirklichkeit vielleicht nicht ausgeführt, weil die Schlange vor Ihnen zuerst bedient wurde; das ist also die optimistische Grenze.

def limit_fill(side, limit, bar_open, bar_low, bar_high):
    if side == "buy" and bar_low <= limit:
        return min(bar_open, limit)             # a gap below the limit fills at the better open
    if side == "sell" and bar_high >= limit:
        return max(bar_open, limit)
    return None

print(limit_fill("buy", 49.95, 50.10, 49.90, 50.20))   # 49.95   traded down through the limit
print(limit_fill("buy", 49.95, 49.90, 49.80, 50.20))   # 49.9    opened below: filled at the open
print(limit_fill("buy", 49.95, 50.10, 50.00, 50.20))   # None    never reached
print(limit_fill("sell", 50.15, 50.00, 49.90, 50.20))  # 50.15

Eine große Order abarbeiten

Viele Handelstische nutzen ein Beteiligungslimit: nicht mehr als etwa 10 % des Volumens nehmen. In einer Bar mit 40.000 gehandelten Aktien sind das 4.000, abgerundet. Eine Order über 5.000 Aktien braucht dann zwei Bars, nicht eine. Das Durchlaufen der Bars ist eine Schleife, die die Restmenge mitführt: Jede Bar füllt min(remaining, int(volume * participation)), und Bars nach Abschluss der Order füllen nichts.

def partial_fill(quantity, bar_volume, participation):
    return min(quantity, int(bar_volume * participation))

def fill_over_bars(quantity, volumes, participation):
    remaining = quantity
    fills = []
    for volume in volumes:
        filled = partial_fill(remaining, volume, participation)
        fills.append(filled)
        remaining -= filled
    return fills

fills = fill_over_bars(5000, [40000, 30000, 80000, 100000], 0.1)
print(fills, sum(fills))                      # [4000, 1000, 0, 0] 5000
Ausführungsmodelle bestimmen Ihre EhrlichkeitJede Vereinfachung hier neigt in dieselbe Richtung: anzunehmen, dass eine Limit-Order beim Berühren ausgeführt wird, dass man den Markt nie bewegt, dass das Volumen da ist. Je mehr ein Ergebnis von Ausführungen abhängt, desto mehr sollte man es mit pessimistischen Regeln testen (nur ausführen, wenn der Preis das Limit durchläuft, ein niedrigeres Beteiligungslimit) und prüfen, ob der Vorteil bleibt.
  • Eine Market-Order durchläuft das Orderbuch Level für Level; der Durchschnittspreis ist volumengewichtet und wird mit der Größe schlechter, ein dünnes Buch füllt nur einen Teil.
  • Eine Limit-Order wird ausgeführt, wenn die Bar das Limit erreicht, zur Eröffnung, wenn sie es übersprungen hat; eine bloße Berührung wird in Wirklichkeit vielleicht nicht ausgeführt.
  • Beteiligungslimits begrenzen jede Bar auf int(volume * participation); eine Schleife trägt die Restmenge über die Bars.

Als Nächstes: CAPM und Beta, messen, wie viel einer Rendite vom Markt stammt.

Lab: Was bewertet wird

  • Mit fill_market_order das Orderbuch durchlaufen25 Pkt.
  • Mit limit_fill entscheiden, ob das Limit erreicht wird25 Pkt.
  • Mit partial_fill das Volumen beachten25 Pkt.
  • Mit fill_over_bars die Order über die Zeit ausführen25 Pkt.
Explorer · lab-92-1
▾ lab-92-1
…
bash · im Browser
learner@quantcraft:~/lab-92-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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