Polymarket Bot Tutorial · Hoofdstuk 30 van 32
Production-grade risk management code voor Polymarket bots: position caps, daily loss limits, halt sentinels, fill-rate watchdogs, reconcile-on-restart, idempotente retries. Codepatronen van echte production trader.
Wat dit hoofdstuk behandelt
Risk code is het grootste deel van een productie trading bot. Strategy-logica is het makkelijke deel; de omringende caps, halts, watchdogs en reconcilers bepalen of de bot zijn eerste slechte week overleeft. Dit hoofdstuk is het production-grade risk-patroon.
Dit is hoofdstuk 30 van onze 32-delige serie over het bouwen van een Polymarket trading bot. We behandelen het onderwerp in detail in de secties hieronder. De body content voor elke sectie wordt geschreven en hoofdstuk-per-hoofdstuk uitgerold; FAQ-antwoorden en referenties zijn al compleet en weerspiegelen production-ervaring van het draaien van onze eigen trader.
- Waarom risk code het grootste deel is van een echte trading bot
- Position caps (per-markt, per-strategie, totaal)
- Daily loss kill switch
- Halt sentinels (file-based noodstop)
- Fill-rate watchdog
- Reconcile diary vs on-chain bij restart
- Code: production-grade halt-aware loop
Waarom risk code het grootste deel is van een echte trading bot
Een meting die we hebben gedaan op onze eigen bot-codebase: 60% van LOC is risk code (caps, halts, watchdogs, reconciliation). 30% is strategy. 10% is glue.
Die verhouding klopt. Strategy is het makkelijke deel — beschrijven wanneer in te treden en wanneer uit te treden past in een paar dozijn regels. Risk code is al het andere: wat te doen wanneer de prijs sneller tegen je in beweegt dan verwacht, wat te doen wanneer fills stoppen met landen, wat te doen wanneer de WebSocket valt, wat te doen wanneer de strategie blijkt onwinstgevend te zijn.
De meeste builder-failure stories delen dezelfde vorm: de strategie werkte, maar de bot bleef doorhandelen tijdens een regime change omdat geen halt vuurde. Schrijf de halts voordat je de strategie schrijft.
Position caps (per-markt, per-strategie, totaal)
Drie caps, afgedwongen in code.
- Per-markt cap: max $X per markt ongeacht edge-confidence. Typisch: 25-100 $ voor kleine bots, 200-500 $ voor productie. Begrenst de blast radius van een verkeerde call op één markt.
- Per-strategie cap: als je meerdere strategieën draait, krijgt elke een slice van totaal kapitaal. Typisch: 30-50% per strategie. Voorkomt dat een slechte dag van één strategie het kapitaal van andere opvreet.
- Totaal cap: max % van wallet-balance gelijktijdig gedeployed. Typisch: 50-70%. Laat kapitaal achter voor onverwachte kansen of voor het vangen van eigen bookkeeping bugs van de bot.
Alle drie caps moeten worden afgedwongen binnen de order-plaatsings functie, niet alleen in de strategy-logica. De strategie kan een bug hebben; de order-plaatsings gate is de laatste verdedigingslinie.
Daily loss kill switch
De belangrijkste enkele risk control: een daily-loss kill switch.
Regel: als realized + unrealized PnL sinds middernacht UTC daalt onder -X% van starting daily balance, stopt de bot met het openen van nieuwe posities en (optioneel) vlakt bestaande af. Typische X: 5-10%.
De math: een bot met 60% verwachte win rate heeft misschien een 5% kans op een 10-trade losing streak. Zonder de kill switch compoundt die streak: 200 $ verlies → bot blijft handelen → nog 200 $ verlies → wallet 40% omlaag. Met de switch die vuurt op -10%, capt de slechte dag op 200 $ en morgen begint de bot fris.
De switch wordt server-side afgedwongen: schrijf een halt-file of zet een database-flag die de trading loop elke iteratie checkt. Restart pas na handmatige review.
Halt sentinels (file-based noodstop)
Het eenvoudigst mogelijke halt-mechanisme: de bot checkt op een file (bijv. /opt/pmt/HALT) elke loop-iteratie en stopt met handelen als de file bestaat.
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)
Om direct te halten vanaf overal (SSH, Telegram bot, een monitoring system): touch /opt/pmt/HALT. Om te hervatten: rm /opt/pmt/HALT.
De file-based aanpak is bewust low-tech omdat het werkt onder omstandigheden waar meer geavanceerde halt-mechanismen falen: wanneer de bot deels gecrashed is, wanneer de database onbereikbaar is, wanneer de API-key rate-limited is. File-system toegang is altijd beschikbaar.
Fill-rate watchdog
De strategie neemt aan dat FOK orders vullen op een bepaalde rate (vaak 60-80%). Wanneer de rate significant daalt, is iets veranderd: market makers trokken, je strategie werd geïdentificeerd, een API-outage is gaande. Wat de reden ook is, de aanname die de PnL-math van de strategie dreef is gebroken.
Watchdog logica: rolling 24-uurs fill-rate count. Als < 30% (of 50% van verwacht), alert + auto-halt. Hervat pas na handmatige review.
De watchdog is ook nuttig als diagnostiek. Een plotselinge fill-rate daling correleert meestal met een externe gebeurtenis (Polymarket deploy, Polygon congestion, jouw IP rate-limited) waarvan je sowieso wilt weten, los van de trading-impact.
Reconcile diary vs on-chain bij restart
De bot onderhoudt een diary van posities die hij denkt te houden. De chain onderhoudt de waarheid. Ze moeten altijd overeenkomen; wanneer ze dat niet doen, opereert de bot op een verkeerd geloof en zal verkeerd handelen.
Reconciliation logica: bij elke restart en eens per uur tijdens normale operatie, fetch on-chain balances voor elk token dat de bot heeft aangeraakt. Vergelijk met het diary; alert + halt als balance van een token verschilt van diary met meer dan rounding tolerance.
De meest voorkomende oorzaak van divergentie is een succesvolle order die de API-call van de bot miste (timeout, retry nooit geregistreerd). De chain heeft de positie; de bot denkt van niet. Zonder reconciliation post de bot de take-profit exit niet en rijdt de positie tot resolution.
Code: production-grade halt-aware loop
Referentie: de productie-trading loop met alle risk controls aangesloten.
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)
Het patroon: elke iteratie gaat door de gate. Strategy-bugs kunnen de controls niet omzeilen, by construction.











