Polymarket Bot Tutorial · Глава 22 из 32

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

Что охватывает эта глава

Multi-outcome NegRisk markets взаимно исключающие - ровно один outcome resolves YES. Эта глава посвящена strategy layer поверх execution mechanics из главы 11: как hedge across legs, когда sum-to-1 arb действительно существует и какие bugs чаще всего ловят NegRisk bots при первом deploy.

  • NegRisk vs binary recap
  • Sum-to-1 invariant и arbitrage
  • Leg-by-leg hedge construction
  • Execution: флаг neg_risk в orders
  • Распространенные bugs в NegRisk bots
  • Code: snapshot всех legs и detect under-1.00 sum

NegRisk vs binary recap

Binary: один yes/no market, два tokens, sum до 1.0. NegRisk: N взаимно исключающих outcomes, N tokens, все YES legs суммарно дают ~1.0 на весь event.

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

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

Sum-to-1 invariant и arbitrage

Логика arb: если покупка всех N YES legs стоит меньше $1.00, вы фиксируете гарантированную прибыль при resolution (один leg обязан выплатить $1.00; остальные уйдут к $0).

На практике arb gap обычно составляет 0-3c и съедается spread + fees на каждом leg; также он исчезает в течение нескольких минут после открытия. Capacity ограничена самым неликвидным leg.

Arb также подвержен специфическим modes of failure при resolution: outcome "none of the above", который явно resolves YES, когда ни один из названных кандидатов не подходит. Если у event есть такой leg, а вы его не купили, ваш "complete hedge" не покрывает фактическую выплату.

Leg-by-leg hedge construction

Держа позицию в одном NegRisk leg, вы можете hedge ее, покупая YES в конкурирующих legs пропорционально. Если у вас Trump-YES по 0.50 и вы хотите hedge against a Trump loss, вы покупаете portfolio из остальных именованных legs.

Вес hedging на leg ≈ текущая implied probability leg при условии, что Trump проиграет. Аппроксимация: weight_i = price_i / (1 - trump_price).

Hedge imperfect, потому что используемые prices взяты на конкретный момент времени, а conditional probabilities меняются по мере появления news. Rebalance hedge раз в неделю или при крупных news. Не усложняйте без необходимости; цель hedging - снизить variance, а не устранить ее полностью.

Execution: флаг neg_risk в orders

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

Распространенные bugs в NegRisk bots

Из production debug logs по нескольким bots.

  1. Missing negRisk flag: orders принимаются, settlement fails. Лечение: enforced flag в каждом wrapper.
  2. Hedging without the "Other" leg: в events с outcome "None of the above" hedge portfolio, исключающий его, неполный. Лечение: всегда проверяйте Other leg при построении hedges.
  3. Sum-to-1 arb under-sizing: arber находит edge в 1c, но торгует по 5 shares на leg; общая прибыль - 5 cents до spread, на net получается минус. Лечение: size arb так, чтобы извлекать значимые абсолютные dollars, а не гоняться за headline percentages.
  4. Stale leg pricing: bot получает 3 leg prices, тратит в сумме 200ms, а price последнего leg уже изменился во время fetch. Лечение: запрашивать все legs параллельно + считать snapshot единым observation.

Code: snapshot всех legs и detect under-1.00 sum

Reference: snapshot всех YES legs NegRisk event параллельно, detect 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 (похожий pattern на code stat-arb из главы 16).

Часто задаваемые вопросы

Что такое sum-to-1 invariant в NegRisk markets?
Across all YES legs of a NegRisk multi-outcome market, сумма YES prices остается near 1 USD, потому что exactly one outcome wins. Если сумма падает ниже 1.00 net of fees, покупка каждого leg пропорционально фиксирует arbitrage profit. Арбитраж редок и быстро sniped - относитесь к нему как к curiosity, а не как к primary strategy.
Чем NegRisk pricing отличается от binary?
Binary: YES price - это ваша прямая оценка probability. NegRisk: YES price одного leg - это probability того, что именно этот outcome победит среди N alternatives. По мере роста N individual prices уменьшаются (probabilities суммируются к 1). Trading NegRisk требует думать в relative probabilities, а не в абсолютном Yes/No.
Какой самый распространенный bug в NegRisk bot?
Забыть флаг neg_risk: true при размещении order. Order либо reject'ится, либо уходит в wrong CTF position. Мы столкнулись с этим в production - commit 06deaef в истории нашего trader был именно этим fix. Всегда ставьте neg_risk=true (Python) или negRisk: true (Node) на NegRisk orders.
Можно ли зарабатывать на NegRisk через hedging legs?
В теории да (фиксируя spread между двумя legs). На практике fees съедают hedge edge для большинства retail bots. Hedging работает для поддержания inventory neutral во время market making, но не как standalone strategy.
Как найти NegRisk markets?
Фильтруйте gamma /events по событиям, где markets count > 2 и установлен флаг negRisk. Частые категории: championship winners (NBA Finals MVP), election fields (next Speaker), tournament brackets. Каждый gamma event включает массив child markets.
NegRisk markets более или менее liquid, чем binary?
Менее liquid на leg, но более liquid в aggregate. У события "30-team NBA Champion" может быть 50K total 24h volume, но у каждого team market только 1.6K - из-за этого trading по отдельным legs сложнее. Aggregate liquidity реальна, просто fragmented.