Polymarket Bot Tutorial · Chapter 30 of 32
Production-grade risk management code for Polymarket bots: position caps, daily loss limits, halt sentinels, fill-rate watchdogs, reconcile-on-restart, idempotent retries. Code patterns from real production trader.
Що охоплює цей розділ
Risk code - це більша частина production trading bot. Логіка стратегії - найлегша частина; навколо неї саме caps, halts, watchdogs і reconcilers визначають, чи переживе бот свій перший невдалий тиждень. Цей розділ - production-grade risk pattern.
- Чому risk code - це більшість справжнього trading bot
- Position caps (per-market, per-strategy, total)
- Daily loss kill switch
- Halt sentinels (file-based emergency stop)
- Fill-rate watchdog
- Reconcile diary vs on-chain on restart
- Code: production-grade halt-aware loop
Чому risk code - це більшість справжнього trading bot
Один із показників, який ми виміряли у власній codebase бота: 60% LOC - це risk code (caps, halts, watchdogs, reconciliation). 30% - strategy. 10% - glue.
Це правильне співвідношення. Strategy - найлегша частина: опис того, коли входити і коли виходити, уміщується в кілька десятків рядків. Risk code - це все інше: що робити, коли ціна рухається проти вас швидше, ніж очікувалося, що робити, коли fills перестають проходити, що робити, коли WebSocket обривається, що робити, коли strategy виявляється збитковою.
У більшості історій провалу builder'ів спільний сюжет один: strategy працювала, але бот продовжував торгувати після regime change, тому що жоден halt не спрацював. Пишіть halts раніше, ніж strategy.
Position caps (per-market, per-strategy, total)
Три caps, які мають бути enforced у code.
- Per-market cap: максимум $X на один market незалежно від confidence у edge. Типово: $25-100 для small bots, $200-500 для production. Обмежує blast radius однієї неправильної ставки на окремий market.
- Per-strategy cap: якщо ви запускаєте кілька strategies, кожна отримує свою частку total capital. Типово: 30-50% на одну strategy. Захищає capital інших strategies від поганого дня однієї з них.
- Total cap: максимальний % від wallet balance, який може бути deployed одночасно. Типово: 50-70%. Залишає capital для неочікуваних opportunity або щоб зловити власні bookkeeping bugs бота.
Усі три caps слід enforce всередині order-placement function, а не лише в strategy logic. У strategy може бути bug; order-placement gate - це остання лінія захисту.
Daily loss kill switch
Найважливіший окремий risk control: daily-loss kill switch.
Правило: якщо realized + unrealized PnL з опівночі UTC падає нижче -X% від starting daily balance, бот припиняє відкривати нові positions і (за бажанням) закриває existing ones. Типове X: 5-10%.
Математика: bot із 60% expected win rate має, можливо, 5% шанс на losing streak із 10 trades. Без kill switch ця серія наростає: $200 loss → бот продовжує торгувати → ще $200 loss → wallet просідає на 40%. Якщо switch спрацьовує на -10%, поганий день обмежується $200, а завтра бот починає з нуля.
Switch enforce server-side: створіть halt file або встановіть database flag, який trading loop перевіряє на кожній ітерації. Перезапускати лише після manual review.
Halt sentinels (file-based emergency stop)
Найпростіший можливий halt mechanism: бот перевіряє наявність file (наприклад, /opt/pmt/HALT) на кожній ітерації loop і зупиняє trading, якщо file існує.
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)
Щоб негайно зупинити бот звідки завгодно (SSH, Telegram bot, monitoring system): touch /opt/pmt/HALT. Щоб відновити роботу: rm /opt/pmt/HALT.
File-based підхід навмисно low-tech, бо він працює в умовах, коли більш складні halt mechanisms fail: коли бот частково crashed, коли database недоступна, коли API key має rate limit. File system доступ завжди є.
Fill-rate watchdog
Strategy припускає, що FOK orders заповнюються з певною rate (часто 60-80%). Коли rate помітно падає, щось змінилося: market makers пішли, вашу strategy ідентифікували, триває API outage. Якою б не була причина, припущення, на якому будувалася PnL math strategy, зламане.
Watchdog logic: rolling 24-hour fill-rate count. Якщо < 30% (або 50% від expected), alert + auto-halt. Відновлення лише після manual review.
Watchdog також корисний як diagnostic. Раптове падіння fill-rate зазвичай корелює із зовнішньою подією (Polymarket deploy, Polygon congestion, ваш IP отримав rate limit), про яку вам варто знати незалежно від trading impact.
Reconcile diary vs on-chain on restart
Bot веде diary positions, які, на його думку, він тримає. Chain зберігає truth. Вони мають завжди збігатися; коли це не так, бот працює на хибному припущенні й торгує неправильно.
Reconciliation logic: на кожному restart і раз на годину під час normal operation отримуйте on-chain balances для кожного token, якого бот торкався. Порівнюйте з diary; alert + halt, якщо баланс будь-якого token відрізняється від diary більше, ніж допускає rounding tolerance.
Найпоширеніша причина розбіжності - successful order, який bot's API call пропустив (timeout, retry never recorded). Chain має position; бот думає, що не має. Без reconciliation бот не виставить take-profit exit, і position дійде до resolution.
Code: production-grade halt-aware loop
Reference: production trading loop з усіма risk controls, підключеними належним чином.
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)
Pattern такий: кожна ітерація проходить через gate. Strategy bugs не можуть обійти controls за самою конструкцією.





