Lección 224 min60 XPGratis
Los tipos de orden y qué hace cada uno en el libro
Al terminar sabrás
- Distinguir orden de mercado, límite, stop y stop-límite por cómo interactúan con el libro
- Saber qué orden da certeza de ejecución y cuál da certeza de precio, y por qué no puedes tener ambas
- Elegir el tipo de orden y la validez (TIF) adecuados para entrar, salir y proteger
Antes de esta conviene haber hecho Quién está al otro lado de tu orden.
Hay dos cosas que puedes pedirle a una orden: que se ejecute seguro, o que se ejecute a un precio concreto. No puedes pedir las dos. Toda la zoología de tipos de orden (mercado, límite, stop, stop-límite, OCO, IOC...) son formas distintas de repartir ese compromiso, y elegir mal es una de las fugas de dinero más silenciosas que hay.
El problema
La mayoría opera con dos botones, "comprar" y "vender", que suelen ser órdenes de mercado. Es la forma más cara de operar. Y luego pone un stop "de protección" sin saber que un stop es una orden de mercado en diferido, que se ejecuta exactamente cuando la liquidez es peor. Esta lección abre la caja y te enseña qué hace cada orden dentro del libro, con un simulador que puedes ejecutar.
Tres capas
Intuición
Vuelve al mercadillo de la bici de M0.1.
- Orden de mercado: "Quiero una bici ya, al precio que sea." Te la llevas seguro, al precio del vendedor más barato que haya en ese instante, y si quieres varias, cada una un poco más cara. Certeza de ejecución, cero control del precio.
- Orden límite: "Compro una bici si alguien me la vende por 99,50 o menos." Escribes tu papel y lo dejas en la pila. Si algún vendedor baja a 99,50, te la llevas a ese precio. Si no baja, te vas sin bici. Certeza de precio, cero certeza de ejecución. Y hay más papeles antes que el tuyo en la pila: los que llegaron antes cobran antes.
- Orden stop: "Si la bici llega a bajar a 99,60, entonces vende la mía al precio que sea." Es un disparador que, al activarse, se convierte en orden de mercado. Sirve para limitar pérdidas, pero se ejecuta justo cuando el precio corre y hay poca gente, así que casi siempre sales peor que el nivel que pusiste.
- Stop-límite: "Si baja a 99,60, vende, pero no por menos de 99,40." Te protege de salir a cualquier precio; a cambio, si el mercado salta por debajo de 99,40, te quedas dentro con la pérdida corriendo.
Ejemplo numérico
El libro de M0.1 y cuatro órdenes, una detrás de otra. Los números salen del simulador de abajo.
Libro inicial: bids 4 @ 99,75, 10 @ 99,50, 25 @ 99,25; asks 3 @ 100,00, 8 @ 100,25, 20 @ 100,50.
- Pones una límite de compra de 5 @ 99,50. Se coloca en el libro, en el nivel 99,50, detrás de los 10 que ya estaban. El nivel muestra 15. No se ejecuta nada.
- Llega una orden de mercado de compra de 10. Cruza el spread: 3 @ 100,00 y 7 @ 100,25. Precio medio 100,175. Último precio: 100,25.
- Alguien vende 6 a mercado. Se lleva los 4 de 99,75 y 2 de 99,50, pero los 2 de 99,50 son de quien estaba delante de ti, no tuyos. Último precio: 99,50.
- Tenías un stop de venta en 99,60 para proteger un largo. El último precio (99,50) está por debajo de 99,60, así que se dispara y se convierte en orden de mercado: vende 2 @ 99,50. Querías salir a 99,60; sales a 99,50. Medio punto de slippage por diseño, no por mala suerte.
Y tu límite de compra de 99,50 sigue sin ejecutarse: el nivel ha bajado de 15 a 11 contratos, pero los 4 que se fueron eran de otros. Mismo precio, misma orden, posición en la cola distinta.
Formal
En un libro con prioridad precio-tiempo (el mecanismo de CME para ES y la mayoría de sus contratos; algunos productos de tipos usan pro-rata), una orden pasiva se ordena primero por precio (mejor precio primero) y, a igual precio, por instante de llegada (FIFO). Una orden agresora se ejecuta contra la cola del mejor precio del lado contrario, agotándola nivel a nivel.
| Tipo | Qué hace al llegar | Certeza de ejecución | Certeza de precio | Riesgo principal |
|---|---|---|---|---|
| Mercado | Cruza y consume niveles hasta completarse | Total (si hay liquidez) | Ninguna | Slippage por tamaño y por libro vacío |
| Límite | Si cruza el spread, se ejecuta como agresora hasta su precio; el resto se coloca pasivo al final de la cola de su nivel | Ninguna | Total (precio o mejor) | No ejecutarse; selección adversa (te ejecutan justo cuando el precio va a seguir en tu contra) |
| Stop | Inactiva hasta que el último precio (o el bid/ask, según configuración) toca el disparador; entonces se envía como mercado | Alta una vez disparada | Ninguna | Se dispara en el peor momento de liquidez; gaps |
| Stop-límite | Al dispararse se envía como límite al precio indicado | Parcial | Parcial | Quedarte dentro si el precio salta el límite |
| Market-if-touched (MIT) | Como un stop pero en sentido contrario (compra si baja a un nivel) | Alta | Ninguna | Igual que el stop |
Validez (Time in Force): Day (muere al cierre de sesión), GTC (hasta cancelar; CME purga GTC en cada vencimiento y algunos brokers no las soportan), IOC (ejecuta lo que pueda inmediatamente y cancela el resto), FOK (todo o nada inmediato), GTD (hasta fecha). Una límite IOC es la forma de "tomar liquidez pero no más allá de este precio" sin dejar nada en el libro.
Órdenes compuestas: OCO (una cancela la otra): típicamente un take-profit límite y un stop de protección, de modo que al ejecutarse uno se cancela el otro. Bracket: entrada + OCO de salida en una sola instrucción. Estas las gestiona la plataforma o el broker, no la bolsa; si tu plataforma se cae, tu bracket puede desaparecer. Los stops nativos de CME existen (stop y stop-limit de Globex) pero la mayoría de plataformas minoristas los simulan en sus servidores.
Dónde vive cada orden. Las límites pasivas están en el libro de CME y son visibles en la profundidad (agregadas por nivel, sin identificar). Los stops de plataforma no están en el libro: están en el servidor de tu broker. Nadie en el mercado ve tu stop; sí ve el volumen que se ejecuta cuando muchos stops saltan a la vez.
Ejemplo trabajado con código
# pandas 3.0 — Un libro de órdenes con prioridad precio-tiempo y los cuatro tipos de orden básicos
from dataclasses import dataclass, field
from collections import deque
@dataclass
class Orden:
id: str; lado: str; cantidad: int; precio: float | None = None; tipo: str = "limite"; stop: float | None = None
@dataclass
class Libro:
tick: float = 0.25
bids: dict = field(default_factory=dict) # precio -> deque de (id, cantidad) (FIFO: el primero en llegar, primero en ejecutar)
asks: dict = field(default_factory=dict)
ultimo: float | None = None
fills: list = field(default_factory=list)
def mejor_bid(self): return max(self.bids) if self.bids else None
def mejor_ask(self): return min(self.asks) if self.asks else None
def _cruzar(self, o: Orden, limite: float | None):
"""Ejecuta una orden agresora contra el lado contrario, nivel a nivel, respetando el límite si lo hay."""
contra = self.asks if o.lado == "compra" else self.bids
while o.cantidad > 0 and contra:
p = min(contra) if o.lado == "compra" else max(contra)
if limite is not None and ((o.lado == "compra" and p > limite) or (o.lado == "venta" and p < limite)):
break
cola = contra[p]
while o.cantidad > 0 and cola:
oid, q = cola[0]
tomo = min(q, o.cantidad)
self.fills.append((o.id, oid, p, tomo)); self.ultimo = p
o.cantidad -= tomo
if tomo == q: cola.popleft()
else: cola[0] = (oid, q - tomo)
if not cola: del contra[p]
def enviar(self, o: Orden):
if o.tipo == "mercado":
self._cruzar(o, None)
elif o.tipo == "limite":
self._cruzar(o, o.precio) # si cruza el spread, se ejecuta como agresora
if o.cantidad > 0: # el resto se queda en el libro, al final de la cola
(self.bids if o.lado == "compra" else self.asks).setdefault(o.precio, deque()).append((o.id, o.cantidad))
elif o.tipo == "stop": # se activa cuando el último precio toca el stop
pass # (gestionado por el broker/plataforma; ver comprobar_stops)
return o
def comprobar_stops(self, stops: list[Orden]):
"""Un stop de venta se dispara si el último precio <= stop y se convierte en orden de MERCADO."""
disparados = []
for s in stops:
if self.ultimo is not None and ((s.lado == "venta" and self.ultimo <= s.stop) or (s.lado == "compra" and self.ultimo >= s.stop)):
disparados.append(s); self.enviar(Orden(s.id, s.lado, s.cantidad, tipo="mercado"))
return disparados
def mostrar(self, niveles=3):
b = sorted(self.bids, reverse=True)[:niveles]; a = sorted(self.asks)[:niveles]
print(f"{'BID':>18s} | {'ASK':<18s}")
for i in range(niveles):
lb = f"{sum(q for _, q in self.bids[b[i]]):3d} @ {b[i]:8.2f}" if i < len(b) else ""
la = f"{a[i]:8.2f} @ {sum(q for _, q in self.asks[a[i]]):3d}" if i < len(a) else ""
print(f"{lb:>18s} | {la:<18s}")
if __name__ == "__main__":
L = Libro()
# Libro inicial (el de M0.1.1): órdenes límite que aportan liquidez, con su orden de llegada
for oid, lado, q, p in [("b1","compra",4,99.75),("b2","compra",10,99.50),("b3","compra",25,99.25),
("a1","venta",3,100.00),("a2","venta",8,100.25),("a3","venta",20,100.50)]:
L.enviar(Orden(oid, lado, q, p))
print("Libro inicial:"); L.mostrar()
print("\n1) Tú pones una LÍMITE de compra de 5 @ 99.50 -> se coloca detrás de b2 (10 contratos por delante):")
L.enviar(Orden("tu_limite", "compra", 5, 99.50)); L.mostrar()
print("\n2) Llega una MERCADO de compra de 10 -> cruza el spread y consume niveles:")
L.enviar(Orden("m1", "compra", 10, tipo="mercado")); L.mostrar()
print(" fills:", [(f[2], f[3]) for f in L.fills if f[0] == "m1"], "| último:", L.ultimo)
print("\n3) Alguien vende 6 a MERCADO -> se lleva los 4 de 99.75 y 2 de 99.50 (los de b2, que estaba antes que tú):")
L.enviar(Orden("m2", "venta", 6, tipo="mercado")); L.mostrar()
print(" fills:", [(f[2], f[3]) for f in L.fills if f[0] == "m2"], "| último:", L.ultimo)
print("\n4) Tenías un STOP de venta en 99.60 (protección de un largo). Último = 99.50 -> se dispara como MERCADO:")
disparados = L.comprobar_stops([Orden("tu_stop", "venta", 2, tipo="stop", stop=99.60)])
print(" fills del stop:", [(f[2], f[3]) for f in L.fills if f[0] == "tu_stop"], "-> querías salir a 99.60, sales a", L.ultimo)
L.mostrar()
print("\n¿Se ejecutó tu límite de compra @ 99.50? ->", "sí" if any(f[1]=="tu_limite" for f in L.fills) else "no, sigue en cola detrás de b2")Libro inicial:
BID | ASK
4 @ 99.75 | 100.00 @ 3
10 @ 99.50 | 100.25 @ 8
25 @ 99.25 | 100.50 @ 20
1) Tú pones una LÍMITE de compra de 5 @ 99.50 -> se coloca detrás de b2 (10 contratos por delante):
BID | ASK
4 @ 99.75 | 100.00 @ 3
15 @ 99.50 | 100.25 @ 8
25 @ 99.25 | 100.50 @ 20
2) Llega una MERCADO de compra de 10 -> cruza el spread y consume niveles:
BID | ASK
4 @ 99.75 | 100.25 @ 1
15 @ 99.50 | 100.50 @ 20
25 @ 99.25 |
fills: [(100.0, 3), (100.25, 7)] | último: 100.25
3) Alguien vende 6 a MERCADO -> se lleva los 4 de 99.75 y 2 de 99.50 (los de b2, que estaba antes que tú):
BID | ASK
13 @ 99.50 | 100.25 @ 1
25 @ 99.25 | 100.50 @ 20
|
fills: [(99.75, 4), (99.5, 2)] | último: 99.5
4) Tenías un STOP de venta en 99.60 (protección de un largo). Último = 99.50 -> se dispara como MERCADO:
fills del stop: [(99.5, 2)] -> querías salir a 99.60, sales a 99.5
BID | ASK
11 @ 99.50 | 100.25 @ 1
25 @ 99.25 | 100.50 @ 20
|
¿Se ejecutó tu límite de compra @ 99.50? -> no, sigue en cola detrás de b2Fíjate en el paso 4: el stop no falló. Hizo exactamente lo que es: una orden de mercado que se envía tarde. Y en tu límite de compra: sigue ahí, ejecutándose los de delante, sin que tú puedas hacer nada más que esperar o mover el precio (y perder la posición en la cola).
Figura
(Figura estática en SVG.)
El error típico
Usar órdenes de mercado para entrar y stops para salir, en una estrategia de muchas operaciones. Cada entrada paga el spread; cada salida por stop paga el spread más el slippage del momento en que el precio corre. Con un edge de medio tick por operación, esa combinación garantiza perder. La alternativa no es "usar siempre límites", que tampoco funciona porque te ejecutan solo cuando el precio va contra ti y te dejan fuera cuando va a favor. La alternativa es saberlo, medirlo (siguiente lecciones) y diseñar la estrategia con esos costes dentro desde el primer día, eligiendo el tipo de orden según lo que la estrategia necesite en cada momento: entrar seguro cuando la señal es rara y valiosa; ahorrar spread con límites cuando la señal es frecuente y el precio no corre.
Quiz
5 preguntas · se aprueba con 60 %
1.¿Qué orden te da certeza de ejecución sin certeza de precio?
2.Un stop de venta en 99,60 se dispara y ejecuta a 99,50. ¿Qué ha pasado?
3.Pones una límite de compra a 99,50 cuando hay 10 contratos en ese nivel. Se ejecutan 6 contratos en 99,50. ¿Cuántos tuyos?
4.Una límite de compra a 100,30 cuando el mejor ask es 100,00:
5.Tu plataforma se cae con un bracket abierto (entrada ejecutada, stop y take-profit pendientes). ¿Qué pasa con el stop?
0 de 5 respondidas
Ejercicio
Con libro.py, añade la orden stop-límite: al dispararse, se envía como límite al precio limite indicado, en vez de a mercado. Repite el escenario de la lección con un stop-límite de venta 99,60 / límite 99,45 y otro con límite 99,55, y anota qué se ejecuta y qué se queda en el libro en cada caso. Después implementa IOC: una límite que ejecuta lo que puede y cancela el resto en vez de dejarlo en el libro.
Resultado verificable: con límite 99,45, el stop-límite vende 2 @ 99,50 (el mejor bid está dentro del límite); con límite 99,55, no se ejecuta nada porque el mejor bid (99,50) es peor que el límite, y la orden queda como ask a 99,55, con la posición larga aún abierta. Con IOC, la límite de compra de 5 @ 99,50 del paso 1 se cancela entera porque no cruza nada.
Qué te llevas
- Certeza de ejecución o certeza de precio: elige, porque no hay orden que dé las dos.
- Un stop es una orden de mercado en diferido que se envía cuando la liquidez es peor. El slippage no es un fallo, es su diseño.
- Las límites pasivas hacen cola por precio y tiempo. Los que llegaron antes cobran antes, y tu stop no está en el libro: está en tu broker.
Siguiente lección: El libro y la profundidad. Cuántos contratos hay de verdad detrás del precio que ves, qué es una orden iceberg y por qué la cola FIFO decide si tu límite se ejecuta o no.
