σμ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 11 · Produktivsysteme und Spitzenmodelle›Thema 11.4·~1 Std.Experte

TWAP-Ausführung

Position in der SkillModul 11 von 11 · Thema 4 von 13
11.4 TWAP-Ausführung
—Lab-Punkte— / 100XP gesamt—Serie—

Warum nicht alles auf einmal senden

Kaufen Sie 200.000 Aktien mit einer einzigen Market-Order, und Sie fressen sich durch das Orderbuch: Die ersten Aktien werden zum besten Ask ausgeführt, die nächsten zu einem schlechteren Preis, und so weiter, und jeder, der Sie kaufen sieht, hebt seine Preise an. Dieser Marktimpact ist ein echter Kostenfaktor, oft größer als die Gebühr. Ein Ausführungsalgorithmus zerlegt die Order in kleinere Child-Orders, die über die Zeit gesendet werden, sodass jede mit weniger Impact aufgenommen wird. Der einfachste ist TWAP, der zeitgewichtete Durchschnittspreis-Algorithmus: Man teilt die Menge in gleiche Teile und sendet zu jedem von gleichmäßig verteilten Zeitpunkten zwischen Start und Ende einen davon.

# Splitting 10 shares into 3 child orders: whole shares, earlier pieces take the extra
def twap_schedule(total, slices):
    size, extra = divmod(total, slices)
    return [size + (1 if index < extra else 0) for index in range(slices)]

print(twap_schedule(10, 3))                          # [4, 3, 3]
print(twap_schedule(200_000, 8))                     # [25000, 25000, 25000, 25000, 25000, 25000, 25000, 25000]
print(sum(twap_schedule(10_001, 7)))                 # 10001   nothing is lost to rounding

Der Plan: wie viel und wann

Ein TWAP-Plan hat zwei Teile. Die Größen teilen die Gesamtmenge in n Teile ganzer Aktien, die sich um höchstens eine Aktie unterscheiden und genau die Order ergeben: divmod(total, n) liefert die Basisgröße und wie viele Teile eine Aktie mehr bekommen. Die Zeiten sind n gleichmäßig zwischen Start und Ende verteilte Startzeiten: start + i * (end - start) / n. Eine ganztägige Order über 200.000 Aktien in 40 Teilen sind 5.000 Aktien alle zehn Minuten, gesendet von einem Scheduler wie dem aus dem vorigen Thema. Echte Implementierungen randomisieren Größen und Zeiten ein wenig, da ein perfekt regelmäßiges Muster für andere leicht zu erkennen und auszunutzen ist.

# When each slice starts: a trading day from 09:30 to 16:00 in 13 half-hour slices (seconds since midnight)
def slice_times(start, end, slices):
    step = (end - start) / slices
    return [start + index * step for index in range(slices)]

times = slice_times(9.5 * 3600, 16 * 3600, 13)
print(times[0], times[1] - times[0])                 # 34200.0 1800.0   09:30 and a slice every 30 minutes
print(times[-1] / 3600)                              # 15.5             the last slice starts at 15:30, the end (16:00) is not a start time

Messen: durchschnittlicher Ausführungspreis und Slippage

Sind die Teile ausgeführt, ist der durchschnittliche Ausführungspreis der mengengewichtete Mittelwert der Fill-Preise, sum(price * quantity) / sum(quantity): Ein großer Fill zählt mehr als ein kleiner, ein einfacher Mittelwert der Preise wäre also falsch. Um das Ergebnis zu beurteilen, vergleichen Sie es mit dem Ankunftspreis, dem Marktpreis im Moment der Entscheidung. Die Differenz ist der Slippage, angegeben in Basispunkten (1 bp sind 0,01 %): bei einem Kauf (Durchschnitt - Ankunft) / Ankunft * 10.000, bei einem Verkauf das umgekehrte Vorzeichen, sodass eine positive Zahl stets Kosten bedeutet. Das ist der Kern des Implementation Shortfall, der Standardmethode, eine Ausführung zu bewerten.

# Average fill price (quantity-weighted) and slippage against the arrival price, in basis points
def average_fill_price(fills):
    return sum(price * quantity for price, quantity in fills) / sum(quantity for _, quantity in fills)

def slippage_bps(avg_price, arrival_price, side):
    sign = 1 if side == "buy" else -1
    return sign * (avg_price - arrival_price) / arrival_price * 10000

fills = [(100.0, 400), (100.2, 300), (100.4, 300)]
average = average_fill_price(fills)
print(round(average, 2), sum(price for price, _ in fills) / 3)      # 100.18 100.2   the plain mean of the prices is not the answer
print(round(slippage_bps(average, 100.0, "buy"), 2))                # 18.0   a buy that averaged 100.18 against an arrival of 100.00 cost 18 bp
print(round(slippage_bps(average, 100.0, "sell"), 2))               # -18.0  the same prices would have been a gain for a seller
# A toy run: the price drifts up while we buy 10 slices; the slippage is what the drift cost us
prices = [100.00, 100.03, 100.05, 100.04, 100.08, 100.10, 100.09, 100.12, 100.15, 100.14]     # price at each slice time
pieces = [100] * 10                                                                         # TWAP: equal child orders

arrival = prices[0]
fills = list(zip(prices, pieces))
average = sum(p * q for p, q in fills) / sum(pieces)
print(round(average, 4))                             # 100.08
print(round((average - arrival) / arrival * 10000, 1))      # 8.0   bp of slippage for buying into a rising market
Was vorhersehbar ist, ist ausnutzbarTWAP ignoriert den Markt: Es handelt dieselbe Menge in ruhigen wie in hektischen Momenten, und sein regelmäßiger Fußabdruck kann erkannt und vorweggenommen werden. Es ist eine vernünftige Basis, wenn Sie keine Meinung zum Volumen haben und Einfachheit wollen. Verbesserungen sind das nächste Thema: der Tagesvolumenkurve folgen (VWAP), Ihren Anteil am Volumen jedes Intervalls deckeln, Größen und Zeiten randomisieren und anhalten oder bremsen, wenn der Preis davonläuft. Vergleichen Sie den Slippage des Algorithmus stets an denselben Tagen mit einem einfachen Benchmark, bevor Sie ihm vertrauen.
  • Große Orders bewegen den Preis; ein Ausführungsalgorithmus sendet kleinere Child-Orders über die Zeit. TWAP sendet gleiche Teile zu gleichmäßig verteilten Zeiten.
  • Größen: divmod(total, n) mit den Extra-Aktien in den ersten Teilen; Zeiten: start + i * (end - start) / n.
  • Bewerten Sie eine Ausführung nach ihrem mengengewichteten Durchschnittspreis gegenüber dem Ankunftspreis in Basispunkten; eine positive Zahl sind Kosten.

Als Nächstes: VWAP-Ausführung, dem Tagesvolumen statt der Uhr folgen.

Lab: Was bewertet wird

  • Jedes Teilstück mit twap_schedule bemessen25 Pkt.
  • Die Teile mit slice_times zeitlich verteilen25 Pkt.
  • Mit average_fill_price Ihre Fills mitteln25 Pkt.
  • Die Kosten mit slippage_bps beziffern25 Pkt.
Explorer · lab-133-1
▾ lab-133-1
…
bash · im Browser
learner@quantcraft:~/lab-133-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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