Tutorial de Bot de Polymarket · Capítulo 30 de 32

Código de gestión de riesgo de nivel producción para bots de Polymarket: límites de posición, límites de pérdida diaria, sentinelas de halt, watchdogs de tasa de fill, reconciliación al reiniciar, reintentos idempotentes. Patrones de código de un trader real en producción.

Qué cubre este capítulo

El código de riesgo es la mayor parte de un bot de trading en producción. La lógica de estrategia es la parte fácil; los límites, halts, watchdogs y reconciliadores que la rodean son lo que determina si el bot sobrevive a su primera mala semana. Este capítulo presenta el patrón de riesgo de nivel producción.

  • Por qué el código de riesgo es la mayor parte de un bot de trading real
  • Límites de posición (por mercado, por estrategia, total)
  • Kill switch de pérdida diaria
  • Sentinelas de halt (parada de emergencia basada en archivo)
  • Watchdog de tasa de fill
  • Reconciliar el diario vs on-chain al reiniciar
  • Código: loop de nivel producción con awareness de halt

Por qué el código de riesgo es la mayor parte de un bot de trading real

Una medición que hicimos en nuestro propio codebase del bot: 60% de las líneas de código (LOC) es código de riesgo (límites, halts, watchdogs, reconciliación). 30% es estrategia. 10% es glue.

Ese ratio es correcto. La estrategia es la parte fácil: describir cuándo entrar y cuándo salir cabe en unas pocas docenas de líneas. El código de riesgo es todo lo demás: qué hacer cuando el precio se mueve en tu contra más rápido de lo esperado, qué hacer cuando los fills dejan de ejecutarse, qué hacer cuando el WebSocket se cae, qué hacer cuando resulta que la estrategia no es rentable.

La mayoría de las historias de fracaso de builders comparten la misma forma: la estrategia funcionaba, pero el bot siguió operando durante un cambio de régimen porque nunca se activó un halt. Escribe los halts antes de escribir la estrategia.

Límites de posición (por mercado, por estrategia, total)

Tres límites, aplicados en código.

  • Límite por mercado: máximo $X por mercado sin importar la confianza en la edge. Típico: $25-100 para bots pequeños, $200-500 para producción. Acota el radio de explosión de una mala llamada en un solo mercado.
  • Límite por estrategia: si ejecutas varias estrategias, cada una recibe una porción del capital total. Típico: 30-50% por estrategia. Evita que un mal día de una estrategia consuma el capital de las demás.
  • Límite total: porcentaje máximo del balance de la wallet desplegado simultáneamente. Típico: 50-70%. Deja capital para oportunidades inesperadas o para detectar bugs contables del propio bot.

Los tres límites deben aplicarse dentro de la función de colocación de órdenes, no solo en la lógica de estrategia. La estrategia puede tener un bug; el gate de colocación de órdenes es la última línea de defensa.

Kill switch de pérdida diaria

El control de riesgo individual más importante: un kill switch de pérdida diaria.

Regla: si el PnL realizado + no realizado desde medianoche UTC cae por debajo de -X% del balance inicial diario, el bot deja de abrir nuevas posiciones y, opcionalmente, cierra las existentes. X típico: 5-10%.

La matemática: un bot con 60% de tasa de acierto esperada quizá tiene 5% de probabilidad de una racha perdedora de 10 trades. Sin el kill switch, esa racha se compone: pérdida de $200 → el bot sigue operando → otra pérdida de $200 → la wallet baja 40%. Con el switch activado en -10%, el mal día se limita a $200, y mañana el bot empieza de nuevo.

El switch se aplica del lado del servidor: escribe un archivo de halt o define un flag en la base de datos que el loop de trading revisa en cada iteración. Reinicia solo después de una revisión manual.

Sentinelas de halt (parada de emergencia basada en archivo)

El mecanismo de halt más simple posible: el bot revisa si existe un archivo (por ejemplo, /opt/pmt/HALT) en cada iteración del loop y detiene el trading si el archivo existe.

def trading_loop():
    while True:
        if os.path.exists("/opt/pmt/HALT"):
            log("HALT file detected, sleeping")
            time.sleep(30)
            continue
        run_one_iteration()
        time.sleep(5)

Para detenerlo inmediatamente desde cualquier lugar (SSH, bot de Telegram, un sistema de monitoreo): touch /opt/pmt/HALT. Para reanudar: rm /opt/pmt/HALT.

El enfoque basado en archivos es intencionalmente low-tech porque funciona en condiciones en las que fallan mecanismos de halt más sofisticados: cuando el bot se crashea parcialmente, cuando la base de datos no está accesible, cuando la API key está rate-limited. El acceso al sistema de archivos siempre está disponible.

Watchdog de fill-rate

