Los límites de posición, el margen, los límites fat-finger y un kill switch tienen que responder en cada orden antes de que salga del gateway. Así viven esas verificaciones dentro de la ruta de la orden y no al lado: qué estado está en memoria, qué se recalcula de forma incremental y qué pasa tras un reinicio. Las restricciones van primero.
Una orden llega al gateway. Antes de salir hacia el venue, algo tiene que decidir si la cuenta puede enviarla. Esa decisión corre en cada orden, incluida la inmensa mayoría que están perfectamente bien, así que su coste lo paga todo el tráfico normal y no solo los rechazos.
Esa es la restricción que hay que nombrar primero. Una verificación de riesgo colocada en la ruta de la orden es un impuesto sobre la entrada de órdenes. La pregunta de ingeniería no es cómo hacer la verificación inteligente, sino cómo hacerla lo bastante pequeña como para que los traders no la noten, y lo bastante honesta como para que siga rechazando las órdenes que debe rechazar.
El hot path responde exactamente a una pregunta: ¿puede enviarse esta orden ahora mismo, dado lo que sabemos actualmente de esta cuenta? Las verificaciones que responden a esa pregunta se quedan. Las que responden a otra pregunta salen.
Todo lo demás corre al lado de la ruta, sobre el mismo estado, sin retener la orden. Alimenta los límites que el hot path aplica, pero no se interpone entre el trader y el venue.
La línea divisoria es una pregunta, no una categoría. En la ruta: ¿puede salir esta orden? Al lado de la ruta: ¿cuáles deberían ser los límites? Cualquier cosa que responda a la segunda pregunta y aun así bloquee la orden es un error de diseño, por importante que sea la verificación.
El estado que necesita una verificación pre-trade - posiciones actuales, órdenes activas, margen usado y disponible, configuración de límites - vive en la memoria del proceso que toma la decisión. No en una caché delante de una base de datos, ni detrás de una llamada de red. En el proceso.
La razón no es solo la velocidad, aunque una consulta es órdenes de magnitud más cara que una búsqueda en un array local. La razón es la corrección. Una base de datos guarda la posición tal como se escribió. La verificación de riesgo necesita la posición incluyendo las órdenes enviadas hace un momento que aún no se han ejecutado, confirmado ni persistido. Si lees del almacenamiento, compruebas contra un pasado que tu propio flujo ya ha dejado atrás.
En la práctica, eso moldea el proceso como se moldea cualquier componente de baja latencia:
La base de datos es donde se registra la posición. No es donde se conoce la posición.
Un recálculo completo de la exposición y el margen de una cuenta recorre cada posición y cada orden activa. Ese coste crece con el tamaño del libro, lo que significa que la verificación de riesgo se volvería más lenta justo para los clientes que más operan. Por eso el hot path no recalcula. Aplica un delta.
La cuenta lleva agregados corrientes: exposición neta y bruta por instrumento y por grupo, margen usado, nocional en vuelo. Una orden entrante produce un pequeño cambio en esos agregados, los valores cambiados se comparan con los límites y la orden se acepta o se rechaza. El trabajo es proporcional a la orden, no a la cartera.
El recálculo completo sigue existiendo: de forma programada, cuando cambian los parámetros de margen y como autocomprobación periódica frente al resultado incremental. Corre fuera de la ruta, sobre una copia, y su resultado o bien se sustituye o bien se levanta como discrepancia. Un estado incremental que se desvía en silencio del estado real es peor que no tener verificación, así que la comparación no es opcional.
Medida en la ruta de riesgo que construimos, la propia verificación pre-trade se completa en <1 ms. Esa cifra cubre la decisión sobre el estado en memoria, no el recorrido completo de una orden desde el cliente al venue y de vuelta.
Un kill switch se usa precisamente cuando algo ya va mal. Eso descarta construirlo sobre la maquinaria que puede ser justamente lo que falla. Es una ruta aparte, con sus propias reglas.
Parar las órdenes nuevas es la mitad fácil. La mitad difícil es lo que el switch hace con las órdenes que ya están en reposo en el venue: retirar cotizaciones y cancelar órdenes activas tiene que ser posible mientras la ruta de envío está deshabilitada. Esa ruta de cancelación merece sus propias pruebas, porque se ejercita en el peor día y no en uno normal.
El estado en memoria es una vista derivada de un registro duradero. Eso es lo que hace sobrevivible un reinicio. Todo evento que cambia el estado de riesgo - una orden aceptada, una reserva liberada, una ejecución aplicada, un límite cambiado, el switch activado - se añade a un journal en la máquina local antes de actuarse aguas abajo.
El tiempo de recuperación depende entonces de la longitud del journal y de la disponibilidad del drop copy, no del tamaño del libro, y el modo de fallo ante cualquier incógnita es el mismo: negarse a operar la cuenta.
Vale la pena enunciar los límites honestos con claridad, porque deciden si esta arquitectura encaja siquiera:
amBrain construye este tipo de ruta de riesgo pre-trade para brókers y prop firms, con los hot paths escritos en Rust. El equipo trabaja en infraestructura de trading desde Ereván, Armenia, desde 2019.
Nuestro equipo de ingeniería se especializa en soluciones de FinTech. Hablemos de cómo podemos hacer realidad tu proyecto.