Polymarket Bot Tutorial · Chapter 22 of 32
باتهای multi-outcome NegRisk در Polymarket: مکانیک sum-to-1، arbitrage بین legها وقتی YES legها به 1 نمیرسند، hedging بین legها، و pitfalls اجرایی مخصوص بازارهای multi-outcome.
این chapter چه چیزهایی را پوشش میدهد
بازارهای multi-outcome NegRisk متقابلاً انحصاری هستند - دقیقاً یکی از آنها YES میشود. این chapter لایه استراتژی روی مکانیکهای execution در chapter 11 است: چگونه بین legها hedge کنید، چه زمانی sum-to-1 arb واقعی است، و رایجترین bugs که بیشتر NegRisk botها در اولین deploy با آن روبهرو میشوند.
- مرور NegRisk در برابر binary
- invariant و arbitrage از نوع sum-to-1
- ساخت hedge بهصورت leg-by-leg
- execution: فلگ neg_risk در orders
- bugs رایج در NegRisk botها
- کد: snapshot همه legها و تشخیص مجموع زیر 1.00
مرور NegRisk در برابر binary
Binary: یک بازار yes/no، دو token، مجموع برابر 1.0. NegRisk: N outcome متقابلاً انحصاری، N token، و همه YES legها در سراسر event مجموعی نزدیک به 1.0 دارند.
از نظر execution، NegRisk روی هر order به negRisk: true نیاز دارد (chapter 11) و از طریق یک exchange contract جداگانه route میشود. از نظر استراتژی، NegRisk دو فرصت منحصربهفرد دارد که binaryها ندارند: cross-leg arb وقتی مجموع از 1.0 منحرف میشود، و ساخت hedge با خرید چندین YES leg.
هزینههای مخصوص NegRisk: leg بیشتر = spread tax بیشتر (هر legی که معامله میکنید حدود ~0.5-1c spread هزینه دارد)، و انحرافهای sum-to-1 بزرگتر در eventهای illiquid (arb بیشتر در دسترس است اما معمولاً کوچکتر).
invariant و arbitrage از نوع sum-to-1
premise آربیتراژ: اگر خرید همه N YES legها کمتر از $1.00 هزینه داشته باشد، شما در زمان resolution سود تضمینشده قفل کردهاید (یکی از legها باید $1.00 پرداخت کند؛ بقیه به $0 میرسند).
در عمل، gap آربیتراژ معمولاً 0-3c است و spread + fee روی هر leg آن را میبلعد، و اغلب ظرف چند دقیقه پس از opening از بین میرود. capacity نیز به نقدشوندهترین leg محدود است.
این arb همچنین در معرض حالتهای شکست خاص resolution است: outcomeای مثل "none of the above" که وقتی هیچ candidate نامبردهشدهای qualify نمیکند، صریحاً YES resolve میشود. اگر event چنین legی داشته باشد و شما آن را نخریده باشید، "complete hedge" شما payout واقعی را از دست میدهد.
ساخت hedge بهصورت leg-by-leg
اگر روی یک NegRisk leg پوزیشن دارید، میتوانید با خرید YES روی legهای رقیب بهتناسب hedge کنید. اگر Trump-YES را با قیمت 0.50 نگه داشتهاید و میخواهید در برابر شکست ترامپ hedge شوید، یک portfolio از سایر legهای نامبردهشده را میخرید.
وزن hedge برای هر leg تقریباً برابر است با probability ضمنی فعلی آن leg بهشرط اینکه ترامپ ببازد. تقریب: weight_i = price_i / (1 - trump_price).
این hedge کامل نیست چون قیمتهای استفادهشده point-in-time هستند و با رسیدن خبرها conditional probabilityها تغییر میکنند. hedge را هفتگی یا هنگام خبرهای مهم rebalance کنید. بیش از حد مهندسیاش نکنید؛ هدف hedge کاهش variance است، نه حذف کامل آن.
execution: فلگ neg_risk در orders
رایجترین bug مخصوص NegRisk: فراموش کردن negRisk: true در payload ثبت order. API order را میپذیرد اما settlement اشتباه انجام میشود چون بهجای NegRisk exchange، به standard CTF exchange route میشود.
// CORRECT for NegRisk markets:
await client.createAndPostOrder(
{ tokenID, price, size, side: Side.BUY },
{ tickSize: '0.01', negRisk: true }, // <-- REQUIRED
OrderType.FOK
);
source of truth: market.negRisk از Gamma API. آن را بخوانید؛ سپس pass through کنید. هرگز بر اساس حدس فلگ را hardcode نکنید.
bugs رایج در NegRisk botها
بر اساس debug logهای production در چندین bot.
- فراموش کردن فلگ negRisk: order پذیرفته میشود، settlement شکست میخورد. راهحل: فلگ را در هر wrapper enforce کنید.
- hedging بدون leg "Other": در eventهایی با outcome "None of the above"، portfolio هج که آن را حذف کرده ناقص است. راهحل: هنگام ساخت hedge همیشه leg Other را بررسی کنید.
- کمسایز کردن sum-to-1 arb: arber آن برتری 1c را پیدا میکند اما فقط 5 سهم برای هر leg معامله میکند؛ سود کل قبل از spread پنج سنت است و net منفی میشود. راهحل: arb را طوری size کنید که دلار واقعی و معنادار استخراج کند، نه اینکه صرفاً درصدهای جذاب تیتر را دنبال کنید.
- قیمتگذاری stale در legها: bot قیمت 3 leg را میگیرد و در مجموع 200ms زمان صرف میکند، اما قیمت leg آخر در طول fetch تغییر کرده است. راهحل: همه legها را بهصورت parallel fetch کنید + snapshot را یک observation واحد در نظر بگیرید.
کد: snapshot همه legها و تشخیص مجموع زیر 1.00
مرجع: همه YES legهای یک event NegRisk را بهصورت parallel snapshot بگیرید و 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
اجرای atomic همه legها مسئله سختتری است و به per-leg FOK + rollback در صورت partial fill نیاز دارد (الگویی مشابه stat-arb در chapter 16).





