Polymarket Bot Tutorial · Chương 22 trong 32
NegRisk multi-outcome bots trên Polymarket: cơ chế sum-to-1, leg arbitrage khi các YES legs không cộng lại thành 1, hedging giữa các legs, và các lỗi triển khai đặc thù của multi-outcome markets.
Chương này bao gồm những gì
Multi-outcome NegRisk markets là loại loại trừ lẫn nhau - chính xác một outcome sẽ resolve YES. Chương này là lớp strategy nằm trên cơ chế execution của chương 11: cách hedge giữa các legs, khi nào sum-to-1 arb là thật, và những bug mà hầu hết NegRisk bots gặp phải ngay lần deploy đầu tiên.
- Tóm tắt NegRisk vs binary
- Invariant sum-to-1 và arbitrage
- Xây dựng hedge theo từng leg
- Execution: cờ neg_risk trong orders
- Các bug phổ biến trong NegRisk bots
- Code: snapshot tất cả các legs và phát hiện tổng dưới 1.00
Tóm tắt NegRisk vs binary
Binary: một market yes/no, hai tokens, tổng bằng 1.0. NegRisk: N outcome loại trừ lẫn nhau, N tokens, tất cả YES legs cộng lại xấp xỉ 1.0 trên toàn sự kiện.
Về execution, NegRisk yêu cầu negRisk: true trên mọi order (chương 11) và đi qua một exchange contract riêng. Về strategy, NegRisk có hai cơ hội độc đáo mà binary không có: cross-leg arb khi tổng lệch khỏi 1.0, và xây dựng hedge bằng cách mua nhiều YES legs.
Chi phí riêng của NegRisk: càng nhiều legs = càng nhiều spread tax (mỗi leg bạn trade tốn khoảng 0.5-1c spread), độ lệch sum-to-1 trên các event kém thanh khoản càng rộng (arb thường xuất hiện hơn nhưng nhỏ hơn).
Invariant sum-to-1 và arbitrage
Giả định của arb: nếu mua tất cả N YES legs với tổng chi phí thấp hơn $1.00, bạn đã khóa được lợi nhuận đảm bảo khi resolve (một leg phải trả $1.00; các leg còn lại về $0).
Trên thực tế, khoảng cách arb thường chỉ 0-3c, bị ăn mòn bởi spread + fees trên từng leg, và biến mất trong vòng vài phút sau khi mở. Capacity bị giới hạn bởi thanh khoản của leg mỏng nhất.
Arb cũng chịu tác động từ các mode lỗi resolve đặc thù: outcome "none of the above" sẽ explicitly resolve YES khi không có ứng viên nào được nêu tên đủ điều kiện. Nếu event có leg như vậy mà bạn không mua nó, "complete hedge" của bạn sẽ bỏ lỡ payout thực tế.
Xây dựng hedge theo từng leg
Khi đang nắm giữ position ở một NegRisk leg, bạn có thể hedge bằng cách mua YES ở các leg đối thủ theo tỷ lệ. Nếu bạn đang giữ Trump-YES ở 0.50 và muốn hedge trước rủi ro Trump thua, bạn sẽ mua một portfolio gồm các named legs còn lại.
Trọng số hedge mỗi leg ≈ xác suất ngụ ý hiện tại của leg đó với điều kiện Trump thua. Xấp xỉ: weight_i = price_i / (1 - trump_price).
Hedge là không hoàn hảo vì các giá dùng là snapshot tại một thời điểm và conditional probabilities thay đổi khi tin tức mới xuất hiện. Tái cân bằng hedge hàng tuần hoặc khi có tin lớn. Đừng over-engineer; mục tiêu của hedge là giảm variance, không phải triệt tiêu nó.
Execution: cờ neg_risk trong orders
Lỗi phổ biến nhất liên quan đến NegRisk: quên negRisk: true trong payload đặt order. Order vẫn được API chấp nhận nhưng settle sai vì nó đi vào standard CTF exchange thay vì NegRisk exchange.
// CORRECT for NegRisk markets:
await client.createAndPostOrder(
{ tokenID, price, size, side: Side.BUY },
{ tickSize: '0.01', negRisk: true }, // <-- REQUIRED
OrderType.FOK
);
Nguồn sự thật: market.negRisk từ Gamma API. Hãy đọc nó; truyền nó qua. Đừng bao giờ hardcode cờ này chỉ bằng phỏng đoán.
Các bug phổ biến trong NegRisk bots
Từ production debug logs trên nhiều bot khác nhau.
- Thiếu cờ negRisk: order được chấp nhận, nhưng settlement thất bại. Cách khắc phục: ép cờ này trong mọi wrapper.
- Hedge mà không có leg "Other": trong các event có outcome "None of the above", portfolio hedge loại trừ nó là chưa đầy đủ. Cách khắc phục: luôn kiểm tra leg Other khi xây dựng hedge.
- Sum-to-1 arb bị sizing quá nhỏ: arber nhận ra edge 1c nhưng chỉ trade 5 shares mỗi leg; tổng lợi nhuận chỉ là 5 cents trước spread, net âm. Cách khắc phục: size arb để lấy được số tiền tuyệt đối đáng kể, không phải chạy theo phần trăm bề mặt.
- Định giá leg bị stale: bot lấy giá của 3 legs, tổng cộng mất 200ms, giá của leg cuối đã đổi trong lúc fetch. Cách khắc phục: fetch tất cả legs song song + coi snapshot là một quan sát duy nhất.
Code: snapshot tất cả các legs và phát hiện tổng dưới 1.00
Tham khảo: snapshot tất cả YES legs của một NegRisk event song song, phát hiện 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
Thực thi atomic tất cả các legs là vấn đề khó hơn và yêu cầu per-leg FOK + rollback khi partial fill (mẫu tương tự code stat-arb ở chương 16).





