σμ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 9 · Datos de mercado y microestructura›Tema 9.1·~1 hAvanzado

El libro de órdenes limitadas

Posición en la rutaMódulo 9 de 11 · Tema 1 de 5
9.1 El libro de órdenes limitadas
—Puntuación del lab— / 100XP total—Racha—

Donde se forman los precios

Un precio en pantalla es el resultado de una cola. En una bolsa, compradores y vendedores colocan órdenes limitadas: «comprar 300 a 99,50», «vender 200 a 100,00». Las que no se ejecutan quedan en el libro de órdenes: las ofertas de compra (bids), la mejor al precio más alto, y las de venta (asks), la mejor al precio más bajo. Una operación ocurre cuando una orden entrante se encuentra con una en espera. Todo lo que los temas anteriores llaman precio, diferencial, deslizamiento e impacto sale de esta estructura.

# A side of the book as a dict {price: total size}
bids = {99.5: 300, 99.4: 500, 99.0: 1200}
asks = {100.0: 200, 100.1: 400, 100.5: 800}

best_bid, best_ask = max(bids), min(asks)
print(best_bid, best_ask)                                 # 99.5 100.0
print(round(best_ask - best_bid, 2), (best_bid + best_ask) / 2)   # the spread 0.5 and the mid 99.75

Diferencial, precio medio y profundidad

El mejor bid y el mejor ask son la cima del libro. Su diferencia es el diferencial (spread), el precio de operar al instante: un comprador que toma el ask y revende al bid pierde el diferencial. A medio camino está el precio medio, la referencia habitual de un precio justo. La profundidad es el tamaño en espera en cada nivel y más allá, y dice cuánto puede operarse antes de que el precio se mueva. Un lado vacío significa que no hay precio en ese lado, así que diferencial y medio quedan indefinidos: None, no cero.

def best_bid_ask(bids, asks):
    return (max(bids) if bids else None, min(asks) if asks else None)

def spread_and_mid(bids, asks):
    bid, ask = best_bid_ask(bids, asks)
    if bid is None or ask is None:
        return None, None
    return ask - bid, (bid + ask) / 2

print(spread_and_mid({99.5: 300, 99.4: 500}, {100.0: 200, 100.1: 400}))      # (0.5, 99.75)
print(spread_and_mid({}, {100.0: 200}))                                       # (None, None): one side is empty

Añadir órdenes sin cambiar el pasado

Una nueva orden limitada se une a un nivel de precio existente, sumando a su tamaño total, o abre un nivel nuevo. Escribirlo como una función que devuelve un dict nuevo en lugar de modificar el anterior tiene una ventaja práctica: se conserva una instantánea del libro antes de la orden, útil para probar y reproducir. Copia con dict(side), cambia la copia, devuélvela. Una función que modifica en silencio su argumento es una fuente clásica de errores cuando el mismo libro se usa en dos sitios.

def add_limit_order(side, price, size):
    new = dict(side)                                   # a copy: the original book is not touched
    new[price] = new.get(price, 0) + size
    return new

bids = {99.5: 300, 99.4: 500}
after = add_limit_order(bids, 99.5, 100)               # joins the existing level
after = add_limit_order(after, 99.3, 50)               # opens a new level
print(after)                                           # {99.5: 400, 99.4: 500, 99.3: 50}
print(bids)                                            # {99.5: 300, 99.4: 500}  unchanged

Casar una orden de mercado

Una compra de mercado toma los asks desde el precio más bajo hacia arriba: todo el primer nivel, luego el segundo, hasta que la orden se llena o el libro se vacía. Recorre los precios ordenados, toma min(left, size_at_price) en cada uno, registra la ejecución y borra el nivel (tomado entero) o redúcelo (tomado en parte). La lista de ejecuciones da el precio medio visto en el tema de ejecuciones, y el libro restante es el mercado tras tu operación: más delgado arriba, con peor mejor ask.

def match_market_buy(asks, size):
    remaining = dict(asks)
    fills = []
    left = size
    for price in sorted(asks):                          # cheapest first
        if left <= 0:
            break
        take = min(left, asks[price])
        fills.append((price, take))
        left -= take
        if take == asks[price]:
            del remaining[price]                        # the level is used up
        else:
            remaining[price] = asks[price] - take
    return fills, remaining

asks = {100.0: 200, 100.1: 400, 100.5: 800}
fills, remaining = match_market_buy(asks, 500)
print(fills)                                            # [(100.0, 200), (100.1, 300)]
print(remaining)                                        # {100.1: 100, 100.5: 800}
Los libros reales son colasUn dict de tamaño total por precio oculta la cola: en cada nivel las órdenes se ejecutan por orden de llegada (prioridad precio-tiempo), y el lugar de tu propia orden en esa cola decide si se ejecuta. Los feeds reales también cancelan y modifican órdenes, lo que domina el tráfico de mensajes. El libro agregado de aquí es el modelo correcto para entender profundidad, diferencial e impacto, y el punto de partida del desequilibrio del flujo de órdenes del siguiente tema.
  • Cada lado es un dict {price: size}: el mejor bid es max(bids), el mejor ask min(asks); el diferencial es ask - bid, el medio su promedio, y ambos son None si un lado está vacío.
  • Añada una orden copiando el dict, sumando en el precio y devolviendo la copia; el libro recibido queda sin cambios.
  • Una compra de mercado recorre los asks ordenados, tomando min(left, size) por nivel, borrando los agotados y reduciendo los tomados en parte; los libros reales tienen además una cola en cada nivel.

A continuación: el desequilibrio del flujo de órdenes, leer la presión del libro para anticipar el próximo movimiento del precio.

Lab: qué se califica

  • Hallar la cima del libro con best_bid_ask25 pts
  • Medir la brecha con spread_and_mid25 pts
  • Dejar una orden en el libro con add_limit_order25 pts
  • Consumir las ventas con match_market_buy25 pts
Explorador · lab-112-1
▾ lab-112-1
…
bash · en el navegador
learner@quantcraft:~/lab-112-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-112-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