Polymarket Bot Tutorial · บทที่ 30 จาก 32
โค้ดการจัดการความเสี่ยงระดับ production-grade สำหรับ Polymarket bots: position caps, daily loss limits, halt sentinels, fill-rate watchdogs, reconcile-on-restart, idempotent retries. รูปแบบโค้ดจากเทรดเดอร์ production จริง
บทนี้ครอบคลุมอะไรบ้าง
โค้ดด้าน risk คือส่วนใหญ่ของ production trading bot จริง ๆ Strategy logic เป็นส่วนที่ง่าย; ส่วน 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 ของ bot เราเอง: 60% ของ LOC คือ risk code (caps, halts, watchdogs, reconciliation) 30% คือ strategy 10% คือ glue
สัดส่วนนั้นถูกต้องแล้ว Strategy คือส่วนที่ง่าย-การอธิบายว่าจะเข้าเมื่อไรและออกเมื่อไรใช้แค่ไม่กี่สิบบรรทัด Risk code คือทุกอย่างที่เหลือ: ต้องทำอะไรเมื่อราคาวิ่งสวนคุณเร็วเกินคาด, ต้องทำอะไรเมื่อ fills หยุดเข้า, ต้องทำอะไรเมื่อ WebSocket หลุด, ต้องทำอะไรเมื่อ strategy กลายเป็นขาดทุน
เรื่องเล่าความล้มเหลวของ builder ส่วนใหญ่มีโครงแบบเดียวกัน: strategy ใช้ได้ แต่ bot ยังเทรดต่อผ่าน regime change เพราะไม่มี halt ทำงาน เขียน halts ก่อนเขียน strategy
Position caps (per-market, per-strategy, total)
มี 3 caps ที่ต้องบังคับใช้ในโค้ด
- Per-market cap: สูงสุด $X ต่อ market ไม่ว่า edge confidence จะเป็นเท่าไร โดยทั่วไป: $25-100 สำหรับ bot เล็ก ๆ, $200-500 สำหรับ production ช่วยจำกัดผลกระทบจากการตัดสินใจผิดใน market เดียว
- Per-strategy cap: ถ้าคุณรันหลาย strategy แต่ละตัวจะได้ส่วนแบ่งของทุนรวม โดยทั่วไป: 30-50% ต่อ strategy ป้องกันไม่ให้วันที่แย่ของ strategy ตัวหนึ่งกินทุนของตัวอื่นหมด
- Total cap: สูงสุด % ของ wallet balance ที่ deploy พร้อมกัน โดยทั่วไป: 50-70% เหลือทุนไว้สำหรับโอกาสที่ไม่คาดคิด หรือไว้จับ bugs ด้าน bookkeeping ของ bot เอง
cap ทั้งสามแบบควรถูกบังคับใช้ภายในฟังก์ชันวาง order ไม่ใช่แค่ใน strategy logic เท่านั้น Strategy อาจมี bug ได้; เกตสำหรับวาง order คือแนวป้องกันด่านสุดท้าย
Daily loss kill switch
การควบคุมความเสี่ยงที่สำคัญที่สุดเพียงอย่างเดียว: daily-loss kill switch
กฎ: ถ้า realized + unrealized PnL ตั้งแต่เที่ยงคืน UTC ต่ำกว่า -X% ของ starting daily balance ให้ bot หยุดเปิด position ใหม่ และ (ถ้าต้องการ) ปิดสถานะเดิมให้แบนราบ Typical X: 5-10%
คณิตศาสตร์คือ: bot ที่มี expected win rate 60% อาจมีโอกาสประมาณ 5% ที่จะเจอ losing streak 10 trades ถ้าไม่มี kill switch streak แบบนี้จะทบกัน: ขาดทุน $200 → bot ยังเทรดต่อ → ขาดทุนอีก $200 → wallet ลง 40% พอ switch ทำงานที่ -10% วันที่แย่ก็จะจบที่ $200 และพรุ่งนี้ bot เริ่มใหม่ได้
switch นี้บังคับฝั่ง server: เขียน halt file หรือ set database flag ที่ trading loop ตรวจทุก iteration รีสตาร์ตได้เฉพาะหลังจากตรวจสอบด้วยมือแล้ว
Halt sentinels (file-based emergency stop)
กลไก halt ที่ง่ายที่สุด: bot ตรวจหาไฟล์ (เช่น /opt/pmt/HALT) ทุกครั้งที่วนลูป และหยุดเทรดถ้ามีไฟล์นี้อยู่
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 ที่ซับซ้อนกว่าล้มเหลว: ตอนที่ bot crash บางส่วน, ตอนที่ database เข้าไม่ถึง, ตอนที่ API key โดน rate-limit การเข้าถึง file-system ใช้ได้เสมอ
Fill-rate watchdog
strategy สมมติว่า FOK orders จะ fill ในอัตราหนึ่ง (มัก 60-80%) เมื่ออัตรานั้นตกลงอย่างมีนัยสำคัญ แปลว่ามีบางอย่างเปลี่ยนไป: market makers ถอนตัว, strategy ของคุณถูกจับได้, หรือมี API outage เกิดขึ้น ไม่ว่าเหตุผลอะไร สมมติฐานที่ใช้คำนวณ PnL ของ strategy พังแล้ว
ตรรกะของ watchdog: นับ rolling 24-hour fill-rate ถ้าต่ำกว่า 30% (หรือ 50% ของที่คาดไว้) ให้ alert + auto-halt กลับมาเทรดได้เฉพาะหลัง manual review
watchdog ยังมีประโยชน์ในเชิงวินิจฉัยด้วย การที่ fill-rate ลดลงแบบฉับพลันมักสัมพันธ์กับเหตุการณ์ภายนอก (Polymarket deploy, Polygon congestion, IP ของคุณโดน rate-limit) ซึ่งเป็นสิ่งที่คุณควรรู้ไม่ว่าผลกระทบต่อการเทรดจะเป็นอย่างไร
Reconcile diary vs on-chain on restart
bot จะเก็บ diary ของ position ที่คิดว่าตัวเองถืออยู่ chain จะเก็บความจริง ทั้งสองอย่างควรตรงกันเสมอ; ถ้าไม่ตรง bot กำลังทำงานบนความเชื่อที่ผิดและจะเทรดผิด
ตรรกะการ reconcile: ทุกครั้งที่รีสตาร์ต และทุก ๆ ชั่วโมงระหว่างการทำงานปกติ ให้ดึง on-chain balances ของทุก token ที่ bot เคยแตะมา เปรียบเทียบกับ diary; ถ้าบาลานซ์ของ token ใดต่างจาก diary เกินกว่าค่าความคลาดเคลื่อนจากการปัดเศษ ให้ alert + halt
สาเหตุที่พบบ่อยที่สุดของ divergence คือ order สำเร็จ แต่ API call ของ bot พลาดไป (timeout, retry ที่ไม่ถูกบันทึก) chain มี position อยู่; bot คิดว่าไม่มี ถ้าไม่ reconcile bot จะไม่วาง take-profit exit และ position จะถือไปจนถึง resolution
Code: production-grade halt-aware loop
อ้างอิง: trading loop สำหรับ production ที่ผูก 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)
รูปแบบคือ: ทุก iteration ต้องผ่านเกตเสมอ bugs ของ strategy ไม่สามารถข้าม controls ได้โดยโครงสร้างของระบบ





