Polymarket Bot Tutorial · Chapter 22 of 32

NegRisk multi-outcome bots на Polymarket: механіка sum-to-1, leg arbitrage, коли YES legs не дають суму 1, hedging між legs і типові помилки виконання, специфічні для multi-outcome markets.

Що охоплює цей розділ

Multi-outcome NegRisk markets є взаємовиключними - рівно один результат закривається як YES. Цей розділ - це стратегічний шар поверх механіки виконання з розділу 11: як hedging між legs, коли sum-to-1 arb є реальним, і які баги найчастіше ловлять NegRisk bots під час першого запуску.

  • Короткий огляд NegRisk vs binary
  • Інваріант sum-to-1 і arbitrage
  • Побудова hedge по legs
  • Execution: neg_risk flag в orders
  • Поширені bugs у NegRisk bots
  • Code: snapshot усіх legs і виявлення суми нижче 1.00

NegRisk vs binary: короткий огляд

Binary: один yes/no market, два tokens, сума дорівнює 1.0. NegRisk: N взаємовиключних outcome, N tokens, усі YES legs разом дають приблизно 1.0 по всій події.

З погляду execution, NegRisk вимагає negRisk: true для кожного order (розділ 11) і проходить через окремий exchange contract. З погляду strategy, NegRisk дає дві унікальні можливості, яких немає в binary: cross-leg arb, коли сума відхиляється від 1.0, і побудову hedge через купівлю кількох YES legs.

Витрати, унікальні для NegRisk: більше legs = більше spread tax (кожен leg, яким ви торгуєте, коштує приблизно 0.5–1c spread), ширші відхилення sum-to-1 на illiquid events (arb частіше доступний, але менший).

Інваріант sum-to-1 і arbitrage

Ідея arb: якщо купівля всіх N YES legs коштує менше ніж $1.00, ви фіксуєте гарантований profit на момент розв'язання (один leg має виплатити $1.00; інші стануть $0).

На практиці arb gap зазвичай становить 0–3c і з'їдається spread + fees на кожному leg, а також зникає протягом кількох хвилин після відкриття. Capacity обмежена найтоншим leg за liquidity.

Arb також підпадає під специфічні режими failure при resolution: outcome "none of the above", який явно закривається як YES, коли жоден названий candidate не підходить. Якщо у події є такий leg, а ви його не купили, ваш "complete hedge" не покриває фактичну виплату.

Побудова hedge по leg-ах

Якщо ви тримаєте позицію в одному NegRisk leg, ви можете hedge-ити її, купуючи YES на конкуруючих legs у відповідній пропорції. Якщо ви тримаєте Trump-YES на 0.50 і хочете захиститися від Trump loss, ви купуєте портфель інших названих legs.

Вага hedge на один leg ≈ поточна implied probability цього leg за умови, що Trump програє. Наближення: weight_i = price_i / (1 - trump_price).

Hedge не є ідеальним, бо ціни, які використовуються, є point-in-time, а conditional probabilities змінюються зі зміною новинного фону. Перераховуйте hedge щотижня або під час важливих новин. Не ускладнюйте надмірно; мета hedge - зменшити variance, а не прибрати її повністю.

Execution: neg_risk flag в orders

Найпоширеніший баг, специфічний для NegRisk: забути negRisk: true у payload для розміщення order. Order приймається API, але розраховується некоректно, бо маршрутизується до стандартного 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
);

Source of truth: market.negRisk з Gamma API. Читайте його і передавайте далі. Ніколи не hardcode-ьте цей flag на основі здогадок.

Поширені bugs у NegRisk bots

Із production debug logs по кількох bots.

  1. Missing negRisk flag: orders приймаються, settlement fails. Виправлення: примусово встановлюйте цей flag у кожному wrapper.
  2. Hedging без "Other" leg: у подіях з outcome "None of the above" hedge portfolio, який його виключає, є неповним. Виправлення: завжди перевіряйте Other leg під час побудови hedges.
  3. Недостатній розмір sum-to-1 arb: arber знаходить 1c edge, але торгує по 5 shares на leg; загальний profit становить 5 cents до spread, а після цього net стає негативним. Виправлення: масштабуйте arb так, щоб витягувати суттєві absolute dollars, а не ганятися за headline percentages.
  4. Застаріле ціноутворення leg-ів: bot отримує 3 leg prices, витрачає 200ms сумарно, і ціна останнього leg змінюється під час fetch. Виправлення: отримуйте всі legs паралельно + розглядайте snapshot як одне спостереження.

Code: snapshot усіх legs і виявлення суми нижче 1.00

Reference: паралельний snapshot усіх YES legs NegRisk події, виявлення 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 execution усіх legs - складніша задача, і вона потребує per-leg FOK + rollback у разі partial fill (схожий патерн на stat-arb code з розділу 16).

Найчастіші запитання

Що таке інваріант sum-to-1 у NegRisk markets?
У всіх YES legs NegRisk multi-outcome market сума YES prices тримається близько 1 USD, бо рівно один outcome перемагає. Якщо сума падає нижче 1.00 нетто після fees, купівля кожного leg у пропорції фіксує arbitrage profit. Arb трапляється рідко і швидко зникає - сприймайте його як цікавий кейс, а не основну strategy.
Чим NegRisk pricing відрізняється від binary?
Binary: YES price - це ваша пряма оцінка probability. NegRisk: YES price для одного leg - це ймовірність того, що саме цей outcome переможе серед N alternatives. Коли N зростає, окремі prices зменшуються (ймовірності в сумі дають 1). Торгівля NegRisk вимагає мислити відносними probabilities, а не абсолютним Yes/No.
Який найпоширеніший bug у NegRisk bot?
Забути flag neg_risk: true під час розміщення order. Order або відхиляється, або маршрутизується в неправильну CTF position. Ми натрапили на це в production - commit 06deaef в історії нашого trader був саме виправленням цього. Завжди встановлюйте neg_risk=true (Python) або negRisk: true (Node) для NegRisk orders.
Чи можна заробляти на NegRisk через hedging legs?
У теорії так (зафіксувати spread між двома legs). На практиці fees для більшості retail bots з'їдають edge hedge. Hedging працює для збереження нейтрального inventory під час market making, а не як самостійна strategy.
Як знайти NegRisk markets?
Фільтруйте gamma /events для подій, де markets count > 2 і встановлено flag negRisk. Типові категорії: championship winners (NBA Finals MVP), election fields (next Speaker), tournament brackets. Кожна gamma подія містить свій child markets array.
NegRisk markets більш чи менш liquid, ніж binary?
Менш liquid на один leg, але більш liquid в aggregate. Подія на 30 команд NBA Champion може мати 50K total 24h volume, але кожен market команди - лише 1.6K, що ускладнює торгівлю по окремих legs. Сукупна liquidity реальна, просто вона fragmented.