Lección 3.3.1 · 60 min
Microestructura FX: OTC, ECN, last look y sesiones
En divisas no hay una bolsa ni un libro único: cada proveedor de liquidez cotiza por su cuenta y quien recibe los precios arma su propio libro. Esta lección reconstruye ese libro con cinco proveedores ficticios en tres sesiones, mide el last look de cada uno orden a orden y calcula lo que cuesta de verdad operar con ellos, más allá de la horquilla que enseñan.
- Módulo
- 3.3 · Forex avanzado
- Duración
- 60 min
Lecciones del nivel 3
3.1 · Futuros en profundidad
3.2 · Spreads de futuros
- 3.2.1 Spreads de calendario, butterflies y condors
- 3.2.2 Spreads intercommodity: crack, spark y crush
- 3.2.3 Spreads de tipos y de índices: 2s10s, NOB, NQ/ES y Europa frente a EE. UU.
- 3.2.4 Ratios de cobertura: por nominal, por DV01 y por volatilidad
- 3.2.5 Datos y backtesting de spreads: cotizados, sintéticos y por patas
- 3.2.6 Estacionalidad de spreads: análisis multi-año, patrones y trampas
3.3 · Forex avanzado
3.4 · Teoría y valoración de opciones
- 3.4.1 Payoffs, paridad put-call y límites de arbitraje
- 3.4.2 Árboles binomiales, Black-Scholes-Merton, Black-76 y Monte Carlo
- 3.4.3 Griegas: delta, gamma, vega, theta, rho, vanna, volga y charm
- 3.4.4 Volatilidad implícita: Newton-Raphson, Brent, py_vollib y QuantLib
- 3.4.5 Sonrisa, skew y estructura temporal; superficie de volatilidad con SVI
- 3.4.6 Volatilidad realizada frente a implícita; prima de riesgo de volatilidad; VIX y VSTOXX
- 3.4.7 Modelos avanzados: Heston, SABR y volatilidad local
3.5 · Estructuras de opciones en Python
- 3.5.1 Estructuras direccionales y verticales: call, put, covered call, collar y spreads
- 3.5.2 Estructuras de volatilidad y rango: straddles, strangles, cóndores y mariposas
- 3.5.3 Calendarios, diagonales, ratios, backspreads, risk reversals y jade lizard
- 3.5.4 Herramienta propia: payoff, griegas agregadas y escenarios
- 3.5.5 Gestión: ajustes, roll, cierre anticipado, asignación temprana y pin risk
3.6 · Estrategias sistemáticas de volatilidad y opciones
3.7 · Cripto derivados y estrategias específicas
Un mercado sin libro central
La lección 1.2.4 presentó el mercado de divisas como un mercado OTC que sigue al sol de Sídney a Nueva York. Aquí interesa su mecánica fina: quién pone los precios, cómo llegan al cliente y qué pasa entre que el cliente pulsa «comprar» y la operación queda hecha. En una bolsa (lección 1.1.3) hay un libro de órdenes central con reglas públicas: una orden que cruza el mejor precio se ejecuta, sin más. En divisas al contado no existe ese libro único. Hay muchos proveedores de liquidez (liquidity providers, LP) que publican precios a sus clientes por canales distintos, y una parte importante de esos precios no es firme: el proveedor se reserva una última mirada antes de aceptar.
Fuente Mermaid
flowchart TB B[LP bancarios] --> ID[Interbancario] B --> MD[Multidealer y ECN] N[LP no bancarios] --> MD B --> SD[Plataforma propia] MD --> AG[Agregador] SD --> AG AG --> C[Fondo o CTA] AG --> R[Bróker minorista] R --> M[Minorista]
- Proveedores de liquidez. Grandes bancos y, cada vez más, empresas no bancarias de creación de mercado electrónica. Cotizan compra y venta de forma continua y ganan la horquilla; su riesgo es la selección adversa (lección 2.3.6): que les ejecuten justo antes de que el precio se mueva.
- Mercado interbancario. Los bancos operan entre sí, a menudo en plataformas con un libro central de órdenes firmes. Ahí sí hay algo parecido a una bolsa, pero solo para participantes con acuerdos de crédito entre ellos.
- Plataformas multidealer y ECN. Reciben precios de varios proveedores y los distribuyen a los clientes. En una ECN (electronic communication network) cada proveedor publica su flujo de precios; el cliente ve todos y elige.
- Plataforma propia (single-dealer). Cada gran banco tiene la suya, con sus precios para sus clientes.
- Agregador. El programa del cliente (o de su bróker) que junta los flujos de varios proveedores, construye un libro y decide a quién mandar cada orden. El libro que ve un fondo no lo ve nadie más: depende de con quién tiene acuerdos.
- Brókeres minoristas. Toman precios de uno o varios proveedores, añaden su margen y los ofrecen a sus clientes; algunos internalizan el flujo (son la contraparte) y otros lo pasan al mercado.
Que no haya libro central tiene una consecuencia práctica para quien hace backtests: no hay un precio oficial. El EURUSD de un proveedor de datos es el de sus fuentes, y dos fuentes no coinciden a la décima de pip (lección 1.3.8).
Cuánto y con quién
La referencia para medir el mercado es la encuesta trienal que los bancos centrales hacen cada tres años, coordinados por el Banco de Pagos Internacionales (BPI). En abril de 2025 participaron 52 países. El Banco de España publica la parte española1Nota 1 · Banco de España, Encuesta trienal sobre los mercados OTC de divisas y de derivados de tipos de interés en España (2025) y nota de prensa del 30 de septiembre de 2025, consultadas el 22/10/2026.:
| Mercado español de divisas, abril de 2025 | Volumen medio diario |
|---|---|
| Total | 67,9 miles de millones de USD (39,2 en abril de 2022) |
| FX swaps | 44,8 miles de millones (66 %) |
| Contado | 11,8 miles de millones (17 %) |
| Con otras entidades declarantes (bancos) | 53 % |
| Con otras instituciones financieras | 41 % |
| Con clientes no financieros | 6 % |
| Con contrapartidas extranjeras | 94 % |
Dos datos de la tabla sirven para entender el resto de la lección. El contado, lo que opera un sistema de trading en divisas, es una parte minoritaria del volumen: la mayor parte son FX swaps, la herramienta de financiación y de cobertura de la lección 3.3.3. Y casi la mitad del volumen ya no es entre bancos: lo negocian otras instituciones financieras, la categoría en la que entran los fondos y los creadores de mercado no bancarios.
Cinco proveedores, tres sesiones
Los datos de esta lección son de QEVUSD, el par de un evro ficticio que imita al EURUSD, el 12 de marzo de 2025:
una hora en cada apertura, Tokio (00:00–01:00 UTC, etiquetada asia), Londres (07:00–08:00) y Nueva York
(13:00–14:00). Hay un precio de referencia que nadie ve y cinco proveedores que lo cotizan, cada uno con su latencia,
su horquilla y su política de last look. Son datos sintéticos con los parámetros plantados en
fx3_lp_verdad.csv: la lección los mide como si no los conociera y al final los compara.
import numpy as np
import pandas as pd
cot = pd.read_parquet("fx3_ecn_cotizaciones.parquet")
print(len(cot), "cotizaciones de", cot["lp"].nunique(), "proveedores")
cot.head(4)193244 cotizaciones de 5 proveedores
ts sesion lp bid ask tam_bid tam_ask
0 2025-03-12 00:00:00.175000+00:00 asia LP-Borea 1.473744 1.473916 1000000 1000000
1 2025-03-12 00:00:00.278000+00:00 asia LP-Atlas 1.473716 1.473944 3000000 1000000
2 2025-03-12 00:00:00.311000+00:00 asia LP-Delta 1.473798 1.473862 3000000 1000000
3 2025-03-12 00:00:00.360000+00:00 asia LP-Delta 1.473798 1.473862 5000000 2000000Cada fila es una actualización de precio de un proveedor: su compra (bid), su venta (ask) y la cantidad en firme
en cada lado, entre 1 y 5 millones de evros. Las marcas de tiempo tienen milisegundos, que en divisas es una
resolución gruesa: un proveedor rápido actualiza varias veces por segundo. Por proveedor y sesión:
PIP = 1e-4
cot["spread"] = (cot["ask"] - cot["bid"]) / PIP
spread = cot.pivot_table(index="lp", columns="sesion",
values="spread", aggfunc="median")
ritmo = cot.groupby(["lp", "sesion"]).size().unstack() / 3600
pd.concat({"spread_pips": spread, "cotiz_por_s": ritmo},
axis=1).round(2) spread_pips cotiz_por_s
sesion asia londres nueva_york asia londres nueva_york
lp
LP-Atlas 2.02 1.26 1.26 1.09 2.94 3.29
LP-Borea 1.66 1.04 1.04 1.40 4.00 4.39
LP-Cirro 0.92 0.58 0.58 2.09 6.01 6.57
LP-Delta 0.74 0.46 0.46 1.73 4.99 5.43
LP-Eris 1.28 0.80 0.80 1.37 3.99 4.40Los dos bancos más clásicos, LP-Atlas y LP-Borea, cotizan horquillas de 1,26 y 1,04 pips en Londres; los dos no
bancarios, LP-Cirro y LP-Delta, de 0,58 y 0,46. En la hora de Tokio todas las horquillas son un 60 % más anchas y
el ritmo de actualización cae a menos de la mitad: el evro se negocia, pero sus grandes centros están cerrados (la
lección 1.2.4 midió el mismo patrón hora a hora en el EURUSD del nivel 1). Londres y Nueva York se parecen entre sí.
La figura pone las horquillas de Tokio y de Londres de cada proveedor junto a la del libro agregado, que se construye
en la sección siguiente. Ya se ve el punto de partida de toda la lección: el proveedor con la horquilla más estrecha
es LP-Delta. Si el precio que enseña fuera el precio al que se ejecuta, la decisión estaría tomada.
El libro agregado: el mejor precio de todos
Un agregador hace lo que hace una bolsa, pero con precios ajenos: para cada instante guarda la última cotización de
cada proveedor y toma el bid más alto y el ask más bajo. El mejor bid y el mejor ask pueden ser de proveedores
distintos. La función de abajo lo hace por sesión con pivot_table y ffill (la última cotización vigente de cada
uno) y guarda cuánto dura cada estado del libro, porque una media por evento daría más peso a los momentos con más
actualizaciones.
def libro_agregado(g):
b = g.pivot_table(index="ts", columns="lp", values="bid",
aggfunc="last").ffill().dropna()
a = g.pivot_table(index="ts", columns="lp", values="ask",
aggfunc="last").ffill().dropna()
libro = pd.DataFrame({"mejor_bid": b.max(axis=1),
"mejor_ask": a.min(axis=1),
"lp_bid": b.idxmax(axis=1)})
libro["spread"] = (libro["mejor_ask"]
- libro["mejor_bid"]) / PIP
t = libro.index.to_series()
libro["dur"] = t.diff().shift(-1).dt.total_seconds()
return libro.dropna()
libros = {s: libro_agregado(g) for s, g in cot.groupby("sesion")}
def resumen(l):
w = l["dur"] / l["dur"].sum() # peso por duración
return pd.Series({
"spread_medio": (w * l["spread"]).sum(),
"cruzado_pct": 100 * w[l["spread"] < 0].sum(),
})
pd.DataFrame({s: resumen(l) for s, l in libros.items()}).T.round(2) spread_medio cruzado_pct
asia 0.70 0.00
londres 0.19 20.01
nueva_york 0.27 11.51En Londres, la horquilla media del libro agregado es de 0,19 pips, menos de la mitad que la del mejor proveedor solo (0,46). Es la ventaja de agregar: el mejor bid y el mejor ask rara vez son del mismo proveedor en el mismo instante. Pero la segunda columna dice algo incómodo: durante el 20 % de la hora de Londres el libro está cruzado, con el mejor bid por encima del mejor ask, y el 11,5 % de la de Nueva York. En Tokio, nunca.
Un libro cruzado parece dinero gratis: comprar al ask de uno y vender al bid de otro. No lo es. Cada proveedor publica el precio de referencia con su propio retraso (5 ms el más rápido, 60 ms el más lento, según el archivo de verdad), y cuando el precio se mueve rápido, como en la apertura de Londres, la cotización del lento se queda atrás y cruza la del rápido. Quien intente aprovecharlo manda una orden contra el precio atrasado, que es justo la que el last look de ese proveedor está diseñado para rechazar. En una bolsa, un libro cruzado no puede existir: las órdenes que se cruzan se ejecutan. En un ECN con precios no firmes, sí.
l = libros["londres"]
cuota = l.groupby("lp_bid")["dur"].sum() / l["dur"].sum()
(100 * cuota).round(1).sort_values(ascending=False)lp_bid
LP-Delta 54.5
LP-Cirro 24.7
LP-Eris 10.7
LP-Borea 5.7
LP-Atlas 4.4
Name: dur, dtype: float64LP-Delta tiene el mejor bid el 54,5 % del tiempo y LP-Cirro el 24,7 %: entre los dos, casi el 80 %. Un agregador
que mande cada orden al mejor precio le dará a Delta más de la mitad del flujo. Por eso importa tanto lo que hace
Delta con las órdenes que recibe.
Last look: la última mirada del proveedor
El FX Global Code, el código de buenas prácticas del mercado de divisas que mantiene el Comité Global de Divisas (GFXC) de los bancos centrales, define el last look en su Principio 17 como una práctica de la negociación electrónica en la que el participante que recibe una solicitud de operación tiene una última oportunidad de aceptarla o rechazarla en función del precio cotizado2Nota 2 · GFXC, FX Global Code, última actualización de diciembre de 2024, Principio 17; versión en español del Banco de España, que traduce last look como «último vistazo».. El cliente manda una orden contra un precio publicado; el proveedor la retiene unos milisegundos, comprueba y decide.
Fuente Mermaid
stateDiagram-v2 [*] --> Cotiza Cotiza --> Solicitud: orden del cliente Solicitud --> Retencion: ventana Retencion --> Ejecutada: pasa Retencion --> Rechazada: no pasa Rechazada --> Cotiza: pedir de nuevo Ejecutada --> [*]
El Código no prohíbe la práctica, pero la acota:
- Si se usa, debe ser un mecanismo de control de riesgos para verificar la validez (que los datos de la operación sean correctos y haya crédito suficiente) y el precio (que el precio solicitado siga siendo coherente con el que podría obtener el cliente en ese momento).
- El proveedor debe explicar, como mínimo, si las variaciones del precio en un sentido u otro influyen en su decisión, cuánto tarda en decidir y para qué usa el last look.
- No se puede usar para obtener información sin intención de aceptar, y el proveedor no puede negociar durante la ventana (ni ajustar precios ni cubrirse) con la información de la solicitud.
El informe del grupo de trabajo del GFXC de agosto de 2021 añade dos precisiones útiles para medir3Nota 3 · GFXC, Execution Principles Working Group Report on Last Look, agosto de 2021, secciones 2 y 5.. La primera, la distinción entre comprobación simétrica (la misma tolerancia alrededor del precio actual en los dos sentidos: rechaza si el precio se ha movido más que la tolerancia, a favor o en contra del proveedor) y asimétrica (acepta cuando el precio se ha movido a favor del proveedor y rechaza cuando se ha movido en su contra). La segunda: incorporar cualquier retraso adicional al necesario para hacer las comprobaciones se considera contrario al Principio 17. El mismo informe señala como posibles indicios de mal uso las tasas de rechazo altas con tiempos de respuesta largos y elementos asimétricos, y los tiempos de respuesta distintos entre aceptaciones y rechazos.
Medir el last look orden a orden
fx3_ecn_ordenes.parquet son 2.266 órdenes IOC (ejecutar ya o cancelar) de un cliente a los cinco proveedores, de 1
a 5 millones de evros. Cada orden trae el precio solicitado, las horas de envío y de respuesta, el estado y el precio de
referencia al enviar y al responder (mid_envio, mid_respuesta), algo que un cliente real no tiene: tendría que
estimarlo con el medio del libro agregado. Lo primero es el signo: para una compra, que el precio suba durante la
retención es bueno para el cliente y malo para el proveedor; para una venta, al revés.
ords = pd.read_parquet("fx3_ecn_ordenes.parquet")
signo = np.where(ords["lado"] == "compra", 1, -1)
ords["retencion_ms"] = (ords["ts_respuesta"] - ords["ts_envio"]
).dt.total_seconds() * 1000
# movimiento durante la retención: + = a favor del cliente
ords["mov"] = (signo * (ords["mid_respuesta"] - ords["mid_envio"])
/ PIP).round(1)
ords["rechazada"] = ords["estado"] == "rechazada"
por_lp = ords.groupby("lp").agg(
ordenes=("rechazada", "size"),
rechazo_pct=("rechazada", "mean"),
retencion_ms=("retencion_ms", "median"))
por_lp["rechazo_pct"] *= 100
por_lp.round(1) ordenes rechazo_pct retencion_ms
lp
LP-Atlas 290 1.7 4.0
LP-Borea 328 14.6 43.0
LP-Cirro 496 12.9 59.0
LP-Delta 820 27.7 152.0
LP-Eris 332 9.9 33.0LP-Delta rechaza el 27,7 % de las órdenes y tarda una mediana de 152 ms en responder; LP-Atlas, el 1,7 % en
4 ms. LP-Delta es además el que más órdenes recibe (820), porque es el que más veces tiene el mejor precio. La
retención medida es la plantada más la latencia de red, de 1 a 3 ms: 4, 43, 59, 152 y 33 ms frente a 2, 40, 60, 150 y
30 plantados.
La tasa de rechazo sola no distingue entre una comprobación justa y una que no lo es. Lo que la distingue es cuándo rechaza cada uno: con el precio quieto, cuando se ha movido a favor del cliente o cuando se ha movido a favor del proveedor.
ords["contexto"] = np.select(
[ords["mov"] > 0.05, ords["mov"] < -0.05],
["contra_lp", "a_favor_lp"], "quieto")
tasa = ords.pivot_table(index="lp", columns="contexto",
values="rechazada", aggfunc="mean")
(100 * tasa).round(1)contexto a_favor_lp contra_lp quieto
lp
LP-Atlas 0.0 NaN 1.7
LP-Borea 59.6 44.2 0.4
LP-Cirro 1.1 74.1 0.9
LP-Delta 0.4 93.4 0.3
LP-Eris 0.0 73.8 0.8La tabla separa las cinco políticas sin necesidad de conocerlas:
LP-Atlas: sin last look. Rechaza el 1,7 % con el precio quieto, nunca por el movimiento (y en 4 ms el precio casi nunca se mueve: no hay órdenes suyas en la columnacontra_lp).LP-Borea: simétrico. Rechaza el 44,2 % cuando el precio se mueve en su contra y el 59,6 % cuando se mueve a su favor. Al cliente le rechaza también operaciones que le habrían salido caras.LP-Cirro,LP-DeltayLP-Eris: asimétricos. Rechazan el 74 %, el 93 % y el 74 % cuando el precio va en su contra, y casi nada (1,1 %, 0,4 % y 0 %) cuando va a su favor.
Con el movimiento exacto se recuperan el umbral y la probabilidad de rechazo:
ords["mov_tramo"] = ords["mov"].clip(-0.3, 0.3)
por_mov = ords.pivot_table(index="mov_tramo", columns="lp",
values="rechazada", aggfunc="mean")
(100 * por_mov.drop(columns="LP-Atlas")).round(0)lp LP-Borea LP-Cirro LP-Delta LP-Eris
mov_tramo
-0.3 69.0 0.0 1.0 0.0
-0.2 40.0 6.0 0.0 0.0
-0.1 62.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0 1.0
0.1 44.0 50.0 94.0 71.0
0.2 38.0 96.0 93.0 70.0
0.3 55.0 82.0 93.0 80.0El precio de referencia se mueve en saltos de 0,1 pips, así que el movimiento solo toma esos valores (los extremos
agrupan todo lo que pasa de ±0,3). LP-Delta, con umbral 0, rechaza el 93–94 % de cualquier movimiento en su contra,
cerca del 95 % plantado. LP-Eris (umbral 0,05) rechaza el 70–80 %, cerca del 70 %. LP-Cirro tiene el umbral en
0,10 pips: con un movimiento de exactamente 0,1 rechaza la mitad (está en la frontera, y la comparación de un
movimiento igual al umbral cae a uno u otro lado por redondeo), y a partir de 0,2 el 82–96 %, cerca del 90 % plantado.
LP-Borea rechaza entre el 38 % y el 69 % a los dos lados: el 60 % plantado, con el ruido de 10 a 24 órdenes por
casilla. La figura lo resume:
Tiempos de respuesta: aceptadas frente a rechazadas
El informe del GFXC señala los tiempos de respuesta distintos entre aceptaciones y rechazos como un posible indicio de mal uso. En los datos se pueden comparar:
ords.pivot_table(index="lp", columns="estado",
values="retencion_ms", aggfunc="median")estado ejecutada rechazada
lp
LP-Atlas 4.0 4.0
LP-Borea 41.0 47.0
LP-Cirro 58.5 79.5
LP-Delta 145.0 173.0
LP-Eris 32.0 38.0Las rechazadas tardan más en los cuatro proveedores con last look: 173 ms frente a 145 en LP-Delta, 79,5 frente a 58,5
en LP-Cirro. En estos datos no hay ninguna retención extra plantada para rechazar: la diferencia sale sola, porque
una retención más larga deja más tiempo para que el precio se mueva y la orden falle la comprobación. Es un buen
recordatorio de que los indicios del informe son indicios: una diferencia de tiempos pide una explicación al proveedor,
no demuestra un abuso. Lo que sí sería una señal clara es que la retención fuera más larga que la que el proveedor
declara.
Lo que cuesta de verdad: horquilla más rechazos
Para comparar proveedores hace falta una medida de coste que incluya los rechazos. Una orden ejecutada cuesta el semi-spread: la distancia entre el precio solicitado y el medio en el momento del envío. Una orden rechazada no cuesta nada en el acto, pero deja al cliente sin la posición y con el precio movido: si el precio subió mientras el proveedor miraba una compra, el cliente tiene que volver a pedir precio desde el nuevo nivel. Ese movimiento perdido es el coste del rechazo. Si el rechazo llega con el precio movido en contra del cliente, el coste es negativo: el proveedor le ha ahorrado una operación mala.
con en las compras y en las ventas y el movimiento del medio durante la retención a favor del cliente, en pips. La medida supone que, tras un rechazo, el cliente vuelve a pagar el mismo semi-spread; ignora el tiempo perdido y el riesgo de que el precio siga moviéndose mientras pide otro precio, así que es una cota inferior del coste real.
ords["semi_spread"] = signo * (ords["precio_solicitado"]
- ords["mid_envio"]) / PIP
ords["coste_rechazo"] = ords["rechazada"] * ords["mov"]
coste = ords.groupby("lp")[["semi_spread", "coste_rechazo"]].mean()
coste["efectivo"] = coste.sum(axis=1)
coste["usd_por_millon"] = 100 * coste["efectivo"]
coste.round(3) semi_spread coste_rechazo efectivo usd_por_millon
lp
LP-Atlas 0.571 0.000 0.571 57.052
LP-Borea 0.502 -0.004 0.499 49.866
LP-Cirro 0.250 0.030 0.280 28.020
LP-Delta 0.199 0.079 0.278 27.807
LP-Eris 0.370 0.024 0.394 39.361Es la figura de la cabecera. El last look de LP-Delta le cuesta al cliente 0,079 pips por orden, un 40 % de su
semi-spread de 0,199. Aun así, su coste efectivo (0,278 pips, unos 28 USD por millón) es la mitad que el de LP-Atlas
(0,571), que no rechaza nada pero cotiza tres veces más ancho. LP-Cirro y LP-Delta quedan empatados, y LP-Eris
paga 0,024 de rechazos sobre un semi-spread de 0,370. La comprobación simétrica de LP-Borea sale gratis de media
(−0,004): rechaza tanto a favor como en contra del cliente.
La conclusión no es «el last look no importa»: es que hay que medirlo. Con estos parámetros y este cliente, la horquilla estrecha compensa los rechazos. Con un cliente distinto, no (ejercicio 2).
El markout: la misma cuenta desde las ejecuciones
Un cliente real no conoce el precio de referencia, pero puede medir lo que se movió el precio de mercado después de cada ejecución: el markout. Si el proveedor filtra las órdenes de forma asimétrica, las ejecuciones que quedan son las que no se movieron o se movieron a favor del proveedor, y el markout medio de las ejecuciones es negativo para el cliente.
ejec = ords[~ords["rechazada"]]
markout = ejec.groupby("lp")["mov"].agg(["mean", "size"])
markout["mean"] = markout["mean"].round(3)
markout mean size
lp
LP-Atlas -0.002 285
LP-Borea 0.003 280
LP-Cirro -0.028 432
LP-Delta -0.097 593
LP-Eris -0.017 299LP-Delta tiene un markout medio de −0,097 pips en sus 593 ejecuciones: el precio se movió en contra del cliente en la
retención, porque las que se habrían movido a su favor fueron rechazadas. LP-Atlas tiene −0,002, como corresponde a
un proveedor que no filtra. LP-Borea, simétrico, tiene +0,003 porque filtra por los dos lados. Si el
precio no tiene tendencia, la suma de los movimientos de todas las órdenes es cero, así que el markout negativo de las
ejecuciones y el coste positivo de los rechazos son el mismo dinero visto desde dos lados. En un análisis de costes
(TCA) real se mide el markout a varios horizontes (100 ms, 1 s, 5 s) con el medio del libro agregado, por proveedor y
por sesión.
Fuente Mermaid
flowchart TB O[Órdenes propias] --> R[Rechazo por mov] O --> T[Tiempos] O --> K[Markout] R --> C[Coste efectivo] K --> C T --> D[Preguntas al LP] C --> E[Reparto del flujo]
Lo que esto cambia en un sistema de trading
- El precio del backtest no es el de la ejecución. Un backtest de divisas con el medio y una horquilla fija supone órdenes firmes. Con last look, una parte de las órdenes no se ejecuta, y las que no se ejecutan son justo las que iban bien. Para una estrategia de baja frecuencia el efecto es pequeño; para una de minutos, puede ser toda la ventaja (lecciones 2.4.7 y 2.4.8).
- La horquilla cotizada no ordena a los proveedores. El coste efectivo, sí. Y depende del flujo de cada cliente: hay que medirlo con las órdenes propias, no con las de otro.
- El libro agregado engaña en los momentos rápidos. Un libro cruzado o una horquilla de 0,05 pips en la apertura de Londres son, en parte, precios atrasados que no se van a ejecutar.
- La sesión importa. En la hora de Tokio el coste efectivo de todos los proveedores casi se duplica (ejercicio 1). Un sistema que opera a cualquier hora debería saber en qué hora ejecuta.
- Pedir los documentos. El Código pide a los proveedores que publiquen su política de last look (simétrica o asimétrica, ventana mínima y máxima). El informe del GFXC propone una hoja de divulgación normalizada. Un cliente institucional puede, y debe, pedirla.
En la lección 3.3.3 se mandan órdenes de verdad a tres brókeres por sus APIs; allí los rechazos aparecen como códigos de respuesta que el programa tiene que tratar.
Ejercicios
- Calcula el coste efectivo por proveedor y sesión. ¿Cuánto más caro es operar en la hora de Tokio que en la de Londres? ¿Cambia el orden de los proveedores?
Solución
ords["efectivo"] = ords["semi_spread"] + ords["coste_rechazo"]
ords.pivot_table(index="lp", columns="sesion",
values="efectivo", aggfunc="mean").round(3)sesion asia londres nueva_york
lp
LP-Atlas 0.992 0.525 0.505
LP-Borea 0.804 0.454 0.451
LP-Cirro 0.445 0.249 0.255
LP-Delta 0.379 0.259 0.256
LP-Eris 0.636 0.356 0.393En Tokio el coste efectivo es casi el doble que en Londres para todos: 0,992 frente a 0,525 pips en LP-Atlas, 0,379
frente a 0,259 en LP-Delta. El orden se mantiene: los no bancarios son los más baratos en las tres sesiones. Con
solo 312 órdenes en Tokio, las diferencias pequeñas (LP-Cirro frente a LP-Delta) no son fiables.
- Imagina un cliente cuyas órdenes anticipan el precio: solo opera cuando el precio va a moverse a su favor en los
milisegundos siguientes. Simúlalo quedándote con las órdenes con
mov > 0y calcula su tasa de rechazo y su coste efectivo por proveedor. ¿Qué proveedor elegiría?
Solución
rapido = ords[ords["mov"] > 0]
t = rapido.groupby("lp").agg(
ordenes=("rechazada", "size"),
rechazo_pct=("rechazada", "mean"),
efectivo=("efectivo", "mean"))
t["rechazo_pct"] *= 100
t.round(2) ordenes rechazo_pct efectivo
lp
LP-Borea 43 44.19 0.53
LP-Cirro 81 74.07 0.45
LP-Delta 241 93.36 0.46
LP-Eris 42 73.81 0.53Para ese cliente, los proveedores asimétricos rechazan casi todo: LP-Delta el 93,4 % y LP-Cirro el 74,1 %. Su
coste efectivo sube de 0,28 a 0,46 pips en LP-Delta y de 0,28 a 0,45 en LP-Cirro. LP-Atlas no tiene órdenes en
la muestra (con 4 ms de retención el precio no llega a moverse), pero como no rechaza, le costaría su semi-spread,
0,57 pips. Por esta medida LP-Delta sigue siendo algo más barato, y sin embargo este cliente no lo elegiría: solo
ejecuta el 7 % de sus órdenes, y la medida solo cuenta el movimiento durante la retención, no el que el cliente espera
capturar después. Si su ventaja es mayor que unas décimas de pip, lo que necesita es que le ejecuten, y paga con gusto
la horquilla de un precio firme; por eso los proveedores de precios firmes cotizan más ancho. Es la selección adversa
de la lección 2.3.6 vista desde el otro lado: el last look es la forma en que el proveedor se protege de este
cliente.
- Un proveedor te dice que su comprobación de precio es simétrica, con una tolerancia de 0,05 pips y una ventana de hasta 50 ms. Con las órdenes que le has mandado, ¿qué tres medidas de esta lección usarías para comprobarlo?
Solución
Primero, la tabla de rechazo por contexto: una comprobación simétrica rechaza en una proporción parecida cuando el
precio se mueve a favor y en contra del proveedor (como LP-Borea), y casi nada con el precio quieto. Segundo, la
distribución de la retención: la mediana y los percentiles altos deben estar dentro de los 50 ms declarados, y la
diferencia entre aceptadas y rechazadas debe explicarse por la duración (las retenciones largas se rechazan más) y no
por un retraso añadido a los rechazos. Tercero, el markout de las ejecuciones: con una comprobación simétrica debe ser
cercano a cero; uno claramente negativo indicaría que, en la práctica, filtra de forma asimétrica.
Footnotes
-
Banco de España, Encuesta trienal sobre los mercados OTC de divisas y de derivados de tipos de interés en España (2025) y nota de prensa del 30 de septiembre de 2025, consultadas el 22/10/2026. ↩
-
GFXC, FX Global Code, última actualización de diciembre de 2024, Principio 17; versión en español del Banco de España, que traduce last look como «último vistazo». ↩
-
GFXC, Execution Principles Working Group Report on Last Look, agosto de 2021, secciones 2 y 5. ↩
Respuesta plegada en cada pregunta
Autoevaluación
Según el Principio 17 del FX Global Code, ¿para qué debe usarse el last look?
- APara que el proveedor decida si le interesa la operación a la vista de la intención del cliente
- BComo mecanismo de control de riesgos para verificar la validez de la operación y el precio
- CPara cubrirse en el mercado antes de aceptar la orden
- DPara retener la orden el tiempo que haga falta hasta que el precio mejore
Ver respuesta
Respuesta B. Como mecanismo de control de riesgos para verificar la validez de la operación y el precio
El Código dice que, si se utiliza, el last look será un mecanismo de control de riesgos para verificar la validez y/o el precio. Prohíbe usarlo para obtener información sin intención de aceptar y negociar durante la ventana con la información de la solicitud; el informe del GFXC de 2021 añade que cualquier retraso adicional al necesario para las comprobaciones es contrario al Principio 17.
En los datos, LP-Borea rechaza el 44 % de las órdenes cuando el precio se mueve en su contra y el 60 % cuando se mueve a su favor. ¿Qué tipo de comprobación de precio aplica?
- AAsimétrica
- BSimétrica: rechaza si el precio se ha movido más que la tolerancia en cualquier dirección
- CNinguna: son rechazos de fondo
- DUna mejora de precio
Ver respuesta
Respuesta B. Simétrica: rechaza si el precio se ha movido más que la tolerancia en cualquier dirección
Una comprobación simétrica aplica la misma tolerancia alrededor del precio actual en los dos sentidos. Rechaza también cuando el movimiento perjudica al cliente, que así se libra de una ejecución que le habría costado. Su coste medio por rechazo es casi nulo (−0,004 pips en los datos).
LP-Delta cotiza la horquilla más estrecha (0,46 pips en Londres) pero rechaza el 27,7 % de las órdenes. ¿Cómo se compara con LP-Atlas, sin last look y con 1,26 pips?
- ADelta es más caro, porque rechaza mucho
- BAtlas es más barato, porque nunca rechaza
- CDelta sigue siendo más barato: su semi-spread de 0,20 pips más 0,08 de coste de los rechazos dan 0,28, frente a 0,57 de Atlas
- DNo se pueden comparar sin saber el tamaño de las órdenes
Ver respuesta
Respuesta C. Delta sigue siendo más barato: su semi-spread de 0,20 pips más 0,08 de coste de los rechazos dan 0,28, frente a 0,57 de Atlas
El coste efectivo suma el semi-spread pagado y, en las órdenes rechazadas, el movimiento a favor del cliente que se pierde al tener que volver a pedir precio. En los datos, el last look de Delta cuesta 0,08 pips por orden, un 40 % de su semi-spread, pero no basta para que Atlas sea más barato. Con un flujo que anticipa el precio (ejercicio 2) la cuenta cambia.
El libro agregado de Londres está cruzado (mejor bid por encima del mejor ask) el 20 % del tiempo. ¿Qué indica?
- AUna oportunidad de arbitraje sin riesgo
- BUn error en los datos
- CQue las cotizaciones de cada proveedor llegan con latencias distintas: unas reflejan el precio de hace 5 ms y otras el de hace 60 ms, y en un mercado rápido se cruzan
- DQue los proveedores coluden
Ver respuesta
Respuesta C. Que las cotizaciones de cada proveedor llegan con latencias distintas: unas reflejan el precio de hace 5 ms y otras el de hace 60 ms, y en un mercado rápido se cruzan
Cada LP publica su precio con su retraso. Cuando el precio de referencia se mueve, el más lento queda atrasado y su cotización puede cruzar la de otro más rápido. Quien intente cruzar las dos se encuentra con el last look del proveedor atrasado: un precio que no es firme no es un arbitraje.
Las ejecuciones de un proveedor con last look asimétrico tienen un markout medio negativo para el cliente. ¿Por qué?
- APorque cobra comisiones ocultas
- BPorque las órdenes en las que el precio se movió a favor del cliente se rechazaron: solo se ejecutan las que no se movieron o se movieron a favor del proveedor
- CPorque las ejecuciones se hacen a un precio peor que el solicitado
- DPor azar
Ver respuesta
Respuesta B. Porque las órdenes en las que el precio se movió a favor del cliente se rechazaron: solo se ejecutan las que no se movieron o se movieron a favor del proveedor
En los datos las ejecuciones son siempre al precio solicitado. El sesgo viene de qué se ejecuta: el filtro asimétrico quita las órdenes que habrían ganado y deja las demás. El markout de las ejecuciones y el coste de los rechazos son dos caras del mismo dinero.
Ideas clave
- Las divisas se negocian OTC: cada proveedor de liquidez publica su precio por separado y el libro que ve el cliente lo construye él o su agregador. En España, según el Banco de España, el 94 % del volumen de abril de 2025 fue con contrapartidas extranjeras.
- El libro agregado es más estrecho que cualquier proveedor (0,19 pips de media en Londres frente a 0,46 del mejor), pero está cruzado el 20 % del tiempo por las distintas latencias: no todo precio visible es firme.
- El last look es una última oportunidad del proveedor para aceptar o rechazar. El FX Global Code lo admite como control de validez y de precio, exige explicar si se aplica de forma simétrica o asimétrica y prohíbe usarlo para obtener información.
- En los datos se recuperan los parámetros plantados: retención mediana de 4, 43, 59, 152 y 33 ms (2, 40, 60, 150 y 30 más 1–3 ms de red), rechazo del 93 % en LP-Delta cuando el precio va en su contra y del 0,4 % cuando va a su favor.
- La comparación correcta entre proveedores es el coste efectivo: semi-spread más coste de los rechazos. LP-Delta, con la horquilla más estrecha, cuesta 0,28 pips por orden; LP-Atlas, sin last look, 0,57.
- El resultado depende del flujo: un cliente cuyas órdenes anticipan el precio ve rechazos mucho más frecuentes y caros. El análisis de costes (TCA) por proveedor, con markouts y rechazos, es la única forma de saberlo.