Polymarket Bot Tutorial · บทที่ 22 จาก 32

บอท NegRisk หลายผลลัพธ์บน Polymarket: กลไก sum-to-1, leg arbitrage เมื่อ YES legs รวมกันไม่ถึง 1, การ hedge ข้ามหลาย legs, และข้อผิดพลาดในการ execution ที่เฉพาะกับตลาดหลายผลลัพธ์

บทนี้ครอบคลุมอะไรบ้าง

ตลาด NegRisk แบบหลายผลลัพธ์เป็นแบบ mutually exclusive-จะมีเพียงหนึ่งผลลัพธ์ที่ปิดเป็น YES เท่านั้น บทนี้คือเลเยอร์ด้านกลยุทธ์ที่ต่อยอดจากกลไกการ execution ในบทที่ 11: วิธี hedge ข้าม legs, เมื่อใดที่ sum-to-1 arb เป็นโอกาสจริง, และบั๊กที่บอท NegRisk ส่วนใหญ่เจอตั้งแต่ตอน deploy ครั้งแรก

  • สรุป NegRisk vs binary
  • invariant แบบ sum-to-1 และ arbitrage
  • การสร้าง hedge แบบ leg-by-leg
  • Execution: neg_risk flag ใน orders
  • บั๊กที่พบบ่อยในบอท NegRisk
  • โค้ด: snapshot ทุก legs และตรวจจับผลรวมต่ำกว่า 1.00

สรุป NegRisk vs binary

Binary: ตลาด yes/no หนึ่งตลาด, มีสอง tokens, ผลรวมเท่ากับ 1.0 NegRisk: มี N ผลลัพธ์ที่ mutually exclusive, มี N tokens, และ YES legs ทั้งหมดรวมกันใกล้เคียง 1.0 สำหรับเหตุการณ์นั้น

ในแง่ execution NegRisk ต้องใส่ negRisk: true ในทุก order (บทที่ 11) และส่งผ่าน exchange contract แยกต่างหาก ในแง่กลยุทธ์ NegRisk มีโอกาสเฉพาะสองอย่างที่ binary ไม่มี: cross-leg arb เมื่อผลรวมเบี่ยงจาก 1.0 และการสร้าง hedge โดยซื้อ YES หลาย legs

ต้นทุนที่เฉพาะกับ NegRisk: legs มากขึ้น = spread tax มากขึ้น (แต่ละ leg ที่เทรดมีต้นทุน spread ราว 0.5-1c), การเบี่ยงเบนจาก sum-to-1 ที่กว้างขึ้นในเหตุการณ์สภาพคล่องต่ำ (arb มักมีให้เห็นบ่อยกว่าแต่ขนาดเล็กกว่า)

invariant แบบ sum-to-1 และ arbitrage

หลักการของ arb: ถ้าการซื้อ YES legs ทั้ง N legs มีต้นทุนต่ำกว่า $1.00 คุณได้ล็อกกำไรที่การปิดตลาดอย่างแน่นอน (ต้องมีหนึ่ง leg จ่าย $1.00; ส่วนที่เหลือจะลงไปที่ $0)

ในทางปฏิบัติ ช่องว่างของ arb มักอยู่ที่ 0-3c และถูกกินไปด้วย spread + fees ของแต่ละ leg และมักหายไปภายในไม่กี่นาทีหลังเปิดตลาด ความจุถูกจำกัดโดย leg ที่มีสภาพคล่องบางที่สุด

arb นี้ยังขึ้นอยู่กับ failure modes ของการปิดตลาดเฉพาะเจาะจง: ผลลัพธ์แบบ "none of the above" ที่ปิดเป็น YES อย่างชัดเจนเมื่อไม่มีผู้สมัครที่ระบุคนใดเข้าเงื่อนไข หากเหตุการณ์มี leg แบบนี้และคุณไม่ได้ซื้อไว้ hedge "ครบชุด" ของคุณจะพลาด payout จริง

การสร้าง hedge แบบ leg-by-leg

