No puedo hablar de los mercados de criptomonedas, sin embargo en los lugares de mercado convencionales, nunca he visto que se haga en el lado del mercado. Lo que estás pensando se suele implementar en el lado del cliente como una comprobación de riesgo previa a la operación.
Enfoque 1: Idempotencia estricta (para dos llamadas cualesquiera con los mismos parámetros, devuelve el mismo estado de posición)
Esta es la solución más ingenua. Puede almacenar todo el historial de todos los nuevos pedidos realizados como una matriz de structs que contenga los parámetros del pedido y la correspondiente matriz de estados de posición alcanzados. Cuando se realiza una nueva orden, se itera a través de ella para comprobar si hay alguna orden pasada que coincida, y si es así, se compara el estado de posición pasado alcanzado con el estado de posición teórico.
Por el contrario, esa idempotencia estricta no es una solución pragmática, porque en la práctica, hay muchos tipos de estrategias que en realidad pretenden colocar dos solicitudes de órdenes idénticas y consecutivas para doblar una posición.
He aquí un ejemplo ingenuo: Usted tiene una señal de impulso que activa su estrategia para cruzar el spread por N lotes. Usted se llena para N, y posteriormente otras 10 operaciones le siguen para agotar el nivel a algún tamaño M < N. En igualdad de condiciones, su señal de impulso probablemente se ha hecho más fuerte debido a las operaciones autocorrelacionadas, y además, ahora hay una prioridad de cola agresiva que puede conseguir cruzando de nuevo por N al mismo precio, por lo que la cantidad residual (N-M) de su orden se convierte en el nuevo tope.
Otro problema de la idempotencia estricta es que resulta costoso para una comprobación previa a la negociación comparar su orden con todo anteriores con los mismos parámetros - y usted no quiere que una comprobación previa a la negociación ralentice la ruta crítica de una orden saliente.
Otra cuestión es que la nueva orden que se está evaluando podría tener deslizamientos, lo que significa que no tiene forma de saber con certeza el estado teórico alcanzado cuando se libera esa orden.
Enfoque 2: estrangulamiento de pedidos
Lo más probable es que lo que quiera es simplemente evitar que una estrategia errante explote enviando órdenes duplicadas en un bucle cerrado. Esto puede lograrse sin una idempotencia estricta. Una solución práctica es definir algunos límites de tasa. Aquí hay algunos ejemplos con generalidad decreciente:
- Ordenar acciones por segundo
- Nuevas acciones de pedido por segundo
- Acciones de pedido de aumento de posición por segundo
- Acciones de nuevas órdenes por segundo por (símbolo, precio)
- Acciones de nuevas órdenes por segundo por (símbolo, precio, tamaño)
Los dos primeros tipos son muy utilizados.
La tercera tiene la ventaja de que no estrangulará las situaciones en las que se apresure a desprenderse de su inventario, pero es quizás menos común porque tiende a quedar subsumida por otra lógica de liquidación.
Las dos últimas tienen la ventaja de ser mejores aproximaciones a la "idempotencia", ya que todavía se está haciendo algún esfuerzo para comprobar los parámetros (símbolo, precio, tamaño) que hacen que una orden sea única. Sin embargo, debido al gran espacio de posibles combinaciones de parámetros de órdenes, una comprobación de comparación completa es cara y poco práctica.
Para la implementación de estos límites de tarifa, dos heurísticos comunes son que (i) normalmente hay límites de tarifa a nivel de mercado o a nivel de sesión que debe tratar como más suelto límites que los tuyos, (ii) quieres estimar las tasas en un algoritmo eficiente y amortizado de O(1). Hay muchas variantes de tales algoritmos, algunos utilizando un cubo de tiempo ingenuo, otros aproximando la tasa con un ajuste de decaimiento exponencial.
Enfoque 3: Comprobar la existencia de dos veces consecutivas y duplicadas pedidos
La comprobación de dos órdenes consecutivas y duplicadas tiene la ventaja de ser más sencilla de calcular que un límite de velocidad real, a la vez que garantiza un rendimiento de tiempo constante.
Hay un ejemplo ingenuo en el que esta comprobación falla: algunas estrategias errantes colocan órdenes duplicadas en ciclos separados, por ejemplo (AAPL, +100), (SBUX, +100), (AAPL, +100), (SBUX, +100), ...
Enfoque 4: Comprobar la existencia de dos duplicados cualesquiera pedidos por encima de algunos intervalo definido por el usuario
Para resolver el problema de los ciclos separados manteniendo un rendimiento razonable, se podría definir un tiempo máximo de separación para comprobar si hay dos pedidos duplicados. Esto tiene algunas ventajas de implementación: (i) permite limitar el tiempo de ejecución de la comprobación del riesgo, ya que no hay que comprobar dos órdenes que se colocan con una gran diferencia de tiempo, (ii) es fácil de intuir, ya que los mercados suelen tener tiempos predecibles de orden a orden.
El inconveniente de este enfoque es que tiene un perfil de memoria lineal.
Método 5: Hashing y comparaciones parciales
Un problema con los enfoques 3 y 4 es que una comparación a nivel de bits de todos los parámetros de orden de una ventana de órdenes pasadas puede ser demasiado lenta para su caso de uso. Tampoco hemos abordado el problema del uso de la memoria para el enfoque 4.
Podrías mejorar los enfoques 3 y 4 comparando sólo los bits más significativos de los parámetros, o haciendo un hash de los parámetros de la orden y comparando sólo los hashes dentro de la ventana de tiempo.
La desventaja de este enfoque es que podría terminar con falsos positivos. Sin embargo, esto puede no ser un problema para ciertas clases de estrategias de alta frecuencia que son robustas a un puñado de rechazos de órdenes cada pocos días.