← Proyectos

TitaniumBOE-Sim Simulador del protocolo BOE de Cboe

Simulador del lado del exchange para el protocolo binario BOE de Cboe, con matching engine precio-tiempo, bots de trading, REST API, WebSocket y dashboard en un solo JAR.

Stack
Java 21 · Javalin · RocksDB · WebSocket · Docker
Estado
Terminado
Año
2025
AAPL · simulación en el navegador del matching precio-tiempo
spread —

Últimos trades

    Envía una orden y mira cómo se cruza con el libro.

    En el servidor real, el 99 % de las confirmaciones llega en menos de 3,5 ms.

    En el cable, cada orden es un mensaje binario de 56 bytes. Toca un campo para ver cómo se decodifica.

    Mensaje New Order real · 56 bytes

    Price offset 38–45 · 8 bytes

    187,2500 USD

    8 bytes en Little Endian: 0x1C9274 = 1.872.500. Con 4 decimales implícitos queda 187,2500, sin coma flotante en el cable.

    Qué es BOE

    BOE (Binary Order Entry) es el protocolo con el que los participantes envían órdenes a los mercados de opciones de Cboe en EE. UU. No es texto: cada mensaje es una secuencia exacta de bytes en Little Endian, con campos de tamaño fijo, precios con 4 decimales implícitos y campos opcionales que se anuncian con bitfields. Arriba puedes enviar una orden al libro y ver después sus bytes, codificados igual que en el simulador.

    Qué construí

    Un simulador del lado del exchange, escrito a partir de la especificación v2.11.90: acepta conexiones TCP, autentica sesiones, recibe órdenes BOE y las casa en un motor de matching con prioridad precio-tiempo. Alrededor de eso:

    • Tres bots (market maker, trend follower y random trader) que mantienen actividad en el libro.
    • REST API y WebSocket para market data y operaciones.
    • Un dashboard web servido desde el mismo JAR.
    • Persistencia en RocksDB: órdenes, trades y sesiones sobreviven a un reinicio.

    Por dentro

    • Cada conexión TCP corre en su propia virtual thread de Java 21: código de I/O bloqueante, fácil de leer, sin pagar un hilo del sistema operativo por cliente.
    • El matching se sincroniza por símbolo, no de forma global: AAPL y MSFT se casan en paralelo sin bloquearse.
    • Las escrituras a RocksDB van a una cola asíncrona: el cliente recibe su confirmación sin esperar al disco.
    • Los mensajes forman una jerarquía de sealed classes, así que el compilador conoce todos los tipos posibles.

    Qué tan cerca está del spec

    Buena parte coincide byte a byte con la especificación, pero no todo, y las diferencias están documentadas en el repositorio. Los códigos de Cancel y Modify no son los del spec (0x39/0x3A en lugar de 0x45/0x4A), algunos textos se rellenan con espacios en vez de NUL y el heartbeat es más permisivo (10 s / 30 s en lugar de 1 s / 5 s). Esto último es a propósito, para que una pausa del GC o un breakpoint no tumben la sesión. Con un cliente BOE real, cancelar o modificar órdenes fallaría.

    Números medidos

    Con la prueba de carga del repositorio, en un equipo de 16 núcleos y con el servidor recién iniciado en cada corrida:

    • 500 conexiones TCP simultáneas, sin rechazos.
    • P99 del Order Acknowledgment entre 2,7 y 3,5 ms (900 órdenes por corrida, en 10 sesiones).
    • Entre 4.600 y 9.200 peticiones REST por segundo.
    • 347 tests automatizados, todos en verde.

    La P99 se mide después de las fases de conexiones, logins y REST, que calientan el JIT. Midiendo la latencia sola, con el servidor en frío, una corrida llegó a 11,7 ms.

    Al medir descubrí que la propia prueba de carga estaba desactualizada: esperaba los códigos de sesión anteriores y enviaba órdenes para un símbolo que el servidor rechaza, así que los logins y la latencia llevaban tiempo sin medirse. La corregí antes de publicar estas cifras. La fase de memoria sigue sin servir: mide el heap del cliente, no el del servidor, así que no publico ese número.

    El cuello de botella

    El login no llega a la meta que me había puesto (200 por segundo): se queda en unos 50. Cada contraseña se verifica con BCrypt de coste 12, que consume del orden de 200 ms de CPU por intento; con 16 núcleos, el techo ronda los 60 logins por segundo. Es un costo deliberado: bajarlo abarataría un ataque de fuerza bruta.

    Verlo funcionando