Polymarket Bot Tutorial · Hoofdstuk 22 van 32
NegRisk multi-outcome bots op Polymarket: sum-to-1 mechanics, leg-arbitrage wanneer YES legs niet optellen tot 1, hedgen over legs en executie-valstrikken specifiek voor multi-outcome markten.
Wat dit hoofdstuk behandelt
Multi-outcome NegRisk markten zijn wederzijds exclusief — precies één resolved YES. Dit hoofdstuk is de strategy-laag bovenop de executie-mechanics van hoofdstuk 11: hoe te hedgen over legs, wanneer sum-to-1 arb echt is en de bugs die de meeste NegRisk bots raken bij first deploy.
Dit is hoofdstuk 22 van onze 32-delige serie over het bouwen van een Polymarket trading bot. We behandelen het onderwerp in detail in de secties hieronder. De body content voor elke sectie wordt geschreven en hoofdstuk-per-hoofdstuk uitgerold; FAQ-antwoorden en referenties zijn al compleet en weerspiegelen production-ervaring van het draaien van onze eigen trader.
- NegRisk vs binary recap
- Sum-to-1 invariant en arbitrage
- Leg-by-leg hedge-constructie
- Executie: neg_risk flag in orders
- Veelvoorkomende bugs in NegRisk bots
- Code: snapshot alle legs en detecteer under-1.00 sum
NegRisk vs binary recap
Binary: één yes/no markt, twee tokens, sommeren tot 1,0. NegRisk: N wederzijds exclusieve uitkomsten, N tokens, alle YES legs sommeren tot ~1,0 over het event.
Executie-wijs vereist NegRisk negRisk: true op elke order (hoofdstuk 11) en routeert via een apart exchange-contract. Strategy-wijs biedt NegRisk twee unieke kansen die binaries niet hebben: cross-leg arb wanneer de som van 1,0 afdrijft, en hedge-constructie door meerdere YES legs te kopen.
Kosten uniek aan NegRisk: meer legs = meer spread tax (elke leg die je trade kost ~0,5-1c spread), bredere sum-to-1 afwijkingen op illiquide events (de arb is vaker beschikbaar maar kleiner).
Sum-to-1 invariant en arbitrage
De arb-premisse: als het kopen van alle N YES legs minder kost dan 1,00 $, heb je een gegarandeerde winst inlocked bij resolution (één leg moet 1,00 $ betalen; de anderen gaan naar 0).
In de praktijk is de arb-gap meestal 0-3c, opgegeten door spread + fees op elke leg, en verdwijnt binnen minuten na opening. Capaciteit is beperkt door de liquiditeit van de dunste leg.
De arb is ook onderhevig aan specifieke resolution-failure modes: een "none of the above" uitkomst die expliciet YES resolved wanneer geen genoemde kandidaat kwalificeert. Als het event zo'n leg heeft en je hem niet kocht, mist je "complete hedge" de daadwerkelijke payout.
Leg-by-leg hedge-constructie
Een positie houdend op één NegRisk leg, kun je hedgen door YES te kopen op concurrerende legs in proportie. Als je Trump-YES op 0,50 houdt en wilt hedgen tegen een Trump-verlies, koop je een portfolio van de andere genoemde legs.
Hedge-gewicht per leg ≈ huidige geïmpliceerde probability van de leg conditioneel op Trump-verlies. Benadering: weight_i = price_i / (1 - trump_price).
De hedge is imperfect omdat de gebruikte prijzen point-in-time zijn en de conditionele probabilities verschuiven naarmate nieuws aankomt. Rebalance de hedge wekelijks of bij groot nieuws. Over-engineer hem niet; het doel van de hedge is variantie verminderen, niet elimineren.
Executie: neg_risk flag in orders
De enkele meest voorkomende NegRisk-specifieke bug: negRisk: true vergeten in de order-plaatsing payload. De order wordt geaccepteerd door de API maar settled incorrect omdat hij routeert naar de standaard CTF exchange in plaats van de 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 uit Gamma API. Lees het; geef het door. Hardcode de flag nooit op basis van gokken.
Veelvoorkomende bugs in NegRisk bots
Uit productie-debug logs over meerdere bots.
- Ontbrekende negRisk flag: orders geaccepteerd, settlement faalt. Genezing: dwing de flag af in elke wrapper.
- Hedgen zonder de "Other" leg: in events met een "None of the above" outcome is het hedge-portfolio dat hem uitsluit incompleet. Genezing: check altijd op de Other-leg bij het construeren van hedges.
- Sum-to-1 arb under-sizing: arber realiseert de 1c edge maar trade 5 shares per leg; totale winst is 5 cent voor spread, negatief netto. Genezing: dimensioneer de arb om betekenisvolle absolute dollars te extraheren, niet de headline-percentages najagen.
- Stale leg pricing: bot fetcht 3 leg-prijzen, neemt totaal 200ms, prijs van laatste leg veranderde tijdens de fetch. Genezing: fetch alle legs parallel + behandel de snapshot als één observatie.
Code: snapshot alle legs en detecteer under-1.00 sum
Referentie: snapshot alle YES legs van een NegRisk event parallel, detecteer 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
Atomische executie van alle legs is het moeilijkere probleem en vereist per-leg FOK + rollback bij partial fill (vergelijkbaar patroon met de stat-arb code van hoofdstuk 16).