La estrategia asume que las órdenes FOK se llenan a cierta tasa (a menudo 60-80%). Cuando la tasa cae de forma significativa, algo cambió: los market makers se retiraron, tu estrategia fue identificada, hay una caída de API en curso. Cualquiera sea la razón, la suposición que impulsaba la matemática de PnL de la estrategia está rota.

Lógica del watchdog: conteo móvil de fill-rate de 24 horas. Si es < 30% (o 50% de lo esperado), alertar + auto-halt. Reanudar solo después de revisión manual.

El watchdog también es útil como diagnóstico. Una caída repentina del fill-rate suele correlacionarse con un evento externo (deploy de Polymarket, congestión de Polygon, tu IP siendo rate-limited) que querrás conocer sin importar el impacto en el trading.

Reconciliar diario vs on-chain al reiniciar

El bot mantiene un diario de las posiciones que cree tener. La cadena mantiene la verdad. Siempre deberían coincidir; cuando no lo hacen, el bot opera con una creencia incorrecta y va a tradear mal.

Lógica de reconciliación: en cada reinicio y una vez por hora durante la operación normal, obtén los balances on-chain de cada token que el bot haya tocado. Compáralos contra el diario; alerta + halt si el balance de cualquier token difiere del diario más allá de la tolerancia de redondeo.

La causa más común de divergencia es una orden exitosa cuya llamada API el bot se perdió (timeout, retry nunca registrado). La cadena tiene la posición; el bot cree que no. Sin reconciliación, el bot no publicará la salida de take-profit y la posición se irá hasta resolución.

Código: loop de nivel producción con awareness de halt

Referencia: el loop de trading en producción con todos los controles de riesgo integrados.

def production_loop():
    while True:
        # Halt checks
        if os.path.exists("/opt/pmt/HALT"):
            sleep_with_log(30); continue
        if daily_pnl_below_threshold():
            create_halt("daily PnL kill"); continue

        # Reconcile every hour
        if now() - last_reconcile > 3600:
            ok = reconcile_diary_vs_chain()
            last_reconcile = now()
            if not ok: create_halt("reconciliation failed"); continue

        # Fill-rate watchdog
        if recent_fill_rate() < 0.30:
            create_halt("fill rate collapse"); continue

        # Strategy
        try:
            run_strategy_once()
        except Exception as e:
            log_exception(e)
            if consecutive_exceptions >= 5:
                create_halt(f"exceptions: {e}"); continue
        time.sleep(5)

El patrón: cada iteración pasa por el gate. Los bugs de la estrategia no pueden saltarse los controles, por construcción.

Preguntas frecuentes

¿Qué es un sentinela de halt?
Un archivo (por ejemplo, data/halt_autobuy) que el bot revisa antes de cada orden. Si el archivo existe, el bot se niega a colocar órdenes incluso si la estrategia dice que sí. Te permite detener el bot en medio de un incidente con un solo comando touch. Agregamos exactamente este patrón a nuestro trader en producción después de un incidente de fill atascado en abril de 2026.
¿Qué límites de posición debería configurar?
Por mercado: 1-5% del bankroll. Por estrategia: 10-20%. Exposición abierta total: 50-70% del bankroll (mantén un buffer de efectivo). Limita UNA sola orden a 1-2% del bankroll sin importar la estrategia; una orden ingresada por error nunca debería tener tamaño de cuenta completa.
¿Cómo implemento un kill switch de pérdida diaria?
Lleva el PnL realizado + no realizado por día UTC. Si el PnL diario cae por debajo de -3 a -5% del bankroll, activa el sentinela de halt y notifícate. El bot detiene nuevas órdenes; las posiciones existentes se gestionan manualmente. Reinicia a diario a las 00:00 UTC.
¿Qué debería hacer el bot al reiniciar después de un crash?
Tres pasos: (1) Reconciliar órdenes abiertas vía SDK contra tu diario local. (2) Verificar las posiciones abiertas on-chain contra tu estado local. (3) Si algo diverge, detener el bot y exigir revisión manual. Nunca auto-reanudes en un estado inconsistente.
¿Cómo evito que un solo bug vacíe mi cuenta?
Límites en capas: límite de posición a nivel de código, límite de tamaño de orden a nivel de código, sentinela de halt a nivel de archivo, mínimos/máximos implícitos a nivel del exchange (Polymarket), alertas de monitoreo que te avisan por una tasa inusual de órdenes. Ninguna capa por sí sola es suficiente; se multiplican entre sí.
¿El bot debería operar si falla el logging?
No. Si el bot no puede escribir en su diario, no puede reconciliar al reiniciar, lo que significa que un crash llevará a un estado inconsistente. Haz fail-hard del bot si falla el logging. Los bots sanos en producción son paranoicos con su propia observabilidad.