Polymarket Bot Tutorial · Capítulo 22 de 32
Bots multi-outcome NegRisk na Polymarket: mechanics de sum-to-1, arbitragem de legs quando os legs YES não somam 1, hedge entre legs e armadilhas de execução específicas de mercados multi-outcome.
O que este capítulo cobre
Mercados multi-outcome NegRisk são mutuamente exclusivos - exatamente um resolve YES. Este capítulo é a camada de strategy em cima dos mechanics de execução do capítulo 11: como fazer hedge entre legs, quando a arbitragem sum-to-1 é real e os bugs que a maioria dos bots NegRisk encontra no primeiro deploy.
- Recap de NegRisk vs binary
- Invariant de sum-to-1 e arbitragem
- Construção de hedge leg by leg
- Execução: flag neg_risk nos orders
- Bugs comuns em bots NegRisk
- Code: snapshot de todos os legs e detecção de soma abaixo de 1.00
Recap de NegRisk vs binary
Binary: um mercado yes/no, dois tokens, soma até 1.0. NegRisk: N outcomes mutuamente exclusivos, N tokens, todos os legs YES somam ~1.0 ao longo do evento.
Na execução, NegRisk exige negRisk: true em cada order (capítulo 11) e faz routing por um exchange contract separado. Na strategy, NegRisk oferece duas oportunidades únicas que binaries não oferecem: arbitragem cross-leg quando a soma desvia de 1.0 e construção de hedge comprando múltiplos legs YES.
Custos únicos do NegRisk: mais legs = mais spread tax (cada leg que você negocia custa ~0.5-1c de spread), desvios sum-to-1 maiores em eventos ilíquidos (a arbitragem aparece com mais frequência, mas é menor).
Invariant de sum-to-1 e arbitragem
A premissa da arbitragem: se comprar todos os N legs YES custa menos de $1.00, você travou um lucro garantido no settlement (um leg necessariamente paga $1.00; os outros vão a $0).
Na prática, o gap de arbitragem costuma ser de 0-3c, consumido por spread + fees em cada leg, e desaparece em minutos após a abertura. A capacidade é limitada pela liquidez do leg mais fino.
A arbitragem também está sujeita a modos de falha específicos de resolution: um outcome de "none of the above" que explicitamente resolve YES quando nenhum candidato nomeado se qualifica. Se o evento tem esse leg e você não o comprou, seu "hedge completo" perde o payout real.
Construção de hedge leg by leg
Se você mantém uma posição em um leg NegRisk, pode fazer hedge comprando YES nos legs concorrentes em proporção. Se você está com Trump-YES a 0.50 e quer fazer hedge contra uma derrota de Trump, compra um portfolio dos outros legs nomeados.
Peso do hedge por leg ≈ probabilidade implícita atual do leg condicional à derrota de Trump. Aproximação: weight_i = price_i / (1 - trump_price).
O hedge é imperfeito porque os prices usados são point-in-time e as probabilidades condicionais mudam conforme as notícias chegam. Rebalanceie o hedge semanalmente ou em notícias importantes. Não complique demais; o objetivo do hedge é reduzir variance, não eliminá-la.
Execução: flag neg_risk nos orders
O bug mais comum específico de NegRisk: esquecer negRisk: true no payload de placement do order. O order é aceito pela API, mas faz settlement incorreto porque é roteado para o exchange CTF padrão em vez do exchange NegRisk.
// 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 da Gamma API. Leia isso; passe adiante. Nunca hardcode a flag com base em chute.
Bugs comuns em bots NegRisk
Dos logs de debug de production em vários bots.
- Flag negRisk ausente: orders aceitos, settlement falha. Solução: impor a flag em todo wrapper.
- Fazer hedge sem o leg "Other": em eventos com outcome "None of the above", o portfolio de hedge que o exclui fica incompleto. Solução: sempre verificar o leg Other ao construir hedges.
- Subdimensionamento da arbitragem sum-to-1: o arber percebe a vantagem de 1c, mas negocia 5 shares por leg; o lucro total é de 5 cents antes do spread, negativo no net. Solução: dimensione a arbitragem para extrair dólares absolutos relevantes, não para perseguir percentuais de headline.
- Pricing obsoleto dos legs: o bot busca 3 prices de legs, leva 200ms no total, e o preço do último leg muda durante a busca. Solução: buscar todos os legs em paralelo + tratar o snapshot como uma única observation.
Code: snapshot de todos os legs e detecção de soma abaixo de 1.00
Referência: snapshot de todos os legs YES de um evento NegRisk em paralelo, detectando arbitragem.
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
A execução atômica de todos os legs é o problema mais difícil e exige FOK por leg + rollback em fill parcial (padrão parecido com o código de stat-arb do capítulo 16).





