Polymarket Bot Tutorial · Chapitre 22 sur 32

Bots multi-outcome NegRisk sur Polymarket : mécanismes de sum-to-1, arbitrage de legs lorsque les legs YES ne totalisent pas 1, hedging entre legs, et pièges d'exécution propres aux marchés multi-outcome.

Ce que couvre ce chapitre

Les marchés NegRisk multi-outcome sont mutuellement exclusifs - exactement un seul se résout en YES. Ce chapitre traite de la couche stratégie au-dessus des mécanismes d'exécution du chapitre 11 : comment hedger entre les legs, quand l'arbitrage sum-to-1 est réel, et les bugs que la plupart des bots NegRisk rencontrent lors du premier déploiement.

  • Récapitulatif NegRisk vs binary
  • Invariant sum-to-1 et arbitrage
  • Construction de hedge leg par leg
  • Exécution : flag neg_risk dans les orders
  • Bugs courants dans les bots NegRisk
  • Code : snapshot de tous les legs et détection d'une somme inférieure à 1.00

Récapitulatif NegRisk vs binary

Binary : un marché yes/no, deux tokens, somme de 1.0. NegRisk : N outcomes mutuellement exclusifs, N tokens, tous les legs YES totalisent ~1.0 sur l'événement.

Du point de vue de l'exécution, NegRisk nécessite negRisk: true sur chaque order (chapitre 11) et passe par un smart contract d'exchange distinct. Du point de vue de la stratégie, NegRisk offre deux opportunités uniques que les binaries n'ont pas : l'arb inter-leg lorsque la somme s'écarte de 1.0, et la construction de hedge en achetant plusieurs legs YES.

