Volver al blog

ProCat Solutions

Bots cripto después de Web3: rate limits, kill switch y backtests honestos

APIs REST y WebSocket de exchanges, ciclo de vida de órdenes, rate limits, gestión de riesgo, monitorización y backtesting: lecciones de ingeniería con bots cripto.

ProCat Solutions criptoweb3websocketnodejsautomatizaciongestion-de-riesgo
Compartir
Bots cripto después de Web3: rate limits, kill switch y backtests honestos

Cuando la llamada REST que envía una orden agota el tiempo de espera, el bot no sabe si el exchange la ha aceptado. Si reintenta a ciegas, puede crear un duplicado. Preguntas como esta surgieron cuando, después de los proyectos de smart contracts y preventas de tokens, nos orientamos hacia la automatización en exchanges. Antes, una aclaración: este artículo no es asesoramiento de inversión. Construimos la infraestructura de bots de trading y automatización; estrategias de trading con el dinero de los clientes, no. La estrategia siempre es del cliente. Nuestro trabajo es que el sistema haga exactamente, de forma predecible y segura, lo que la estrategia dicta.

Varios monitores con gráficos de precios en una oficina en casa

Dos canales, dos verdades

Casi todos los exchanges centralizados ofrecen dos canales. Por la API REST enviamos y cancelamos órdenes y consultamos saldo e historial. Por WebSocket llegan las cotizaciones, las actualizaciones del order book y los cambios de estado de nuestras propias órdenes. Los dos canales no están sincronizados. El WebSocket puede mostrar ya la ejecución mientras REST sigue dando la orden por “abierta”, y también ocurre al revés.

Nuestra solución: el WebSocket es la fuente principal del estado, por detrás corre una conciliación periódica contra REST y, si hay discrepancia, manda la respuesta REST del exchange. Un heartbeat vigila la conexión WebSocket. Al reconectar pedimos un snapshot completo, porque la recuperación de mensajes perdidos funciona distinto en cada exchange y rara vez es fiable.

La orden que agotó el tiempo

La máquina de estados de una orden parece sencilla: creada, abierta, parcialmente ejecutada, ejecutada, cancelada, rechazada. La dificultad está en las transiciones, y el timeout es la peor. Por eso cada orden lleva un identificador propio del lado del cliente, que la mayoría de los exchanges aceptan. Un reintento no crea entonces un duplicado: el exchange devuelve la orden que ya existe.

Cada cambio de estado se escribe en un registro de eventos append-only en PostgreSQL, y el estado actual se deriva de él. Si algo se discute, la secuencia de eventos muestra qué pasó y cuándo.

Rate limits

El otro muro contra el que choca todo bot es el rate limit. Los exchanges ponderan sus límites: una consulta del order book cuesta más que un ping. Pasarse trae un bloqueo breve, que duele justo cuando hay que cancelar una orden deprisa. Por eso:

  • un token bucket del lado del cliente contabiliza el consumo, leyéndolo de las propias cabeceras del exchange;
  • las operaciones críticas (cancelación, kill switch) tienen un margen reservado que las consultas no pueden agotar;
  • ante un error aplicamos backoff exponencial con jitter, y tras una respuesta 429 esperamos lo que pide el exchange, no lo que elegiríamos nosotros.
Registros impresos con líneas resaltadas

La capa bajo la estrategia

Para nosotros, la gestión de riesgo es independiente de la estrategia. Corre por debajo y la estrategia no puede eludirla:

  • límites de posición por activo y en total; por encima del límite, el sistema no envía órdenes de apertura;
  • una pérdida diaria máxima, tras la cual el bot solo permite órdenes de cierre;
  • kill switch: un único comando que cancela todas las órdenes abiertas y pone el bot en modo pasivo, accesible también por un canal separado, al margen de la interfaz web del propio bot;
  • modo paper trading, donde todo corre igual, salvo que las órdenes van a un ejecutor simulado.

El paper trading es la base de las pruebas y no lo tratamos como una comodidad. Todo cambio de código corre primero allí durante días, sobre el flujo de datos real.

Caerse en silencio

Un bot que se detiene en silencio es peor que uno que falla con estruendo. Por eso su estado lo señalan métricas de heartbeat: la antigüedad de la última actualización de precio, el número de órdenes abiertas, el estado de la conexión. Salta una alerta si alguna sale del rango esperado o si el flujo de datos se atasca, aunque no haya llegado ningún mensaje de error. La alerta sale por varios canales, porque el propio bot no puede saber cuál está vivo en ese momento.

Las claves de API nunca entran en el repositorio ni en la imagen Docker. Llegan desde un almacén de secretos al arrancar, como variables de entorno. Sus permisos son mínimos (trading sí, retiradas no) y están restringidas por IP. La revocabilidad importa más que el cifrado: una clave comprometida tiene que poder sustituirse en minutos.

Curvas bonitas, supuestos malos

El backtesting seduce porque dibuja curvas bonitas, pero el resultado vale lo que valen sus supuestos. Los errores típicos que podemos atajar desde el software:

  • look-ahead: la estrategia usa datos que en ese instante aún no estaban disponibles, así que el motor de backtesting solo sirve datos que según su marca de tiempo “ya han llegado”;
  • slippage y comisiones: el ejecutor simulado ejecuta según el order book y con comisiones, nunca al precio medio;
  • huecos en los datos: las velas que faltan no se interpolan; se marcan, y la estrategia también ve el hueco;
  • ejecución no determinista: la misma entrada da siempre el mismo resultado, porque la aleatoriedad se siembra con una semilla y el tiempo se inyecta en lugar de leerse del reloj del sistema.

Esta capa garantiza que el backtest sea reproducible y honesto. No garantiza que la estrategia sea buena. Hay que separar las dos cosas, y durante el desarrollo nosotros respondemos de la primera.

Compartir
Széchenyi Terv Plusz kedvezményezetti infoblokk
QR Code