Cuatro números, todos medidos en nuestro propio stack de paper trading, una estrategia, señales de 1 minuto sobre el perpetuo BTCUSDT, 31 días y 1,418 órdenes. Tiempo mediano desde el cierre de barra hasta el ack de la orden por el exchange: 195 ms. Percentil 99: 2,970 ms. Mediana en el 1% de minutos con mayor volatilidad realizada: 840 ms. Y la constante de latencia que estuvo en la config del backtest durante la mayor parte del año anterior: 0.
Tres de esos números son aburridos. Todo el mundo sabe que el cero está mal, todo el mundo acaba sustituyéndolo por algo, y ese algo es casi siempre una constante que alguien eligió a ojo. 100 ms, 250 ms, «seamos conservadores, 500.» El número que de verdad importa es 840, porque dice que tu latencia es función del estado del mercado, y los estados de mercado en los que se dispara son los mismos en los que tu señal cree haber encontrado algo.
Dónde se van los 195 milisegundos
Aquí va el presupuesto completo, medido etapa por etapa con timestamps de reloj monotónico escritos en cada salto. La máquina es una instancia de AWS en ap-northeast-1, la misma región que los endpoints del venue, que es más o menos lo mejor a lo que llega un setup de perfil retail no colocalizado.
| Etapa | p50 | p95 | p99 |
|---|---|---|---|
| Cierre de barra → evento WS kline-closed recibido | 128 ms | 402 ms | 1,940 ms |
| Parseo + actualización del estado de features | 3 ms | 9 ms | 28 ms |
| Decisión: eval del modelo + controles de riesgo | 11 ms | 22 ms | 60 ms |
| Envío de orden → ack del exchange | 47 ms | 180 ms | 1,100 ms |
| Extremo a extremo (medido, no sumado) | 195 ms | 690 ms | 2,970 ms |
Dos cosas a tener en cuenta antes de la parte interesante. Primero, las medianas no se suman: 128 + 3 + 11 + 47 = 189, y la mediana extremo a extremo medida es 195. Los percentiles no son aditivos, y si construyes tu estimación de latencia sumando los p99 de cada etapa obtendrás 3,128 ms cuando el p99 real es 2,970. Aquí está lo bastante cerca; un disparate cuando las etapas están correlacionadas en la otra dirección. Mide el camino completo.
Segundo, mira la fila de arriba. Dos tercios del presupuesto mediano se van esperando a que el exchange te diga que la barra cerró. No es la red, no es tu código, no es el enrutado de órdenes. El venue agrega trades en una kline, decide que el minuto se acabó y hace push. Ese push tiene una cola delante, y la cola se comparte con todos los demás suscriptores de ese stream.
El 840
Agrupa cada una de esas 1,418 órdenes por la volatilidad realizada del minuto que produjo la señal, y la distribución se descompone.
| Grupo de volatilidad de la barra de señal | Órdenes | p50 extremo a extremo | p99 extremo a extremo |
|---|---|---|---|
| Cuartil inferior | 201 | 141 ms | 488 ms |
| Dos cuartiles centrales | 796 | 183 ms | 1,210 ms |
| Cuartil superior | 407 | 312 ms | 2,880 ms |
| Top 1% de todos los minutos | 14 | 840 ms | 4,100 ms |
Todas las etapas se degradan a la vez, y por eso se acumula. La cola de agregación y broadcast del venue se alimenta de la carga del matching engine, así que un minuto con 11,000 trades se empuja más tarde que un minuto con 600. Tu propio proceso está manejando más actualizaciones de profundidad y más prints de trades en la misma ventana, así que la actualización de features que normalmente tarda 3 ms tarda 28. El camino REST de órdenes está compitiendo con el pánico de todos los demás, y empiezas a ver el ocasional 503-and-retry que por sí solo te cuesta un segundo entero. El coeficiente de correlación entre el recuento de trades de la barra de señal y la latencia extremo a extremo en nuestra muestra fue 0.41. No es enorme. Basta para arruinar una constante.
Y las estrategias que sobreviven a un primer filtro son, de forma abrumadora, las que operan rupturas, reversiones, dislocaciones, cascadas de liquidación. Disparan exactamente en el grupo donde la latencia es peor. Una señal de momentum que solo se activa cuando el minuto se movió 40 bps es una señal que se ha organizado, estructuralmente, para que siempre la atienda la versión más lenta de tu stack.
Una vez nos pasamos un día persiguiendo un outlier de 3.6 segundos que aparecía más o menos a la misma hora cada noche. Era logrotate, haciendo copy-truncate de un archivo de 2 GB en el mismo volumen EBS en el que escribía el proceso, y trabando el event loop. El mercado era inocente. Primero mide, después culpa a la microestructura.
Lo que eso le hace a un fill
El precio deriva mientras esperas. En un minuto aleatorio, el movimiento adverso medio a lo largo de nuestros 195 ms de mediana fue de unos 1.1 bps en contra de la dirección de la señal. En los minutos del cuartil superior a 312 ms, 5.8 bps. En los minutos del top-1% a 840 ms, unos 14 bps de drift adverso antes de que la orden siquiera llegue al libro.
En los perps de BTC el spread apenas participa en esto: un tick sobre una cotización de 84,000 es 0.012 bps, así que el daño es drift adverso más que coste de cruce. Pasa la misma estrategia a un perp mid-cap y el segundo término se despierta — el spread de top-of-book en nuestra muestra pasó de 1.4 bps en minutos calmados a 6.2 bps en el cuartil superior, y la profundidad en ese toque se adelgazó en más de la mitad. Pagas el drift y el spread más ancho y la peor profundidad, todo a la vez, todo porque comparten una causa.
Cuando reprodujimos los mismos 31 días con latencia condicional por barra en lugar de un 200 ms plano, el precio medio de entrada del backtest empeoró 3.1 bps, concentrado casi por completo en el 9% de las operaciones. La divergencia de precio de entrada backtest-versus-paper bajó de 4.2 bps a 0.9 bps. El Sharpe in-sample de esa estrategia pasó de 1.7 a 1.1, que es el número honesto y siempre lo fue.
Entonces, ¿qué pones realmente en la config?
No un escalar. Lo que ejecutamos ahora:
- Muestrea, no fijes. Extrae la latencia de cada orden simulada de una distribución empírica condicionada a la propia actividad de esa barra — el recuento de trades y el retorno absoluto bastan, y ambos ya están en una kline estándar. Ajústala una vez por venue y por tipo de orden, reajusta mensualmente.
- Conserva la cola. No ajustes una lognormal y lo des por hecho; el p99 vive en tormentas de reintentos y pausas de GC que ninguna distribución suave reproduce. Usamos los cuantiles empíricos con una cola remuestreada por encima del p95.
- La latencia también aplica a los cancels. Un reemplazo de stop o un cancel de cobertura está sujeto al mismo retraso, y en mercados rápidos tu cancel está compitiendo con un fill. Si tu simulador cancela al instante, tu modelo de riesgo es ficción.
- Añade un guard de caducidad y simúlalo. El nuestro descarta cualquier señal cuya barra tenga más de 1.5 segundos de antigüedad al llegar. Eso es un comportamiento real con un coste real — elimina operaciones en silencio, y tiene que eliminar las mismas en el backtest.
- Recalibra contra paper. El paper trading es donde obtienes la ground truth. Registra los cuatro timestamps de salto en cada orden y compara las distribuciones con lo que asumió el simulador, semanalmente.
Otras clases de activo, la misma enfermedad. Acciones estadounidenses: la cinta consolidada añade su propio retraso de agregación encima del de tu bróker, y se ensancha bajo presión de message-rate por la misma razón estructural. Mercados de predicción: entrada de órdenes solo por REST en la mayoría de venues, y hemos medido medianas sub-100 ms que pasan a varios segundos cuando llega un evento de resolución y todo el mundo aparece a la vez. Opciones cripto: la cotización de la que partes puede llevar dos segundos de retraso exactamente en el minuto en que se movió el subyacente.
La forma general del error es tratar un parámetro de ejecución como una constante independiente cuando es función de la misma variable de estado que impulsa tu señal. Las comisiones se comportan; el funding se comporta; la latencia, no. Si de todo esto te vas a llevar un número en la cabeza, llévate el ratio: nuestro p99 es quince veces nuestra mediana, y nuestra señal llega de forma desproporcionada cerca del extremo del p99.
Instrumenta los cuatro saltos. Es una tarde de trabajo y te dirá más sobre tu estrategia que otra semana de búsqueda de parámetros.
← Todos los artículos