Coûts propres à NegRisk : plus il y a de legs, plus la spread tax est élevée (chaque leg tradé coûte environ 0.5-1c de spread), et plus les déviations sum-to-1 sont larges sur les événements illiquides (l'arb est plus souvent disponible, mais plus petit).

Invariant sum-to-1 et arbitrage

Le principe de l'arb : si acheter tous les N legs YES coûte moins de 1.00 $, vous verrouillez un profit garanti à la résolution (un leg doit payer 1.00 $ ; les autres tombent à 0).

En pratique, l'écart d'arb est généralement de 0 à 3c, absorbé par la spread + les fees sur chaque leg, et disparaît en quelques minutes après l'ouverture. La capacité est limitée par la liquidité du leg le plus mince.

L'arb est aussi soumis à des modes d'échec de résolution spécifiques : un outcome "none of the above" qui se résout explicitement en YES lorsqu'aucun candidat nommé ne correspond. Si l'événement comporte un tel leg et que vous ne l'avez pas acheté, votre "hedge complet" ne couvre pas le payout réel.

Construction de hedge leg par leg

Si vous détenez une position sur un leg NegRisk, vous pouvez hedger en achetant les YES sur les legs concurrents en proportion. Si vous détenez Trump-YES à 0.50 et voulez vous couvrir contre une perte de Trump, vous achetez un portfolio des autres legs nommés.

Poids de hedge par leg ≈ probabilité implicite actuelle du leg conditionnelle à une défaite de Trump. Approximation : weight_i = price_i / (1 - trump_price).

Le hedge est imparfait parce que les prix utilisés sont pris à un instant donné et que les probabilités conditionnelles évoluent à mesure que les news arrivent. Rééquilibrez le hedge chaque semaine ou lors d'une information majeure. N'allez pas trop loin dans l'ingénierie ; le but du hedge est de réduire la variance, pas de l'éliminer.

Exécution : flag neg_risk dans les orders

Le bug spécifique NegRisk le plus courant : oublier negRisk: true dans le payload de placement d'order. L'order est accepté par l'API mais se settle incorrectement parce qu'il est routé vers l'exchange CTF standard au lieu de l'exchange NegRisk.

// CORRECT for NegRisk markets:
await client.createAndPostOrder(
  { tokenID, price, size, side: Side.BUY },
  { tickSize: '0.01', negRisk: true },   // <-- REQUIRED
  OrderType.FOK
);

Source de vérité : market.negRisk depuis l'API Gamma. Lisez-le ; transmettez-le. Ne hardcodez jamais le flag en devinant.

Bugs courants dans les bots NegRisk

À partir des logs de debug de production sur plusieurs bots.

  1. Flag negRisk manquant : orders acceptés, settlement échoue. Solution : imposer le flag dans chaque wrapper.
  2. Hedging sans le leg "Other" : dans les événements avec un outcome "None of the above", le portfolio de hedge qui l'exclut est incomplet. Solution : vérifier systématiquement le leg Other lors de la construction des hedges.
  3. Arb sum-to-1 sous-dimensionné : l'arber repère l'écart de 1c mais trade 5 shares par leg ; le profit total est de 5 cents avant spread, donc négatif net. Solution : dimensionner l'arb pour générer des dollars absolus significatifs, pas pour courir après des pourcentages spectaculaires.
  4. Prix de leg obsolètes : le bot récupère 3 prix de legs, cela prend 200ms au total, et le prix du dernier leg change pendant la récupération. Solution : récupérer tous les legs en parallèle + traiter le snapshot comme une seule observation.

Code : snapshot de tous les legs et détection d'une somme inférieure à 1.00

Référence : snapshot en parallèle de tous les legs YES d'un événement NegRisk, détection de l'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

L'exécution atomique de tous les legs est le problème plus difficile et nécessite un FOK par leg + rollback en cas de fill partiel (même pattern que le code stat-arb du chapitre 16).

Questions fréquemment posées

Qu'est-ce que l'invariant sum-to-1 dans les marchés NegRisk ?
Sur tous les legs YES d'un marché multi-outcome NegRisk, la somme des prix YES reste proche de 1 USD parce qu'un seul outcome gagne. Si la somme passe sous 1.00 net de fees, acheter chaque leg en proportion verrouille un profit d'arbitrage. L'arb est rare et disparaît très vite - considérez-le comme une curiosité, pas comme une stratégie principale.
En quoi le pricing NegRisk diffère-t-il du binary ?
Binary : le prix YES est votre estimation directe de probabilité. NegRisk : le prix YES d'un leg correspond à la probabilité de cet outcome spécifique parmi N alternatives. À mesure que N augmente, les prix individuels diminuent (les probabilités totalisent 1). Trader le NegRisk exige de penser en probabilités relatives, pas en Yes/No absolu.
Quel est le bug le plus courant d'un bot NegRisk ?
Oublier le flag neg_risk: true lors du placement de l'order. L'order est soit rejeté, soit routé vers la mauvaise position CTF. Nous avons rencontré cela en production - le commit 06deaef dans l'historique de notre trader était précisément le correctif. Définissez toujours neg_risk=true (Python) ou negRisk: true (Node) sur les orders NegRisk.
Puis-je gagner de l'argent sur NegRisk en hedgant les legs ?
En théorie oui (verrouiller la spread entre deux legs). En pratique, les fees mangent l'avantage du hedge pour la plupart des bots retail. Le hedging fonctionne pour garder un inventory neutre pendant le market making, pas comme stratégie autonome.
Comment trouver les marchés NegRisk ?
Filtrez gamma /events pour les événements dont le nombre de markets est > 2 et dont le flag negRisk est activé. Catégories fréquentes : gagnants de championnat (NBA Finals MVP), champs électoraux (next Speaker), brackets de tournoi. Chaque événement gamma inclut son array de child markets.
Les marchés NegRisk sont-ils plus ou moins liquid que les binary ?
Moins par leg, plus en agrégé. Un événement NBA Champion à 30 équipes peut avoir 50K de volume total sur 24h, mais chaque marché d'équipe n'a que 1.6K - ce qui rend le trading par leg plus difficile. La liquidité agrégée est réelle, simplement fragmentée.