Polymarket Bot Tutorial · Глава 30 из 32
Production-grade code для risk management в 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. Логика strategy - самая простая часть; окружающие caps, halts, watchdogs и reconcilers и определяют, переживет ли bot свою первую плохую неделю. Эта глава - 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 - это всё остальное: что делать, когда price движется против вас быстрее, чем ожидалось, что делать, когда fills перестают проходить, что делать, когда WebSocket падает, что делать, когда strategy оказывается убыточной.
Большинство историй провала builder'ов похожи друг на друга: strategy работала, но bot продолжал торговать во время смены режима рынка, потому что halt так и не сработал. Пишите halts до того, как писать strategy.
Position caps (per-market, per-strategy, total)
Три cap'а, enforced в code.
- Per-market cap: max $X на market независимо от confidence в edge. Типично: $25-100 для small bots, $200-500 для production. Ограничивает blast radius ошибочного решения по одному market.
- Per-strategy cap: если вы запускаете несколько strategies, каждая получает свою долю total capital. Типично: 30-50% на strategy. Не позволяет одному плохому дню одной strategy съесть capital остальных.
- Total cap: max % от balance wallet, deployed одновременно. Типично: 50-70%. Оставляет capital для неожиданных возможностей или для ловли собственных bookkeeping bugs бота.
Все три cap'а должны enforced внутри order-placement function, а не только в logic strategy. У strategy может быть bug; order-placement gate - это последняя линия защиты.
Daily loss kill switch
Самый важный отдельный risk control: daily-loss kill switch.
Правило: если realized + unrealized PnL с полуночи UTC опускается ниже -X% от starting daily balance, bot перестаёт открывать new positions и, optionally, закрывает existing ones. Типичное значение X: 5-10%.
Математика такая: у bot с expected win rate 60% есть, возможно, 5% chance серии из 10 подряд убыточных trades. Без kill switch эта серия накапливается: loss $200 → bot продолжает trading → ещё loss $200 → wallet down на 40%. Если switch срабатывает на -10%, плохой день ограничивается $200, а завтра bot начинает заново.
Switch enforced на server side: запишите halt file или установите database flag, который trading loop проверяет на каждой итерации. Перезапускать только после manual review.
Halt sentinels (file-based emergency stop)
Самый простой возможный halt mechanism: bot проверяет наличие 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)
Чтобы немедленно остановить bot откуда угодно (SSH, Telegram bot, monitoring system): touch /opt/pmt/HALT. Чтобы возобновить: rm /opt/pmt/HALT.
Подход на базе file intentionally low-tech, потому что он работает в условиях, где более сложные halt mechanisms дают сбой: когда bot частично crashed, когда database недоступна, когда API key ограничен rate limit'ом. Доступ к file system почти всегда доступен.
Fill-rate watchdog
Strategy assumes, что FOK orders исполняются с некоторой rate (часто 60-80%). Когда rate заметно падает, что-то изменилось: market makers ушли, вашу strategy распознали, идёт API outage. Какой бы ни была причина, assumption, лежавшее в основе PnL math strategy, больше не работает.
Логика watchdog: rolling 24-hour count fill-rate. Если < 30% (или 50% от expected), alert + auto-halt. Возобновление - только после manual review.
Watchdog полезен и как diagnostic. Резкое падение fill-rate обычно связано с внешним событием (Polymarket deploy, congestion в Polygon, rate limit для вашего IP), о котором вы захотите узнать независимо от влияния на trading.
Reconcile diary vs on-chain on restart
Bot ведёт diary позиций, которые, по его мнению, он держит. Chain хранит truth. Они всегда должны совпадать; когда это не так, bot работает на неверном предположении и будет торговать неправильно.
Логика reconciliation: при каждом restart и раз в час во время normal operation получайте on-chain balances для каждого token, с которым bot работал. Сравнивайте с diary; alert + halt, если balance любого token отличается от diary больше, чем на tolerance для округления.
Самая частая причина divergence - успешный order, который API call бота не зафиксировал (timeout, retry не был записан). Chain содержит position; bot считает, что её нет. Без reconciliation bot не выставит 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)
Паттерн такой: каждая итерация проходит через gate. Bugs strategy не могут обойти controls по конструкции.





