σμ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 AcademyRutas
Ctrl K
AO
+1,2 k estudiantes
Iniciar sesiónUnirse ↗
Rutas
AO
+1,2 k estudiantes
Iniciar sesión
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Ruta de Python›Módulo 11 · Sistemas de producción y modelos de vanguardia›Tema 11.5·~1 hExperto

Ejecución VWAP

Posición en la rutaMódulo 11 de 11 · Tema 5 de 13
11.5 Ejecución VWAP
—Puntuación del lab— / 100XP total—Racha—

Operar cuando opera el mercado

El precio medio ponderado por volumen es el precio medio de todo lo negociado, cada operación ponderada por su tamaño: sum(price * volume) / sum(volume). Es la referencia más común en el trading institucional porque es lo que pagó un participante medio ese día. Un algoritmo VWAP intenta igualarlo o superarlo operando *en proporción al volumen del mercado*: mucho cuando el mercado está activo (la apertura, el cierre), poco cuando está tranquilo (la hora de comer). Donde el TWAP sigue el reloj, el VWAP sigue a la multitud, así que cada una de tus órdenes es una fracción parecida de lo que hacen los demás y mueve menos el precio.

# 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 perfil de volumen y un calendario que lo sigue

No se puede conocer el volumen de hoy por adelantado, así que un algoritmo VWAP usa un perfil de volumen estimado del histórico: la parte media del volumen del día negociada en cada intervalo durante, digamos, las últimas 20 sesiones. El volumen intradía suele tener forma de U, alto en la apertura y el cierre. El calendario da entonces a cada intervalo total * parte acciones. Rara vez son enteros, y redondear cada uno puede perder o añadir acciones. El método del mayor resto lo arregla: da a cada intervalo la parte entera y reparte las acciones sobrantes, una a cada uno, a los intervalos con las mayores partes fraccionarias, de modo que el calendario siempre suma la orden.

# 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

Límites de participación y seguimiento de la referencia

Un calendario es un plan; el mercado puede estar más tranquilo de lo que el perfil predijo. Un tope de participación limita tu negociación en cada intervalo a una fracción del volumen real del mercado en él, digamos el 10 %, para que nunca seas la mayor parte del flujo. Las acciones que no pudiste negociar se trasladan a intervalos posteriores, lo que puede dejar algunas sin ejecutar al final; entonces decides si asumir más riesgo, ampliar la ventana o parar. Tras el día, compara tu precio medio con el VWAP del mercado: la diferencia, en puntos básicos, es el error de seguimiento del algoritmo. Superar el VWAP operando tarde en un mercado alcista no es habilidad; juzga un algoritmo por su deslizamiento durante muchos días.

# 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
El VWAP es una referencia, no una metaIgualar el VWAP dice que operaste como el participante medio, lo que puede ser un mal resultado si tu propia orden empujó el precio (tus operaciones son parte del VWAP con el que te comparan). Comprueba también el algoritmo frente al precio de llegada, prueba el perfil en días en que no se estimó y espera que los perfiles fallen en días de noticias, medias jornadas y rebalanceos de índices. Guarda un registro legible de cada orden hija para el análisis posterior.
  • VWAP es sum(price * volume) / sum(volume), la referencia común; un algoritmo VWAP opera en proporción al volumen del mercado.
  • Estima un perfil de volumen del histórico y reparte la orden según él con el método del mayor resto para que las acciones enteras sumen exactamente.
  • Limita tu participación en cada intervalo y traslada el resto; juzga el algoritmo por su error de seguimiento y su deslizamiento durante muchos días.

A continuación: creación de mercado, cotizar ambos lados y gestionar el inventario resultante.

Lab: qué se califica

  • Calcular la referencia con vwap25 pts
  • Dar forma al día con volume_profile25 pts
  • Repartir la orden con vwap_schedule25 pts
  • Respetar el mercado con cap_participation25 pts
Explorador · lab-134-1
▾ lab-134-1
…
bash · en el navegador
learner@quantcraft:~/lab-134-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-134-1 vuelve a los archivos iniciales y se limpia el terminal. Tu solución actual se perderá: no se puede deshacer.

Se restablecerá
  • main.py → código inicial
  • Historial del terminal y salida de pruebas
  • Cambios sin enviar
Se conservará
  • Mejor puntuación del lab
  • Tu XP y tu racha
  • Progreso de la lección y notas

Inicia sesión para ejecutar tu código.

Todas las clases se pueden leer gratis. Crea una cuenta o inicia sesión para ejecutar código, lanzar las pruebas y enviar este lab.

  • IDE en el navegador con terminal bash — sin instalar nada
  • Corrección instantánea, XP y tu lugar en la ruta
Crear una cuentaIniciar sesión
O
Continuar con GitHub