Polymarket Bot Tutorial · 32개 중 30장
Polymarket bot을 위한 프로덕션급 risk management code: position caps, daily loss limits, halt sentinels, fill-rate watchdogs, restart 시 reconcile, idempotent retries. 실제 production trader에서 가져온 code pattern.
이 장에서 다루는 내용
Risk code는 production trading bot의 대부분을 차지합니다. strategy logic는 쉬운 부분이고, 주변의 caps, halts, watchdogs, reconcilers가 bot이 첫 번째 나쁜 주를 버틸 수 있는지를 결정합니다. 이 장은 production-grade risk pattern에 대해 다룹니다.
- Why risk code is most of a real 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
Why risk code is most of a real trading bot
우리 own bot codebase에서 측정한 값 하나: LOC의 60%가 risk code(caps, halts, watchdogs, reconciliation)입니다. 30%는 strategy, 10%는 glue입니다.
이 비율은 맞습니다. strategy는 쉬운 부분입니다. 언제 enter하고 언제 exit할지 설명하는 건 수십 줄이면 충분합니다. risk code는 나머지 전부입니다: price가 예상보다 빠르게 불리하게 움직일 때 무엇을 할지, fills가 더 이상 들어오지 않을 때 무엇을 할지, WebSocket이 끊겼을 때 무엇을 할지, strategy가 수익성이 없다는 사실이 드러났을 때 무엇을 할지입니다.
대부분의 builder failure story는 같은 형태를 띱니다. strategy는 잘 작동했지만, halt가 발동되지 않아서 regime change를 지나치게 오래 따라갔습니다. strategy를 쓰기 전에 halts부터 작성하세요.
Position caps (per-market, per-strategy, total)
세 가지 cap을 code에서 강제합니다.
- Per-market cap: edge confidence와 상관없이 market당 최대 $X. 일반적으로 소규모 bot은 $25-100, production은 $200-500입니다. 단일 market의 잘못된 판단이 만드는 blast radius를 제한합니다.
- Per-strategy cap: 여러 strategy를 운영한다면 각 strategy에 total capital의 일부를 배분합니다. 일반적으로 strategy당 30-50%입니다. 한 strategy의 나쁜 하루가 다른 strategy의 capital을 잠식하지 못하게 합니다.
- Total cap: wallet balance의 최대 몇 %까지 동시에 deploy할지 제한합니다. 일반적으로 50-70%입니다. 예상치 못한 기회나 bot의 accounting bug를 잡아낼 여유 capital을 남겨둡니다.
이 세 cap은 strategy logic 안이 아니라 order-placement function 내부에서 강제되어야 합니다. strategy에는 bug가 있을 수 있습니다. order-placement gate가 마지막 방어선입니다.
Daily loss kill switch
가장 중요한 단일 risk control은 daily-loss kill switch입니다.
Rule: UTC midnight 이후 realized + unrealized PnL이 시작 daily balance의 -X% 아래로 떨어지면, bot은 새로운 position을 열지 않고, 선택적으로 기존 position을 정리(flatten)합니다. 일반적인 X는 5-10%입니다.
수학적으로 보면, 기대 win rate가 60%인 bot은 10번 연속 손실을 볼 확률이 대략 5% 정도입니다. kill switch가 없으면 이 streak는 누적됩니다: $200 손실 → bot이 계속 trading → 추가 $200 손실 → wallet이 40% 하락. switch가 -10%에서 발동하면 bad day는 $200에서 끝나고, 다음 날 bot은 새로 시작합니다.
이 switch는 server-side로 강제합니다. trading loop가 매 iteration마다 확인하는 halt file을 쓰거나 database flag를 설정하세요. manual review 후에만 restart합니다.
Halt sentinels (file-based emergency stop)
가장 단순한 halt mechanism은 bot이 매 loop iteration마다 파일(예: /opt/pmt/HALT) 존재 여부를 확인하고, 파일이 있으면 trading을 중단하는 방식입니다.
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)
어디에서든 즉시 halt하려면(SSH, Telegram bot, monitoring system): touch /opt/pmt/HALT를 실행합니다. 재개하려면: rm /opt/pmt/HALT.
file-based approach를 의도적으로 low-tech로 만드는 이유는 더 정교한 halt mechanism이 실패하는 조건에서도 작동하기 때문입니다: bot이 부분적으로 crash했을 때, database에 접근할 수 없을 때, API key가 rate-limited일 때입니다. file-system access는 항상 가능합니다.
Fill-rate watchdog
strategy는 FOK order가 어느 정도 rate로 fill된다고 가정합니다(종종 60-80%). rate가 크게 떨어지면 무언가 바뀐 것입니다: market maker가 빠졌거나, strategy가 식별되었거나, API outage가 진행 중이거나. 이유가 무엇이든, strategy의 PnL 수학을 떠받치던 가정이 깨진 것입니다.
Watchdog logic: rolling 24-hour fill-rate count. 30% 미만(또는 expected의 50% 미만)이면 alert + auto-halt. manual review 후에만 resume합니다.
watchdog는 diagnostic으로도 유용합니다. 갑작스러운 fill-rate 하락은 보통 외부 event(Polymarket deploy, Polygon congestion, IP rate-limit)와 연관되며, trading impact와 무관하게 알아야 할 정보입니다.
Reconcile diary vs on-chain on restart
bot은 자신이 보유하고 있다고 생각하는 position의 diary를 유지합니다. chain은 truth를 유지합니다. 이 둘은 항상 일치해야 합니다. 일치하지 않으면 bot은 잘못된 믿음 위에서 운영되고 있으며 잘못 trade하게 됩니다.
Reconciliation logic: 모든 restart 시점과 normal operation 중 매 1시간마다 bot이 건드린 모든 token의 on-chain balance를 가져옵니다. diary와 비교하고, 어떤 token이든 balance가 rounding tolerance보다 많이 다르면 alert + halt합니다.
가장 흔한 divergence 원인은 성공한 order를 bot의 API call이 놓친 경우입니다(timeout, retry가 기록되지 않음). chain에는 position이 있는데, bot은 없다고 생각합니다. reconciliation이 없으면 bot은 take-profit exit를 올리지 못하고 position이 resolution까지 그대로 남습니다.
Code: production-grade halt-aware loop
Reference: 모든 risk control이 연결된 production trading loop입니다.
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)
패턴은 이렇습니다: 모든 iteration이 gate를 통과합니다. strategy bug가 control을 우회할 수 없습니다. 설계상 불가능합니다.












