---
title: "1.1.3 Libro de órdenes: bid, ask, spread y profundidad"
description: "Cómo se lee un libro de órdenes: bid y ask, horquilla, profundidad, desequilibrio y microprecio, y cómo se reconstruye el L2 a partir de los mensajes L3."
url: "https://pythonparatrading.com/curso-python-trading/nivel-1/libro-de-ordenes-bid-ask-y-profundidad/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-1/libro-de-ordenes-bid-ask-y-profundidad.png"
---

# 1.1.3 · Libro de órdenes: bid, ask, spread y profundidad

> El libro de órdenes es la lista de lo que los demás están dispuestos a comprar y vender, y a qué precio. Esta lección lo lee en sus tres niveles de detalle sobre la sesión de NOVA: el mejor precio, la escalera de diez niveles y los mensajes orden a orden, con los que se reconstruye el libro y se descubre una orden iceberg.

- Curso: [Nivel 1: Datos financieros, mercados y análisis](https://pythonparatrading.com/curso-python-trading/nivel-1/)
- Módulo: 1.1 · Cómo funcionan los mercados
- Duración: 60 min
- Requisitos: [1.1.1 · Participantes y centros de negociación](https://pythonparatrading.com/curso-python-trading/nivel-1/participantes-y-centros-de-negociacion/), [1.1.2 · Sesiones, subastas, festivos y calendarios](https://pythonparatrading.com/curso-python-trading/nivel-1/sesiones-subastas-y-calendarios-de-mercado/)

## Al terminar esta lección

- Leer un libro de órdenes: bid, ask, horquilla en ticks y en puntos básicos, profundidad por nivel y profundidad acumulada.
- Distinguir los datos L1, L2 y L3 por lo que contienen, para qué sirven y qué no enseñan.
- Calcular el desequilibrio del libro y el microprecio, y medir con datos si anticipan el siguiente movimiento del precio medio.
- Reconstruir el libro a partir de los mensajes L3 con prioridad precio-tiempo y comprobar que coincide con las fotos L2.
- Detectar una orden iceberg por sus reposiciones con el mismo identificador.

## Qué es un libro de órdenes

En la negociación continua, cada orden limitada que no se ejecuta al llegar se queda esperando en el **libro de
órdenes**: una lista ordenada de lo que otros participantes están dispuestos a comprar y vender. El libro tiene dos
lados:

- **Bid (compras).** Órdenes de compra ordenadas de mayor a menor precio. El primero es el **mejor bid**: el precio más
  alto que alguien paga ahora mismo.
- **Ask u offer (ventas).** Órdenes de venta ordenadas de menor a mayor precio. El primero es el **mejor ask**: el
  precio más bajo al que alguien vende ahora mismo.

La distancia entre el mejor ask y el mejor bid es la **horquilla** (*spread*). Si alguien quiere comprar ya, paga el
ask; si quiere vender ya, cobra el bid. Por eso la horquilla es el primer coste de operar (lección 1.1.5). El **precio
medio** es el punto entre los dos, y es la referencia habitual de «el precio» en un instante.

Cada **nivel** es un precio con órdenes. Su **tamaño** es la suma de las acciones de todas las órdenes a ese precio.
La **profundidad** es cuánto hay en el libro: en un nivel, en los cinco primeros, a menos de un céntimo del medio… Los
precios van de **tick** en tick, el salto mínimo de precio: en NOVA, como en la mayoría de las acciones de EE. UU., un céntimo.

Los datos de esta lección son el libro visible de NOVA, la acción ficticia de la lección 1.1.1, el 2 de junio de 2025.
Recuerda la simplificación del simulador: hay un único libro visible, el agregado de los centros con libro.

## Tres niveles de detalle: L1, L2 y L3

Los proveedores venden el libro con tres grados de detalle, y cada uno se obtiene agregando el siguiente:

```mermaid
flowchart TB
  L3[L3: cada orden] -->|suma por precio| L2[L2: por nivel]
  L2 -->|solo el primero| L1[L1: mejor precio]
  L3 -->|ejecuciones| T[Operaciones]
```

| Nivel | Qué contiene | En los datos del curso | Para qué sirve |
|---|---|---|---|
| L1 (*top of book*) | Mejor bid y mejor ask con sus tamaños | `nova_cotizaciones.parquet`, una fila por cambio | Horquilla, precio medio, alinear operaciones (1.1.1) |
| L2 (*market by price*) | Varios niveles por lado, con tamaño y número de órdenes | `nova_libro_l2.parquet`, 10 niveles cada 10 s | Profundidad, impacto de una orden grande, desequilibrio |
| L3 (*market by order*) | Cada orden: alta, cancelación, modificación y ejecución, con su identificador | `nova_libro_l3.parquet`, 5 minutos | Cola de prioridad, icebergs, reconstrucción exacta del libro |

Cuanto más detalle, más volumen de datos y más caro (lección 1.3.1). En NOVA, cinco minutos de L3 son 7.241 mensajes:
a ese ritmo, la sesión completa pasaría del medio millón, frente a 129.247 cambios de L1 en todo el día. Para un sistema que opera a diario basta con L1 y
barras; para estudiar costes de ejecución hace falta L2; para modelar la cola o la llegada de órdenes, L3.

## Una foto del libro, nivel a nivel

Las fotos L2 de NOVA tienen una fila por nivel y lado, cada 10 segundos. Esta es la de las 19:00:00 UTC, las 15:00 de
Nueva York, puesta como una escalera: compras a la izquierda, ventas a la derecha.

```python
import numpy as np
import pandas as pd

l2 = pd.read_parquet("nova_libro_l2.parquet")
foto = l2[l2["ts"] == "2025-06-02 19:00:00+00:00"]

bid = foto[foto["lado"] == "bid"].set_index("nivel")
ask = foto[foto["lado"] == "ask"].set_index("nivel")
escalera = pd.concat({
    "bid": bid[["ordenes", "tamano", "precio"]],
    "ask": ask[["precio", "tamano", "ordenes"]],
}, axis=1)
escalera
```
```output
          bid                    ask
      ordenes   tamano precio precio tamano ordenes
nivel
1        36.0  13432.0  52.74  52.75   1870       5
2        44.0   9380.0  52.73  52.76   9900      18
3        41.0   9059.0  52.72  52.77  13280      29
4         5.0   1800.0  52.71  52.78  17322      54
5         2.0    600.0  52.70  52.79  14521      49
6         1.0    100.0  52.69  52.80   5142      30
7         3.0    526.0  52.67  52.81   9303      22
8         1.0    300.0  52.64  52.82   4300      11
9         NaN      NaN    NaN  52.83   1229       8
10        NaN      NaN    NaN  52.84   2252       6
```

La figura de la cabecera dibuja la misma escalera. Se ven varias cosas que no están en un gráfico de precios. El lado
comprador solo tiene ocho niveles en ese instante, y entre 52,69 y 52,67 falta el 52,68: «nivel» es un precio **con órdenes**, no cada tick. El primer nivel de compra
tiene 13.432 acciones repartidas en 36 órdenes; el de venta, solo 1.870 en 5. Y en los diez niveles hay más del
doble de acciones a la venta que a la compra. La foto es un instante: diez segundos después será otra.

Las medidas de L1 salen de los dos primeros niveles:

```python
def medidas_l1(foto):
    b = foto[(foto["lado"] == "bid") & (foto["nivel"] == 1)].iloc[0]
    a = foto[(foto["lado"] == "ask") & (foto["nivel"] == 1)].iloc[0]
    medio = (b["precio"] + a["precio"]) / 2
    horquilla = a["precio"] - b["precio"]
    qb, qa = b["tamano"], a["tamano"]
    return pd.Series({
        "bid": b["precio"], "ask": a["precio"], "medio": medio,
        "horquilla_ticks": round(horquilla / 0.01),
        "horquilla_pb": 1e4 * horquilla / medio,
        "desequilibrio": (qb - qa) / (qb + qa),
        "microprecio": (b["precio"] * qa + a["precio"] * qb)
                       / (qb + qa),
    })

medidas_l1(foto).round(4)
```
```output
bid                52.7400
ask                52.7500
medio              52.7450
horquilla_ticks     1.0000
horquilla_pb        1.8959
desequilibrio       0.7556
microprecio        52.7488
dtype: float64
```

La horquilla es de un tick, 1,9 puntos básicos sobre el precio medio. El **desequilibrio** del primer nivel va de −1
(solo hay venta) a +1 (solo compra):

$$
I = \frac{q_b - q_a}{q_b + q_a}
$$

Aquí vale 0,76: casi todo el primer nivel es compra. El **microprecio** pondera cada precio por el tamaño del lado
**contrario**:

$$
P_{\text{micro}} = \frac{P_b\, q_a + P_a\, q_b}{q_b + q_a}
$$

Con 13.432 acciones esperando a comprar a 52,74 y solo 1.870 vendiendo a 52,75, lo probable es que el ask se agote
antes que el bid, y el precio medio suba medio céntimo. El microprecio, 52,7488, ya está casi en el ask.

## Profundidad acumulada

La pregunta práctica es cuántas acciones se pueden comprar o vender sin alejarse demasiado del precio medio. La
profundidad acumulada la responde: para cada precio, la suma de lo que hay desde el mejor nivel hasta él.

```python
medio = medidas_l1(foto)["medio"]
prof = foto.sort_values(["lado", "nivel"]).copy()
prof["acumulado"] = prof.groupby("lado")["tamano"].cumsum()
prof["distancia_cent"] = (100 * (prof["precio"] - medio).abs()).round(1)
print(prof.groupby("lado")["tamano"].sum().to_string())
prof.pivot(index="nivel", columns="lado",
           values=["distancia_cent", "acumulado"])
```
```output
lado
ask    79119
bid    35197
      distancia_cent       acumulado
lado             ask   bid       ask      bid
nivel
1                0.5   0.5    1870.0  13432.0
2                1.5   1.5   11770.0  22812.0
3                2.5   2.5   25050.0  31871.0
4                3.5   3.5   42372.0  33671.0
5                4.5   4.5   56893.0  34271.0
6                5.5   5.5   62035.0  34371.0
7                6.5   7.5   71338.0  34897.0
8                7.5  10.5   75638.0  35197.0
9                8.5   NaN   76867.0      NaN
10               9.5   NaN   79119.0      NaN
```

*Fig. — Profundidad acumulada del libro de NOVA a las 15:00 de Nueva York: acciones disponibles desde el precio medio hasta cada precio.* Dos curvas escalonadas que parten del precio medio, 52,745. Hacia la derecha, la venta acumulada sube rápido hasta 79.119 acciones en 52,84; hacia la izquierda, la compra acumulada sube hasta 31.871 en tres niveles y después casi no crece, hasta 35.197 en 52,64. Una línea destacada en 20.000 acciones corta la curva de venta en el tercer nivel y la de compra en el segundo.

A menos de 2,5 céntimos del medio hay 31.871 acciones a la compra (tres niveles) y 25.050 a la venta. Más allá, el lado
vendedor sigue engordando mientras el comprador se queda casi plano: en 10 niveles, 35.197 contra 79.119. Una orden de
compra de 20.000 acciones necesitaría los tres primeros niveles de venta; una de venta del mismo tamaño se llenaría con
el primer nivel de compra y parte del segundo. Cuánto cuesta en cada caso es el **impacto** de la orden, que la lección 1.1.4
calcula recorriendo el libro y la 1.1.5 convierte en coste.

<aside class="callout" data-kind="aviso">

El libro visible no es toda la liquidez. Faltan las partes ocultas de las órdenes iceberg, el centro oscuro y el
internalizador (lección 1.1.1), y sobra liquidez que se retira en milisegundos cuando llega una orden grande. La
profundidad de una foto es un límite optimista de lo que se puede ejecutar de golpe.

</aside>

## La horquilla a lo largo de la sesión

En una acción líquida con un precio de unas decenas de dólares, la horquilla suele estar pegada al mínimo, un tick.
Las 2.340 fotos de la sesión permiten ver cuándo se abre:

```python
n1 = l2[l2["nivel"] == 1].pivot(index="ts", columns="lado",
                                values=["precio", "tamano"])
pb, pa = n1[("precio", "bid")], n1[("precio", "ask")]
qb, qa = n1[("tamano", "bid")], n1[("tamano", "ask")]
ticks = ((pa - pb) / 0.01).round()
pbs = 1e4 * (pa - pb) / ((pa + pb) / 2)

hora_ny = n1.index.tz_convert("America/New_York")
tabla = pd.DataFrame({"ticks": ticks.values, "pb": pbs.values,
                      "mas_de_1": (ticks > 1).values}, index=hora_ny)
print(ticks.value_counts().sort_index().to_string())
tabla.resample("30min").mean().round(3)
```
```output
1.0    2252
2.0      87
3.0       1
                           ticks     pb  mas_de_1
ts
2025-06-02 09:30:00-04:00  1.022  1.916     0.022
2025-06-02 10:00:00-04:00  1.039  1.947     0.039
2025-06-02 10:30:00-04:00  1.028  1.925     0.028
2025-06-02 11:00:00-04:00  1.033  1.926     0.028
2025-06-02 11:30:00-04:00  1.044  1.940     0.044
2025-06-02 12:00:00-04:00  1.039  1.933     0.039
2025-06-02 12:30:00-04:00  1.028  1.914     0.028
2025-06-02 13:00:00-04:00  1.056  1.963     0.056
2025-06-02 13:30:00-04:00  1.006  1.883     0.006
2025-06-02 14:00:00-04:00  1.044  1.957     0.044
2025-06-02 14:30:00-04:00  1.022  1.931     0.022
2025-06-02 15:00:00-04:00  1.022  1.940     0.022
2025-06-02 15:30:00-04:00  1.111  2.102     0.111
```

*Fig. — Porcentaje de fotos L2 de NOVA con horquilla de más de un tick en cada media hora del 2 de junio de 2025.* Trece barras, una por media hora de 9:30 a 16:00 de Nueva York. Casi todas entre el 0,6 % y el 5,6 % de las fotos con horquilla de más de un céntimo; la última, de 15:30 a 16:00, destacada, con el 11,1 %.

El 96,2 % de las fotos tiene la horquilla mínima, de un tick. Las demás se reparten por el día, con más frecuencia en
la última media hora, cuando la llegada de órdenes se acelera antes de la subasta de cierre (lección 1.1.2) y los
creadores de mercado ajustan sus cotizaciones. En puntos básicos la horquilla depende del precio: el mismo céntimo es
1,88 puntos básicos con la acción a 53 USD y sería 10 con la acción a 10 USD. Para comparar costes entre activos, la
horquilla se mide en puntos básicos; para entender la mecánica, en ticks.

## ¿Anticipa el libro el siguiente precio?

Si el primer nivel de venta está casi vacío y el de compra lleno, lo siguiente que suele pasar es que el ask se agote
y el precio medio suba. Con las fotos de NOVA se puede medir: para cada foto, el desequilibrio y el cambio del precio
medio hasta la foto siguiente, diez segundos después.

```python
medio_s = (pa + pb) / 2
deseq = (qb - qa) / (qb + qa)
cambio = 100 * (medio_s.shift(-1) - medio_s)   # céntimos
df = pd.DataFrame({"deseq": deseq, "cambio": cambio}).dropna()
df["tramo"] = pd.cut(df["deseq"], [-1, -0.6, -0.2, 0.2, 0.6, 1],
                     include_lowest=True)
print(f"correlación: {df['deseq'].corr(df['cambio']):.2f}")
df.groupby("tramo", observed=True)["cambio"].agg(
    ["mean", "size"]).round(3)
```
```output
correlación: 0.56
                 mean  size
tramo
(-1.001, -0.6] -0.645   599
(-0.6, -0.2]   -0.146   374
(-0.2, 0.2]    -0.036   388
(0.2, 0.6]      0.088   382
(0.6, 1.0]      0.661   596
```

*Fig. — Cambio medio del precio medio de NOVA en los 10 segundos siguientes según el desequilibrio del primer nivel del libro, 2 de junio de 2025.* Cinco barras por tramo de desequilibrio, de −1 a 1. Con el primer nivel muy cargado a la venta, el precio medio baja 0,65 céntimos de media; en los tramos intermedios, −0,15, −0,04 y +0,09; con el primer nivel muy cargado a la compra, sube 0,66 céntimos (destacado).

La relación es clara y casi simétrica: cuando el primer nivel está muy cargado a la venta (desequilibrio por debajo de
−0,6), el precio medio baja de media 0,65 céntimos en los diez segundos siguientes; cuando está muy cargado a la
compra, sube 0,66. La correlación es de 0,56. ¿Por qué el microprecio es mejor estimación del precio «verdadero» que
el medio? Porque ya incorpora esa información. Comparando los dos con el precio medio de la foto siguiente:

```python
micro = (pb * qa + pa * qb) / (qb + qa)
siguiente = medio_s.shift(-1)
ok = siguiente.notna()
for nombre, pred in (("medio", medio_s), ("microprecio", micro)):
    rmse = np.sqrt(((siguiente - pred)[ok] ** 2).mean())
    print(f"{nombre:<12} error cuadrático medio: {100 * rmse:.3f} cent")
```
```output
medio        error cuadrático medio: 0.867 cent
microprecio  error cuadrático medio: 0.736 cent
```

El microprecio reduce el error de predicción del precio medio siguiente de 0,867 a 0,736 céntimos, un 15 %. Son datos
sintéticos, en los que la relación se ha construido de forma limpia; en datos reales también aparece, pero más débil y
a horizontes muy cortos, segundos o menos.

<aside class="callout" data-kind="riesgo">

Que el desequilibrio anticipe el siguiente medio céntimo no es una estrategia. Para aprovecharlo hay que cruzar la
horquilla, que cuesta un céntimo entero, o estar el primero en la cola, que exige velocidad. Por eso es una señal de
ejecución (cuándo enviar una orden que ya se iba a enviar) más que una fuente de beneficio para un sistema minorista.

</aside>

## Prioridad precio-tiempo

Cuando llega una orden agresiva, ¿contra qué orden del libro se ejecuta? En casi todos los mercados de acciones, por
**prioridad precio-tiempo**: primero el mejor precio y, dentro del mismo precio, la orden que llegó antes. Cada nivel
es una cola.

```mermaid
flowchart LR
  C[Compra a mercado] --> A[1.ª, más antigua]
  A --> B[2.ª orden]
  B --> N[Última llegada]
```

Las consecuencias son concretas. Una orden nueva se pone al **final** de la cola de su precio. Reducir el tamaño de
una orden conserva su puesto; aumentarlo o cambiarle el precio equivale a cancelarla y enviar otra, que va al final.
Y una orden limitada en el mejor bid no se ejecuta hasta que se hayan ejecutado o cancelado todas las que tenía
delante. Por eso «el precio tocó mi límite» no significa «mi orden se ejecutó» (lección 1.1.4).

## Del L3 al L2: reconstruir el libro

El fichero L3 tiene los mensajes orden a orden entre las 14:00 y las 14:05 UTC. Las 358 primeras filas, todas con la
marca de las 14:00:00, son la foto inicial: cada orden viva, en orden de prioridad. Después viene un mensaje por
cambio.

```python
l3 = pd.read_parquet("nova_libro_l3.parquet")
print(len(l3), "mensajes")
print(l3["evento"].value_counts().to_string())
l3.iloc[358:364]
```
```output
7241 mensajes
evento
alta            3443
cancelacion     2842
ejecucion        746
modificacion     210
                                  ts  id_orden       evento lado  precio  tamano
358 2025-06-02 14:00:00.111345+00:00  41031081         alta  bid   53.03     200
359 2025-06-02 14:00:00.121651+00:00  41031083         alta  bid   52.99      97
360 2025-06-02 14:00:00.154247+00:00  41030881  cancelacion  ask   53.12     100
361 2025-06-02 14:00:00.178017+00:00  41031084         alta  ask   53.10    1000
362 2025-06-02 14:00:00.209129+00:00  41030590  cancelacion  bid   53.04     200
363 2025-06-02 14:00:00.260941+00:00  41030785  cancelacion  ask   53.13     100
```

Las reglas de cada mensaje: `alta` añade una orden al final de la cola de su precio; `cancelacion` la quita;
`modificacion` deja el **nuevo** tamaño y conserva la prioridad; `ejecucion` resta lo ejecutado y, si llega a cero, la
orden sale. Con un diccionario de Python, que conserva el orden de inserción, eso es todo lo que hace falta para
mantener las colas:

```python
def aplica(libro, m):
    """Aplica un mensaje L3 al libro {id: [lado, precio, tamaño]}."""
    if m.evento == "alta":
        libro[m.id_orden] = [m.lado, m.precio, m.tamano]
    elif m.evento == "cancelacion":
        del libro[m.id_orden]
    elif m.evento == "modificacion":
        libro[m.id_orden][2] = m.tamano      # conserva el puesto
    elif m.evento == "ejecucion":
        libro[m.id_orden][2] -= m.tamano
        if libro[m.id_orden][2] == 0:
            del libro[m.id_orden]

def a_l2(libro, n=10):
    """Agrega las órdenes por precio: el L2 de n niveles."""
    df = pd.DataFrame(list(libro.values()),
                      columns=["lado", "precio", "tamano"])
    g = (df.groupby(["lado", "precio"])["tamano"]
           .agg(tamano="sum", ordenes="size").reset_index())
    bids = g[g["lado"] == "bid"].nlargest(n, "precio")
    asks = g[g["lado"] == "ask"].nsmallest(n, "precio")
    out = pd.concat([bids, asks])
    out["nivel"] = out.groupby("lado").cumcount() + 1
    cols = ["lado", "nivel", "precio", "tamano", "ordenes"]
    return out[cols].reset_index(drop=True)
```

Ahora se reproducen los mensajes en orden y, en cada instante en que hay foto L2 (cada 10 segundos), se compara el
libro reconstruido con la foto. Cada foto incluye todos los mensajes con marca de tiempo menor o igual que la suya:

```python
fotos = pd.date_range("2025-06-02 14:00:00", "2025-06-02 14:05:00",
                      freq="10s", tz="UTC")
libro, iguales, i = {}, 0, 0
mensajes = list(l3.itertuples(index=False))
for t in fotos:
    while i < len(mensajes) and mensajes[i].ts <= t:
        aplica(libro, mensajes[i])
        i += 1
    ref = l2[l2["ts"] == t].drop(columns="ts").reset_index(drop=True)
    iguales += a_l2(libro).equals(ref)
print(f"{iguales} de {len(fotos)} fotos coinciden")
print(len(libro), "órdenes vivas a las 14:05:00")
```
```output
31 de 31 fotos coinciden
345 órdenes vivas a las 14:05:00
```

Las 31 fotos coinciden exactamente: niveles, precios, tamaños y número de órdenes. Es la comprobación que conviene
hacer siempre con un feed L3 propio: si el libro reconstruido se desvía del L2 del proveedor, falta algún mensaje o se
ha aplicado mal una regla. Otra comprobación barata: las ejecuciones del L3 deben sumar el volumen de los centros con
libro en la cinta de operaciones.

```python
op = pd.read_parquet("nova_operaciones.parquet")
ventana = op[(op["ts"] > "2025-06-02 14:00:00+00:00")
             & (op["ts"] <= "2025-06-02 14:05:00+00:00")]
con_libro = ventana["centro"].isin(["PRINCIPAL", "MTF_A", "MTF_B"])
print("L3:", l3.loc[l3["evento"] == "ejecucion", "tamano"].sum())
print("cinta, centros con libro:",
      ventana.loc[con_libro, "tamano"].sum())
print("cinta, todos los centros:", ventana["tamano"].sum())
```
```output
L3: 78705
cinta, centros con libro: 78705
cinta, todos los centros: 134726
```

Las 78.705 acciones ejecutadas contra el libro coinciden con la cinta. El resto del volumen de esos cinco minutos se
cruzó en el oscuro y en el internalizador, que no pasan por el libro: el L3 más completo de una bolsa no enseña toda la
negociación de la acción.

Con el libro reconstruido se ve la cola completa de un nivel, que ningún L2 enseña:

```python
cola = [(oid, o[2]) for oid, o in libro.items()
        if o[0] == "bid" and o[1] == max(
            v[1] for v in libro.values() if v[0] == "bid")]
print("precio:", libro[cola[0][0]][1], "· órdenes:", len(cola),
      "· acciones:", sum(q for _, q in cola))
pd.DataFrame(cola[:5], columns=["id_orden", "tamano"])
```
```output
precio: 53.17 · órdenes: 34 · acciones: 14140
   id_orden  tamano
0  41034369    1078
1  41034404     200
2  41034422     100
3  41034426      62
4  41034433     500
```

La primera orden de la cola tiene 1.078 acciones y se ejecutará antes que ninguna otra a ese precio. Una orden de
compra nueva a 53,17 tendría delante 14.140 acciones: antes de que le toque, alguien tiene que vender todo eso, o las
órdenes de delante cancelarse.

## La orden iceberg

Una **orden iceberg** enseña solo una parte de su tamaño. Cuando la parte visible se ejecuta entera, el sistema repone
otro tramo desde la reserva oculta, con el mismo identificador y al final de la cola. En el L2 solo se ve el tramo
visible. En el L3 la delata la repetición: una orden normal tiene un único `alta`.

```python
altas = l3[l3["evento"] == "alta"].groupby("id_orden").size()
print(altas[altas > 1].to_string())

ice = l3[l3["id_orden"] == altas.idxmax()]
print(ice.groupby("evento")["tamano"].agg(["size", "sum"]).to_string())
print("precio:", ice["precio"].iloc[0], "· lado:", ice["lado"].iloc[0])
print("de", ice["ts"].min().strftime("%H:%M:%S"),
      "a", ice["ts"].max().strftime("%H:%M:%S.%f"))
```
```output
id_orden
41031312    30
           size   sum
evento
alta         30  9000
ejecucion    86  9000
precio: 53.09 · lado: ask
de 14:00:20 a 14:01:31.224465
```

La orden 41031312 vende a 53,09. Aparece 30 veces con 300 acciones (la primera y 29 reposiciones) y se ejecuta en 86
trozos que suman 9.000 acciones, todo lo que tenía, entre las 14:00:20 y las 14:01:31. Quien miraba el L2 veía en
53,09 unos cientos de acciones a la venta; en realidad había 9.000. El efecto en el precio se ve en la cotización:

```python
cot = pd.read_parquet("nova_cotizaciones.parquet").set_index("ts")
tramo = cot["2025-06-02 14:00:10":"2025-06-02 14:02:00"]
tramo.resample("10s").last()
```
```output
                             bid    ask  tam_bid  tam_ask
ts
2025-06-02 14:00:10+00:00  53.08  53.09     3631    13073
2025-06-02 14:00:20+00:00  53.08  53.09    12431    10914
2025-06-02 14:00:30+00:00  53.08  53.09    19151     2361
2025-06-02 14:00:40+00:00  53.08  53.09    26743      653
2025-06-02 14:00:50+00:00  53.08  53.09    32909       71
2025-06-02 14:01:00+00:00  53.08  53.09    37482      259
2025-06-02 14:01:10+00:00  53.08  53.09    41363      259
2025-06-02 14:01:20+00:00  53.08  53.09    38533      249
2025-06-02 14:01:30+00:00  53.09  53.10     7681       54
2025-06-02 14:01:40+00:00  53.11  53.12     6156       89
2025-06-02 14:01:50+00:00  53.13  53.15     3946     4475
2025-06-02 14:02:00+00:00  53.13  53.15     3850     4975
```

*Fig. — Mejor bid y mejor ask de NOVA entre las 14:00 y las 14:02:30 UTC del 2 de junio de 2025, con la orden iceberg de venta en 53,09.* Dos líneas escalonadas. Desde las 14:00 el ask se queda fijo en 53,09 y el bid en 53,08; el tramo de 14:00:20 a 14:01:31 en 53,09, cuando una iceberg de venta de 9.000 acciones que enseña 300 se ejecuta por completo, está destacado. Al agotarse, el ask sube a 53,15 en menos de 30 segundos.

Durante algo más de un minuto, el ask no se mueve de 53,09 aunque el tamaño visible a la venta se reduce a unas
decenas o cientos de acciones y el bid acumula decenas de miles: cada vez que el tramo visible se agota, aparece otro.
Cuando la reserva se termina, a las 14:01:31, el ask pasa de 53,09 a 53,15 en menos de treinta segundos. Para quien compra, la
iceberg es liquidez que no esperaba; para quien estudia el libro, un desequilibrio que «debería» haber movido el
precio y no lo hizo.

## Ejercicios

1. Calcula la horquilla en puntos básicos, el desequilibrio y el microprecio de la foto L2 de las 13:30:00 UTC, la
   primera de la sesión, y compáralos con los de las 15:00 de Nueva York.

**Solución.**

```python
primera = l2[l2["ts"] == "2025-06-02 13:30:00+00:00"]
pd.DataFrame({"13:30 UTC": medidas_l1(primera),
              "19:00 UTC": medidas_l1(foto)}).round(4)
```
```output
                 13:30 UTC  19:00 UTC
bid                53.3400    52.7400
ask                53.3600    52.7500
medio              53.3500    52.7450
horquilla_ticks     2.0000     1.0000
horquilla_pb        3.7488     1.8959
desequilibrio       0.4118     0.7556
microprecio        53.3541    52.7488
```

En la primera foto, justo después de la subasta de apertura, la horquilla es de dos ticks (53,34 a 53,36) y el
libro todavía es fino: 1.200 acciones en el mejor bid y 500 en el mejor ask. El desequilibrio es positivo y el
microprecio queda por encima del medio, como a las 15:00, pero con una horquilla doble. Los primeros segundos de la
sesión continua son los más caros de cruzar.

2. Con el libro reconstruido a las 14:05:00, ¿cuántas acciones tendría delante una orden de venta nueva al mejor ask?
   ¿Y una al segundo nivel de venta?

**Solución.**

```python
asks = sorted({o[1] for o in libro.values() if o[0] == "ask"})
for precio in asks[:2]:
    delante = sum(o[2] for o in libro.values()
                  if o[0] == "ask" and o[1] <= precio)
    print(f"vendiendo a {precio}: {delante} acciones por delante")
```
```output
vendiendo a 53.18: 4654 acciones por delante
vendiendo a 53.19: 37172 acciones por delante
```

A precio igual, la orden nueva va al final de la cola, así que tiene delante todo el nivel: 4.654 acciones en 53,18.
En 53,19 tendría delante 37.172. En el segundo nivel tiene
delante ese nivel entero (32.518 acciones) y además el primero, que se ejecuta antes por tener mejor precio. Cuanto más lejos del
mejor precio, más probable es que la orden no se ejecute nunca si el precio se da la vuelta.

3. Un proveedor te ofrece L1 gratis, L2 por una cuota mensual y L3 por una cuota mucho mayor. Tu sistema opera una
   vez al día, con órdenes de 500 acciones de acciones muy líquidas. ¿Qué nivel necesitas y para qué usarías cada uno?

**Solución.**

Con L1 y barras basta para operar: el tamaño (500 acciones) está muy por debajo de la profundidad típica del primer
nivel, así que el coste es esencialmente media horquilla, y la horquilla sale del L1. Un L2 serviría para comprobar de
vez en cuando que la profundidad sigue siendo suficiente (por ejemplo, en la apertura o en días de noticias) y para
estimar el impacto si el tamaño crece. El L3 no aporta nada a ese horizonte: sirve para modelar colas, icebergs y la
llegada de órdenes, cosas que importan a quien opera en segundos o provee liquidez.

## Autoevaluación

1. El mejor bid de NOVA es 52,74 y el mejor ask 52,75. ¿Cuál es la horquilla en puntos básicos sobre el precio medio?

   - A. 1 punto básico
   - B. Unos 1,9 puntos básicos
   - C. 0,01 puntos básicos
   - D. 19 puntos básicos

   *Respuesta B: Unos 1,9 puntos básicos.* La horquilla es 0,01 USD, un tick. Sobre el precio medio, 52,745, es 0,01 / 52,745 = 0,000190, es decir, 1,90 puntos básicos. En ticks es la mínima posible; en puntos básicos depende del precio de la acción.

2. ¿Qué contiene un dato L2 que no contiene un L1?

   - A. Las operaciones ejecutadas
   - B. El tamaño agregado en varios niveles de precio a cada lado, no solo en el mejor
   - C. El identificador de cada orden
   - D. Quién envió cada orden

   *Respuesta B: El tamaño agregado en varios niveles de precio a cada lado, no solo en el mejor.* L1 es el mejor bid y el mejor ask con sus tamaños. L2 añade los siguientes niveles de precio, cada uno con el tamaño total y, a veces, el número de órdenes. El identificador de cada orden es L3; quién la envió no lo publica ningún nivel.

3. En la foto de las 15:00 de Nueva York, el mejor bid tiene 13.432 acciones y el mejor ask 1.870. ¿Dónde está el microprecio?

   - A. Justo en el punto medio, 52,745
   - B. Cerca del ask, en torno a 52,749
   - C. Cerca del bid, en torno a 52,741
   - D. Por debajo del bid

   *Respuesta B: Cerca del ask, en torno a 52,749.* El microprecio pondera cada precio por el tamaño del lado contrario: bid × tamaño del ask + ask × tamaño del bid, dividido por la suma. Con mucha más compra que venta en el primer nivel, se acerca al ask: el lado delgado es el que está a punto de agotarse.

4. Una orden de venta aparece una y otra vez con el mismo identificador al final de la cola de 53,09, siempre con 300 acciones, cada vez que se ejecuta entera. ¿Qué es?

   - A. Un error del proveedor de datos
   - B. Una orden iceberg: enseña 300 acciones y repone la parte visible desde una reserva oculta
   - C. Un creador de mercado que cancela y vuelve a enviar
   - D. Una orden stop

   *Respuesta B: Una orden iceberg: enseña 300 acciones y repone la parte visible desde una reserva oculta.* Una iceberg tiene una parte visible y una reserva. Al agotarse lo visible, el sistema repone otro tramo con el mismo identificador y lo pone al final de la cola, porque la parte nueva pierde la prioridad temporal. En el L2 solo se ve el tramo visible; en el L3 la delata la repetición del identificador.

5. Llega una orden de compra a mercado de 500 acciones y en el mejor ask hay tres órdenes: A (200, la más antigua), B (100) y C (400). ¿Cómo se reparte?

   - A. Contra C, la más grande
   - B. 200 contra A, 100 contra B y 200 contra C
   - C. A partes iguales entre las tres
   - D. Contra la más reciente

   *Respuesta B: 200 contra A, 100 contra B y 200 contra C.* Con prioridad precio-tiempo, dentro de un mismo precio se ejecuta primero la orden que llegó antes. A se llena entera, luego B, y C se ejecuta por lo que falta (200) y le quedan 200 en el libro, conservando su puesto.

## Ideas clave

- El libro tiene dos lados: compras (bid) ordenadas de mayor a menor precio y ventas (ask) de menor a mayor. La distancia entre los mejores es la horquilla.
- L1 es el mejor precio de cada lado; L2, varios niveles con el tamaño agregado; L3, cada orden con su identificador. Cada nivel se obtiene agregando el siguiente.
- La profundidad dice cuánto se puede ejecutar sin mover mucho el precio, y cambia de un instante a otro: el libro visible de NOVA a las 15:00 tenía 35.197 acciones a la compra y 79.119 a la venta en diez niveles.
- El desequilibrio del primer nivel anticipa el siguiente movimiento del precio medio en los datos de NOVA; el microprecio lo incorpora en una sola cifra.
- La prioridad precio-tiempo decide quién se ejecuta primero. Con los mensajes L3 se reconstruye el libro exacto, y el L2 que se obtiene coincide con las 31 fotos de la ventana.

## Recursos

### Research

- [Liquidez Order Book - Trading Liquidez Agregada](https://pythonparatrading.com/limit-order-book-y-liquidez-de-mercado/) · Research-0008 · 11 min
- [Introducción a la Volatilidad - Liquidez](https://pythonparatrading.com/introduccion-a-la-volatilidad-liquidez/) · Research-0001 · 6 min

### Libros

- [Bouchaud, Bonart, Donier y Gould: Trades, Quotes and Prices. Financial Markets Under the Microscope (Cambridge University Press, 2018)](https://doi.org/10.1017/9781316659335) · doi.org

### Datos

- [Datos del nivel 1: fotos L2 del libro de NOVA (Parquet)](https://pythonparatrading.com/curso/datos/nivel-1/nova_libro_l2.parquet) · Descarga · nova_libro_l2.parquet
- [Datos del nivel 1: mensajes L3 del libro de NOVA (Parquet)](https://pythonparatrading.com/curso/datos/nivel-1/nova_libro_l3.parquet) · Descarga · nova_libro_l3.parquet

Lección anterior: [1.1.2 · Sesiones, subastas, festivos y calendarios](https://pythonparatrading.com/curso-python-trading/nivel-1/sesiones-subastas-y-calendarios-de-mercado/)

Lección siguiente: [1.1.4 · Tipos de órdenes](https://pythonparatrading.com/curso-python-trading/nivel-1/tipos-de-ordenes/)
