Polymarket Bot Tutorial · Capitolo 30 di 32
Codice di risk management di livello production per Polymarket bot: position cap, daily loss limit, halt sentinel, fill-rate watchdog, reconcile-on-restart, retry idempotenti. Pattern di codice da un vero trader in produzione.
Cosa copre questo capitolo
Il codice di risk è la maggior parte di un production trading bot. La logica di strategy è la parte facile; i cap, gli halt, i watchdog e i reconciler che la circondano sono ciò che determina se il bot sopravvive alla sua prima settimana negativa. Questo capitolo è il pattern di risk di livello production.
Questo è il capitolo 30 della nostra serie in 32 parti su come costruire un Polymarket trading bot. Trattiamo l’argomento in profondità nelle sezioni qui sotto. Il body content di ogni sezione viene scritto e pubblicato capitolo per capitolo; le risposte della FAQ e i riferimenti sono già completi e riflettono l’esperienza production maturata gestendo il nostro trader.
- Perché il codice di risk è la parte più importante di un vero trading bot
- Position cap (per-market, per-strategy, total)
- Daily loss kill switch
- Halt sentinel (emergency stop basato su file)
- Fill-rate watchdog
- Reconcile diary vs on-chain al riavvio
- Codice: production-grade loop con awareness degli halt
Perché il codice di risk è la parte più importante di un vero trading bot
Una misurazione che abbiamo fatto sul codebase del nostro bot: il 60% delle LOC è risk code (cap, halt, watchdog, reconciliation). Il 30% è strategy. Il 10% è glue.
Quel rapporto è corretto. La strategy è la parte facile — descrivere quando entrare e quando uscire sta in poche decine di righe. Il risk code è tutto il resto: cosa fare quando il prezzo si muove contro di te più velocemente del previsto, cosa fare quando i fill smettono di arrivare, cosa fare quando il WebSocket cade, cosa fare quando la strategy si rivela non profittevole.
Le storie di fallimento dei builder hanno quasi sempre la stessa forma: la strategy funzionava, ma il bot ha continuato a tradare durante un regime change perché non è scattato nessun halt. Scrivi gli halt prima di scrivere la strategy.
Position cap (per-market, per-strategy, total)
Tre cap, applicati nel codice.
- Per-market cap: massimo $X per market indipendentemente dalla confidence dell’edge. Tipico: $25-100 per bot piccoli, $200-500 per production. Limita il blast radius di una singola chiamata errata su un market.
- Per-strategy cap: se esegui più strategy, ciascuna riceve una quota del capitale totale. Tipico: 30-50% per strategy. Impedisce che una giornata storta di una strategy consumi il capitale delle altre.
- Total cap: massima % del saldo wallet deployata simultaneamente. Tipico: 50-70%. Lascia capitale per opportunità inattese o per intercettare i bug di bookkeeping del bot stesso.
Tutti e tre i cap devono essere applicati dentro la funzione di order placement, non solo nella logica della strategy. La strategy può avere un bug; il gate di order placement è l’ultima linea di difesa.
Daily loss kill switch
Il singolo controllo di risk più importante: un daily-loss kill switch.
Regola: se il realized + unrealized PnL da mezzanotte UTC scende sotto -X% del daily balance iniziale, il bot smette di aprire nuove position e, opzionalmente, chiude quelle esistenti. X tipico: 5-10%.
La matematica: un bot con expected win rate del 60% ha forse una probabilità del 5% di una losing streak di 10 trade. Senza kill switch, quella streak si compone: perdita di $200 → il bot continua a tradare → un’altra perdita di $200 → wallet a -40%. Con lo switch che scatta a -10%, la giornata negativa si ferma a $200, e domani il bot riparte da zero.
Lo switch viene applicato lato server: scrivi un file di halt o imposta un flag in database che il trading loop controlla a ogni iterazione. Riavvia solo dopo una manual review.
Halt sentinel (emergency stop basato su file)
Il meccanismo di halt più semplice possibile: il bot controlla la presenza di un file (per esempio /opt/pmt/HALT) a ogni iterazione del loop e smette di tradare se il file esiste.
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)
Per fermare immediatamente da qualsiasi punto (SSH, Telegram bot, monitoring system): touch /opt/pmt/HALT. Per riprendere: rm /opt/pmt/HALT.
L’approccio basato su file è volutamente low-tech perché funziona in condizioni in cui meccanismi di halt più sofisticati falliscono: quando il bot è parzialmente crashato, quando il database non è raggiungibile, quando la API key è soggetta a rate limit. L’accesso al filesystem è sempre disponibile.
Fill-rate watchdog
La strategy assume che gli ordini FOK vengano filled a un certo rate (spesso 60-80%). Quando il rate scende in modo significativo, qualcosa è cambiato: i market maker si sono ritirati, la tua strategy è stata identificata, c’è un outage della API in corso. Qualunque sia il motivo, l’assunzione che guidava la matematica del PnL della strategy è rotta.
Logica del watchdog: conteggio rolling del fill-rate nelle ultime 24 ore. Se < 30% (o 50% dell’atteso), alert + auto-halt. Riprendi solo dopo una manual review.
Il watchdog è utile anche come diagnostica. Un calo improvviso del fill-rate di solito è correlato a un evento esterno (deploy di Polymarket, congestione di Polygon, il tuo IP che viene rate-limited) che vorresti comunque conoscere, indipendentemente dall’impatto sul trading.
Reconcile diary vs on-chain al riavvio
Il bot mantiene un diary delle position che pensa di detenere. La chain mantiene la verità. Dovrebbero sempre coincidere; quando non coincidono, il bot sta operando con una convinzione errata e tradarà in modo sbagliato.
Logica di reconciliation: a ogni riavvio e una volta all’ora durante il normale funzionamento, recupera i saldi on-chain per ogni token che il bot ha toccato. Confrontali con il diary; alert + halt se il balance di un token differisce dal diary oltre la tolleranza di rounding.
La causa più comune della divergenza è un ordine riuscito che la chiamata API del bot si è persa (timeout, retry mai registrato). La chain ha la position; il bot pensa di no. Senza reconciliation, il bot non pubblicherà l’uscita take-profit e la position andrà fino alla resolution.
Codice: production-grade loop con awareness degli halt
Reference: il trading loop production con tutti i controlli di risk collegati.
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)
Il pattern: ogni iterazione passa attraverso il gate. I bug della strategy non possono bypassare i controlli, per costruzione.











