σμ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 AcademyParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Parcours
AO
+1,2 k apprenants
Connexion
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Parcours Python›Module 11 · Systèmes de production et modèles de pointe›Sujet 11.5·~1 hExpert

Exécution VWAP

Position dans le parcoursModule 11 sur 11 · Sujet 5 sur 13
11.5 Exécution VWAP
—Score du lab— / 100XP total—Série—

Négocier quand le marché négocie

Le prix moyen pondéré par les volumes est le prix moyen de tout ce qui s'est échangé, chaque transaction pesant selon sa taille : sum(price * volume) / sum(volume). C'est le benchmark le plus courant du trading institutionnel car c'est ce qu'un participant moyen a payé ce jour-là. Un algorithme VWAP cherche à l'égaler ou le battre en négociant *proportionnellement au volume du marché* : beaucoup quand le marché est actif (l'ouverture, la clôture), peu quand il est calme (l'heure du déjeuner). Là où le TWAP suit l'horloge, le VWAP suit la foule : chacun de vos ordres est une fraction similaire de ce que font les autres et déplace moins le prix.

# 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

Un profil de volume et un calendrier qui le suit

On ne peut pas connaître à l'avance le volume du jour : un algorithme VWAP utilise donc un profil de volume estimé sur l'historique, la part moyenne du volume de la journée échangée dans chaque intervalle sur, disons, les 20 dernières séances. Le volume intrajournalier a typiquement une forme en U, fort à l'ouverture et à la clôture. Le calendrier donne alors à chaque intervalle total * part actions. Ce sont rarement des entiers, et arrondir chacun peut faire perdre ou gagner des actions. La méthode du plus grand reste règle cela : donnez à chaque intervalle la partie entière, puis distribuez les actions restantes, une chacune, aux intervalles ayant les plus grandes parties fractionnaires, pour que le calendrier totalise toujours l'ordre.

# 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

Limites de participation et suivi de la référence

Un calendrier est un plan ; le marché peut être plus calme que ce que le profil prévoyait. Un plafond de participation limite vos échanges dans chaque intervalle à une fraction du volume réel du marché dans cet intervalle, disons 10 %, pour que vous ne deveniez jamais l'essentiel du flux. Les actions que vous n'avez pas pu négocier sont reportées aux intervalles suivants, ce qui peut en laisser d'inexécutées à la fin ; vous décidez alors de prendre plus de risque, d'étendre la fenêtre ou d'arrêter. Après la journée, comparez votre prix moyen au VWAP du marché : l'écart, en points de base, est l'erreur de suivi de l'algorithme. Battre le VWAP en négociant tard dans un marché haussier n'est pas de l'habileté ; jugez un algorithme à son glissement sur de nombreux jours.

# 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
Le VWAP est un benchmark, pas un objectifÉgaler le VWAP signifie que vous avez négocié comme le participant moyen, ce qui peut être un mauvais résultat si votre propre ordre a poussé le prix (vos transactions font partie du VWAP auquel vous êtes comparé). Vérifiez aussi l'algorithme face au prix d'arrivée, testez le profil sur des jours où il n'a pas été estimé, et attendez-vous à ce que les profils échouent les jours de nouvelles, les demi-journées et les rééquilibrages d'indice. Gardez un journal lisible de chaque ordre enfant pour l'analyse ultérieure.
  • Le VWAP est sum(price * volume) / sum(volume), le benchmark courant ; un algorithme VWAP négocie proportionnellement au volume du marché.
  • Estimez un profil de volume sur l'historique et répartissez l'ordre selon lui par la méthode du plus grand reste pour que les actions entières totalisent exactement l'ordre.
  • Plafonnez votre participation dans chaque intervalle et reportez le reste ; jugez l'algorithme à son erreur de suivi et à son glissement sur de nombreux jours.

À suivre : la tenue de marché, coter les deux côtés et gérer l'inventaire qui en résulte.

Lab : ce qui est noté

  • Calculer la référence avec vwap25 pts
  • Modeler la journée avec volume_profile25 pts
  • Répartir l'ordre avec vwap_schedule25 pts
  • Respecter le marché avec cap_participation25 pts
Explorateur · lab-134-1
▾ lab-134-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-134-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-134-1 revient aux fichiers de départ et le terminal est vidé. Votre solution actuelle sera perdue : cette action est irréversible.

Sera réinitialisé
  • main.py → code de départ
  • Historique du terminal et sortie des tests
  • Modifications non soumises
Sera conservé
  • Meilleur score du lab
  • Votre XP et votre série
  • Progression du cours et notes

Connectez-vous pour exécuter votre code.

Tous les cours sont gratuits à lire. Créez un compte ou connectez-vous pour exécuter du code, lancer les tests et soumettre ce lab.

  • IDE dans le navigateur avec terminal bash — rien à installer
  • Correction instantanée, XP et votre place dans le parcours
Créer un compteSe connecter
OU
Continuer avec GitHub