ถ้าคุณถือสถานะใน NegRisk leg หนึ่ง leg คุณสามารถ hedge ได้โดยซื้อ YES ของ legs คู่แข่งในสัดส่วนที่เหมาะสม หากคุณถือ Trump-YES ที่ 0.50 และต้องการ hedge ความเสี่ยงจาก Trump แพ้ คุณจะซื้อพอร์ตของ legs อื่นที่มีชื่อระบุไว้

น้ำหนัก hedge ต่อ leg ≈ ความน่าจะเป็นโดยนัยปัจจุบันของ leg นั้นเมื่อเงื่อนไขเป็น Trump แพ้ สูตรประมาณ: weight_i = price_i / (1 - trump_price).

hedge นี้ไม่สมบูรณ์เพราะราคาที่ใช้เป็น point-in-time และความน่าจะเป็นแบบมีเงื่อนไขจะเปลี่ยนไปเมื่อมีข่าวเข้ามา ปรับ hedge ใหม่ทุกสัปดาห์หรือเมื่อมีข่าวสำคัญ อย่าทำให้ซับซ้อนเกินไป; จุดประสงค์ของ hedge คือการลด variance ไม่ใช่กำจัดมันทั้งหมด

Execution: neg_risk flag ใน orders

บั๊กที่พบบ่อยที่สุดและเฉพาะกับ NegRisk คือการลืมใส่ negRisk: true ใน payload ตอนส่ง order order จะถูก API รับ แต่ settlement จะผิดเพราะมันถูกส่งไปที่ standard CTF exchange แทนที่จะเป็น NegRisk exchange

// CORRECT for NegRisk markets:
await client.createAndPostOrder(
  { tokenID, price, size, side: Side.BUY },
  { tickSize: '0.01', negRisk: true },   // <-- REQUIRED
  OrderType.FOK
);

แหล่งข้อมูลอ้างอิงที่ถูกต้อง: market.negRisk จาก Gamma API อ่านมัน แล้วส่งต่อไป อย่าตั้งค่า flag แบบเดาเอาเอง

บั๊กที่พบบ่อยในบอท NegRisk

จาก production debug logs ของบอทหลายตัว

  1. ลืม negRisk flag: order ถูกยอมรับ แต่ settlement ล้มเหลว วิธีแก้: บังคับตั้ง flag นี้ในทุก wrapper
  2. hedging โดยไม่รวม "Other" leg: ในเหตุการณ์ที่มีผลลัพธ์ "None of the above" พอร์ต hedge ที่ไม่รวมมันถือว่าไม่ครบ วิธีแก้: ตรวจสอบ Other leg ทุกครั้งเมื่อสร้าง hedge
  3. under-sizing ของ sum-to-1 arb: arber มองเห็น edge 1c แต่เทรดแค่ 5 shares ต่อ leg; กำไรรวมก่อนหัก spread มีแค่ 5 เซนต์ และสุทธิเป็นลบ วิธีแก้: ขนาด arb ควรใหญ่พอให้ได้กำไรเป็นดอลลาร์ที่มีนัยสำคัญ ไม่ใช่ไล่ตามเปอร์เซ็นต์ที่ดูดีบนหัวข้อข่าว
  4. ราคาของ leg ล้าสมัย: บอทดึงราคา 3 legs ใช้เวลารวม 200ms แล้วราคาของ leg สุดท้ายเปลี่ยนระหว่างดึงข้อมูล วิธีแก้: ดึงทุก legs แบบ parallel + มอง snapshot นั้นเป็นการสังเกตครั้งเดียว

โค้ด: snapshot ทุก legs และตรวจจับผลรวมต่ำกว่า 1.00

อ้างอิง: snapshot YES legs ทั้งหมดของเหตุการณ์ NegRisk แบบ parallel และตรวจหา arb

import asyncio, aiohttp

async def fetch_leg_ask(session, token_id):
    async with session.get(f"https://clob.polymarket.com/book?token_id={token_id}") as r:
        d = await r.json()
        asks = d.get("asks", [])
        return float(asks[0]["price"]) if asks else None

