Polymarket Bot Tutorial · Rozdział 22 z 32
Boty NegRisk multi-outcome na Polymarket: mechanika sumy do 1, leg arbitrage, gdy YES legs nie sumują się do 1, hedging między legami oraz pułapki wykonawcze specyficzne dla rynków multi-outcome.
Co obejmuje ten rozdział
Rynki NegRisk multi-outcome są wzajemnie wykluczające się — dokładnie jeden wynik rozlicza się jako YES. Ten rozdział to warstwa strategii nad mechaniką wykonania z rozdziału 11: jak hedgować między legami, kiedy arb sum-to-1 jest realny i jakie bugi najczęściej łapią boty NegRisk przy pierwszym wdrożeniu.
To jest rozdział 22 z naszej 32-częściowej serii o budowie Polymarket trading bota. Omawiamy temat dogłębnie w sekcjach poniżej. Treść dla każdej sekcji jest pisana i publikowana rozdział po rozdziale; odpowiedzi w FAQ i reference są już kompletne i odzwierciedlają doświadczenie produkcyjne z uruchamiania naszego własnego tradera.
- NegRisk vs binary recap
- Inwariant sum-to-1 i arbitrage
- Budowa hedga leg po legu
- Execution: flaga neg_risk w orders
- Najczęstsze bugi w botach NegRisk
- Code: snapshot wszystkich legów i wykrywanie sumy poniżej 1.00
NegRisk vs binary recap
Binary: jeden market yes/no, dwa tokeny, suma do 1.0. NegRisk: N wzajemnie wykluczających się wyników, N tokenów, wszystkie YES legs sumują się do około 1.0 w ramach wydarzenia.
Od strony execution, NegRisk wymaga negRisk: true w każdym orderze (rozdział 11) i przechodzi przez osobny exchange contract. Od strony strategii, NegRisk daje dwie unikalne możliwości, których binary nie ma: cross-leg arb, gdy suma odjeżdża od 1.0, oraz budowę hedga przez kupowanie wielu YES legs.
Koszty specyficzne dla NegRisk: więcej legów = większy spread tax (każdy traded leg kosztuje około 0.5-1c spreadu), szersze odchylenia sum-to-1 na mało płynnych wydarzeniach (arb jest wtedy częściej dostępny, ale mniejszy).
Inwariant sum-to-1 i arbitrage
Założenie arbitrażu: jeśli kupno wszystkich N YES legs kosztuje mniej niż $1.00, masz zablokowany gwarantowany profit przy rozliczeniu (jeden leg musi wypłacić $1.00; pozostałe spadają do $0).
W praktyce luka arbitrażowa to zwykle 0-3c, zjadana przez spread + fees na każdym legu, i znika w ciągu minut od otwarcia. Pojemność ogranicza leg o najcieńszej płynności.
Arb podlega też specyficznym failure mode'om rozliczenia: wynik typu "none of the above", który wyraźnie rozlicza się jako YES, gdy żaden nazwany kandydat nie kwalifikuje się. Jeśli event ma taki leg i go nie kupiłeś, twój "pełny hedge" nie obejmuje rzeczywistej wypłaty.
Budowa hedga leg po legu
Trzymając pozycję na jednym legu NegRisk, możesz hedgować, kupując YES na konkurencyjnych legach w odpowiednich proporcjach. Jeśli masz Trump-YES po 0.50 i chcesz zabezpieczyć się przed porażką Trumpa, kupujesz portfel pozostałych nazwanych legów.
Waga hedga na leg ≈ bieżące implied probability tego legu pod warunkiem, że Trump przegrywa. Aproksymacja: weight_i = price_i / (1 - trump_price).
Hedge jest niedoskonały, bo użyte ceny są punktowe, a conditional probabilities zmieniają się wraz z napływem newsów. Rebalance hedga rób co tydzień albo po dużych newsach. Nie over-engineeruj tego; celem hedga jest redukcja variance, a nie jego eliminacja.
Execution: flaga neg_risk w orders
Najczęstszy bug specyficzny dla NegRisk: zapomnienie o negRisk: true w payloadzie do złożenia ordera. Order jest akceptowany przez API, ale rozlicza się nieprawidłowo, bo trafia do standardowego CTF exchange zamiast do 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 z Gamma API. Odczytaj to i przekaż dalej. Nigdy nie hardcoduj flagi na podstawie zgadywania.
Najczęstsze bugi w botach NegRisk
Z produkcyjnych logów debugowania z wielu botów.
- Brak flagi negRisk: ordery są akceptowane, settlement failuje. Naprawa: wymuś flagę w każdym wrapperze.
- Hedging bez legu "Other": w eventach z wynikiem "None of the above" portfel hedge, który go pomija, jest niekompletny. Naprawa: zawsze sprawdzaj leg Other przy budowie hedga.
- Under-sizing arb sum-to-1: arber zauważa edge 1c, ale handluje 5 shares na leg; całkowity profit to 5 centów przed spreadem, netto ujemnie. Naprawa: skaluj arb tak, by wyciągać sensowne kwoty absolutne, a nie gonić procenty z nagłówka.
- Stale leg pricing: bot pobiera ceny 3 legów, zajmuje to łącznie 200ms, a cena ostatniego legu zmieniła się podczas fetchowania. Naprawa: pobieraj wszystkie legi równolegle + traktuj snapshot jako jedną obserwację.
Code: snapshot wszystkich legów i wykrywanie sumy poniżej 1.00
Reference: snapshot wszystkich YES legs wydarzenia NegRisk równolegle, wykrycie arbitrażu.
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 wszystkich legów to trudniejszy problem i wymaga per-leg FOK + rollback przy partial fill (podobny pattern jak w code stat-arb z rozdziału 16).











