σμ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.5·~1 Std.Experte

VWAP-Ausführung

Position in der SkillModul 11 von 11 · Thema 5 von 13
11.5 VWAP-Ausführung
—Lab-Punkte— / 100XP gesamt—Serie—

Handeln, wenn der Markt handelt

Der volumengewichtete Durchschnittspreis ist der Durchschnittspreis alles Gehandelten, jeder Trade nach seiner Größe gewichtet: sum(price * volume) / sum(volume). Er ist der häufigste Benchmark im institutionellen Handel, weil er zeigt, was ein durchschnittlicher Teilnehmer an diesem Tag gezahlt hat. Ein VWAP-Algorithmus versucht, ihn zu erreichen oder zu schlagen, indem er *proportional zum Marktvolumen* handelt: viel, wenn der Markt lebhaft ist (Eröffnung, Schluss), wenig, wenn er ruhig ist (Mittagszeit). Wo TWAP der Uhr folgt, folgt VWAP der Menge, sodass jede Ihrer Orders ein ähnlicher Bruchteil dessen ist, was alle anderen tun, und den Preis weniger bewegt.

# The benchmark: each price counts as much as the volume that traded at it
def vwap(prices, volumes):
    return sum(p * v for p, v in zip(prices, volumes)) / sum(volumes)

prices = [100.0, 101.0, 102.0]
volumes = [100, 300, 600]
print(round(vwap(prices, volumes), 4))               # 101.5     most volume traded near 102, so the VWAP leans that way
print(sum(prices) / len(prices))                     # 101.0     the plain average ignores how much traded at each price

Ein Volumenprofil und ein Plan, der ihm folgt

Das heutige Volumen kennt man nicht im Voraus, deshalb nutzt ein VWAP-Algorithmus ein aus der Historie geschätztes Volumenprofil: den durchschnittlichen Anteil des Tagesvolumens, der in jedem Intervall gehandelt wurde, über etwa die letzten 20 Sitzungen. Das Intraday-Volumen ist typischerweise U-förmig, hoch bei Eröffnung und Schluss. Der Plan gibt jedem Intervall dann total * Anteil Aktien. Das sind selten ganze Zahlen, und jedes einzeln zu runden kann Aktien verlieren oder hinzufügen. Die Methode des größten Rests behebt das: Geben Sie jedem Intervall den abgerundeten Wert und verteilen Sie die übrigen Aktien, je eine, an die Intervalle mit den größten Nachkommaanteilen, sodass der Plan immer die Order ergibt.

# From volumes to a profile, then to whole shares by the largest remainder method
import math

def volume_profile(volumes):
    total = sum(volumes)
    return [v / total for v in volumes]

def vwap_schedule(total, profile):
    exact = [total * share for share in profile]
    shares = [math.floor(value + 1e-9) for value in exact]
    leftover = total - sum(shares)
    for index in sorted(range(len(profile)), key=lambda i: (-(exact[i] - shares[i]), i))[:leftover]:
        shares[index] += 1
    return shares

profile = volume_profile([300, 100, 100, 200, 500, 800])       # a U-shape: busy at the open and the close
print([round(p, 3) for p in profile])                # [0.15, 0.05, 0.05, 0.1, 0.25, 0.4]
print(vwap_schedule(1003, profile))                  # [151, 50, 50, 100, 251, 401]   adds up to 1003
print(sum(vwap_schedule(1003, profile)))             # 1003

Beteiligungsgrenzen und das Verfolgen des Benchmarks

Ein Plan ist ein Plan; der Markt kann ruhiger sein, als das Profil vorhersagte. Eine Beteiligungsgrenze begrenzt Ihren Handel in jedem Intervall auf einen Bruchteil des tatsächlichen Marktvolumens darin, etwa 10 %, sodass Sie nie den Großteil des Flusses ausmachen. Aktien, die Sie nicht handeln konnten, werden auf spätere Intervalle vorgetragen, was am Ende einen Rest unausgeführt lassen kann; dann entscheiden Sie, ob Sie mehr Risiko eingehen, das Fenster verlängern oder aufhören. Vergleichen Sie nach dem Tag Ihren Durchschnittspreis mit dem Markt-VWAP: Die Differenz in Basispunkten ist der Tracking Error des Algorithmus. Den VWAP zu schlagen, indem man spät in einem steigenden Markt handelt, ist keine Kunst; beurteilen Sie einen Algorithmus nach seinem Slippage über viele Tage.

# A participation cap: never more than a fraction of the market's volume, carrying the rest forward
import math

def cap_participation(schedule, market_volumes, rate):
    trades, carry = [], 0
    for scheduled, volume in zip(schedule, market_volumes):
        wanted = scheduled + carry
        done = min(wanted, math.floor(rate * volume + 1e-9))
        trades.append(done)
        carry = wanted - done
    return trades, carry

print(cap_participation([100, 100, 100], [500, 1000, 1000], 0.1))      # ([50, 100, 100], 50)
print(cap_participation([100, 0, 0, 0], [500, 1000, 400, 800], 0.1))   # ([50, 50, 0, 0], 0)   the carry is traded when the market allows it
# Following the clock (TWAP) and following the volume (VWAP) give different average prices on the same day
prices = [100.0, 100.2, 100.1, 100.4, 100.3, 100.5]
volumes = [300, 100, 100, 200, 500, 800]               # busy at the open and the close

market_vwap = sum(p * v for p, v in zip(prices, volumes)) / sum(volumes)
twap_average = sum(prices) / len(prices)                # equal pieces at every time
print(round(market_vwap, 4), round(twap_average, 4))    # 100.33 100.25
print(round((twap_average - market_vwap) / market_vwap * 10000, 1))      # -8.0   a TWAP buy beat the VWAP here, by trading light when volume was heavy
VWAP ist ein Benchmark, kein ZielDen VWAP zu treffen heißt, Sie haben wie der durchschnittliche Teilnehmer gehandelt, was ein schlechtes Ergebnis sein kann, wenn Ihre eigene Order den Preis geschoben hat (Ihre Trades sind Teil des VWAP, mit dem Sie verglichen werden). Prüfen Sie den Algorithmus auch gegen den Ankunftspreis, testen Sie das Profil an Tagen, an denen es nicht geschätzt wurde, und rechnen Sie damit, dass Profile an Nachrichtentagen, Halbtagen und Index-Rebalancings versagen. Führen Sie ein lesbares Protokoll jeder Child-Order für spätere Analysen.
  • VWAP ist sum(price * volume) / sum(volume), der gängige Benchmark; ein VWAP-Algorithmus handelt proportional zum Marktvolumen.
  • Schätzen Sie ein Volumenprofil aus der Historie und teilen Sie die Order mit der Methode des größten Rests darauf auf, damit ganze Aktien exakt aufgehen.
  • Deckeln Sie Ihre Beteiligung in jedem Intervall und tragen Sie den Rest vor; beurteilen Sie den Algorithmus nach Tracking Error und Slippage über viele Tage.

Als Nächstes: Market Making, beide Seiten quotieren und den entstehenden Bestand verwalten.

Lab: Was bewertet wird

  • Den Benchmark mit vwap berechnen25 Pkt.
  • Mit volume_profile den Tag formen25 Pkt.
  • Die Order mit vwap_schedule aufteilen25 Pkt.
  • Den Markt mit cap_participation respektieren25 Pkt.
Explorer · lab-134-1
▾ lab-134-1
…
bash · im Browser
learner@quantcraft:~/lab-134-1$
Python noch nicht geladenPythonLn 1, Col 1Spaces: 4UTF-8

Dieses Thema zurücksetzen?

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