async def check_arb(event_slug):
    event = await fetch_event(event_slug)
    if not event["markets"][0]["negRisk"]: return None
    legs = []
    for m in event["markets"]:
        toks = json.loads(m["clobTokenIds"])
        yes_token = toks[0]
        legs.append(yes_token)

    async with aiohttp.ClientSession() as s:
        asks = await asyncio.gather(*[fetch_leg_ask(s, t) for t in legs])
    if any(a is None for a in asks): return None
    total = sum(asks)
    if total < 0.97:
        return {"edge": 1 - total, "legs": list(zip(legs, asks))}
    return None

การ execute ทุก legs แบบ atomic เป็นปัญหาที่ยากกว่า และต้องใช้ FOK แยกต่อ leg + rollback เมื่อ fill ไม่ครบ (รูปแบบคล้ายกับโค้ด stat-arb ในบทที่ 16)

คำถามที่พบบ่อย

invariant แบบ sum-to-1 ในตลาด NegRisk คืออะไร?
Across all YES legs ของตลาด NegRisk แบบหลายผลลัพธ์ ผลรวมของราคา YES จะอยู่ใกล้ 1 USD เพราะจะมีเพียงหนึ่งผลลัพธ์ที่ชนะเท่านั้น หากผลรวมต่ำกว่า 1.00 หลังหัก fees แล้ว การซื้อทุก leg ตามสัดส่วนจะล็อกกำไร arbitrage ได้ arb แบบนี้เกิดไม่บ่อยและโดน snip เร็วมาก - ควรมองเป็นของน่าสนใจ ไม่ใช่กลยุทธ์หลัก
ราคาใน NegRisk ต่างจาก binary อย่างไร?
Binary: ราคา YES คือค่าประมาณความน่าจะเป็นโดยตรงของคุณ NegRisk: ราคา YES ของหนึ่ง leg คือความน่าจะเป็นที่ผลลัพธ์เฉพาะนั้นจะชนะเมื่อเทียบกับทางเลือก N รายการ เมื่อ N โตขึ้น ราคาของแต่ละ leg จะเล็กลง (เพราะความน่าจะเป็นรวมกันเป็น 1) การเทรด NegRisk ต้องคิดในเชิงความน่าจะเป็นแบบสัมพัทธ์ ไม่ใช่ yes/no แบบสัมบูรณ์
บั๊กที่พบบ่อยที่สุดในบอท NegRisk คืออะไร?
ลืมตั้ง flag neg_risk: true ตอนส่ง order order อาจถูก reject หรือไปยังตำแหน่ง CTF ที่ผิด เราเจอปัญหานี้ใน production - commit 06deaef ใน history ของ trader เราเป็นตัวแก้ไขปัญหานี้โดยเฉพาะ ต้องตั้ง neg_risk=true (Python) หรือ negRisk: true (Node) บน orders ของ NegRisk เสมอ
ฉันจะทำเงินจาก NegRisk ด้วยการ hedge legs ได้ไหม?
ในทางทฤษฎีได้ (ล็อก spread ระหว่างสอง legs) แต่ในทางปฏิบัติ fees กิน edge ของ hedge ไปเกือบหมดสำหรับบอทรายย่อยส่วนใหญ่ การ hedge ใช้ได้ดีเพื่อทำให้ inventory เป็นกลางขณะ market making ไม่ใช่กลยุทธ์แบบเดี่ยว ๆ
ฉันจะหา markets แบบ NegRisk ได้อย่างไร?
กรอง gamma /events สำหรับ events ที่มีจำนวน markets > 2 และตั้งค่า negRisk ไว้ หมวดหมู่ที่พบบ่อย: แชมป์รายการ (NBA Finals MVP), ช่องเลือกตั้ง (next Speaker), ตารางทัวร์นาเมนต์ แต่ละ gamma event จะมีอาร์เรย์ child markets ของตัวเอง
ตลาด NegRisk มีสภาพคล่องมากกว่าหรือน้อยกว่า binary?
น้อยกว่าต่อ leg แต่มากกว่าเมื่อรวมทั้งหมด Event NBA Champion ที่มี 30 ทีมอาจมี volume 24 ชั่วโมงรวม 50K แต่ market ของแต่ละทีมมีแค่ 1.6K - ทำให้การเทรดราย leg ยากกว่า สภาพคล่องรวมมีอยู่จริง เพียงแต่กระจัดกระจาย