Tutoriel bot Polymarket · Chapitre 24 sur 32

Polymarket Perps dispose d'une API publique complète, avec des SDK officiels en TypeScript et en Python. Ce chapitre construit un bot sur la véritable interface : authentification avec une clé de trading proxy, données de marché via REST et WebSocket, ordres avec take-profit et stop-loss, et contrôles de risque qui empêchent un bot à effet de levier de vider le compte.

Build your own theme park, free in your browserPublicité Annoncez ici
Avant de vous lancer. Le passage d'ordres sur Perps n'est pas autorisé depuis les États-Unis, le Canada, Cuba, l'Iran, la Corée du Nord, la Syrie, la Crimée, Donetsk ou Louhansk, et polymarket.com bloque d'autres pays encore. Un bot ou un serveur à l'étranger n'y change rien. Avec l'effet de levier, un bug fait perdre de l'argent très vite : testez donc avec la taille minimale. Vous découvrez Perps ? Commencez par le guide Polymarket Perps.

Contenu de ce chapitre

  • Chiffres clés pour les développeurs de bots
  • Comment l'API Perps est construite
  • Étape 1 : installer le SDK et ouvrir une session
  • Étape 2 : lire les données de marché via REST et WebSocket
  • Étape 3 : passer des ordres avec take-profit et stop-loss
  • Étape 4 : un squelette de bot avec contrôles de risque dans le code
  • Erreurs, dead man's switch, règles applicables aux bots et hébergement

Chaque méthode du SDK et chaque endpoint cités ici proviennent de la documentation Perps de Polymarket (docs.polymarket.com/perps, consultée le 6 novembre 2026). Notre propre logique est signalée dans les commentaires, et la fonction de stratégie est un espace réservé clairement identifié.

Chiffres clés pour les développeurs de bots (en novembre 2026)

ÉlémentValeur
URL de base RESThttps://api.perpetuals.polymarket.com
WebSocketwss://ws.perpetuals.polymarket.com/v1/ws
SDK TypeScript@polymarket/client (avec viem pour la signature)
SDK Pythonpolymarket-client (asynchrone)
Données publiques/v1/info/*, sans authentification
Lectures privées/v1/account/* avec les en-têtes polymarket-proxy et polymarket-secret
Écritures signées/v1/trade/*, signature EIP-712 par la clé proxy, valable 5 minutes
Identifiants de sessionExpirent par défaut au bout d'une semaine
Ordre minimum10 $ de notionnel ; dépôt minimum de 10 pUSD
Ordre au marché maximal1 000 000 $ sur les marchés 50x et 20x, 500 000 $ sur la plupart des autres, 50 000 $ sur les cryptos à 3x et 5x
Format du prix et de la tailleChaînes décimales, sans dépasser le nombre de décimales du marché ni 5 chiffres significatifs
Effet de levier maximal50x (BTC, ETH, USA500, US100), sinon 20x, 10x, 5x ou 3x selon le marché, moins pour les grosses positions
Frais (niveau de base)Taker 0,040 %, maker 0,0125 % ; ANT à moitié prix
FinancementToutes les heures, plafonné à +/-4 % par heure
Déclencheurs TP/SLPrix de marque, pas le dernier prix échangé
Keepalive WebSocketPing environ toutes les 25 secondes ; considérer la connexion comme périmée après environ 65 secondes de silence
Fraîcheur du tickerJusqu'à 10 secondes de retard

Comment l'API Perps est construite

Perps est une plateforme d'échange hybride : l'appariement des ordres se fait offchain, la conservation des fonds et le règlement sur Polygon. Seuls les dépôts et les retraits sont onchain, il n'y a donc pas de frais de gas par ordre. L'API comporte trois couches :

  • Données publiques (/v1/info/) : instruments, tickers, carnet d'ordres, bougies, transactions, financement, frais. Aucune clé requise et aucun blocage géographique.
  • Lectures privées (/v1/account/) : portefeuille, soldes, ordres, exécutions, configuration.
  • Écritures signées (/v1/trade/) : ordres, annulations, effet de levier, marge isolée, annulation automatique. Chaque écriture est encodée en MessagePack, hachée avec keccak256 et signée sous forme de données typées EIP-712 par la clé proxy.

Les SDK s'occupent de la signature à votre place. Il existe aussi une spécification OpenAPI (/api-spec/perps-openapi.json sur le site de documentation) et une spécification AsyncAPI pour le WebSocket.

Les symboles diffèrent des exemples de la documentation. La documentation affiche BTC-PERP. L'API en production renvoie BTC-USD, SP500-USD (USA500), NAS100-USD (US100), ANT-USD et ainsi de suite. Récupérez la liste des instruments, faites la correspondance sur le symbol réel et enregistrez l'id numérique. Ne copiez pas les ID des exemples : en production, BTC vaut 6 et SP500 vaut 1.

Étape 1 : installer le SDK et ouvrir une session

Installez avec pip install polymarket-client ou npm install @polymarket/client@latest viem. Le bot a besoin de l'adresse de votre portefeuille Polymarket et de la clé privée du signataire qui détient le compte Perps (le compte est rattaché à l'EOA signataire, pas au Safe). L'ouverture d'une session demande une seule signature pour autoriser une nouvelle clé de trading proxy, qui signe ensuite chaque ordre : votre clé de financement ne trade donc jamais. Conservez session.credentials sous forme chiffrée pour reprendre la session plus tard.

import asyncio
import os
from datetime import timedelta

from polymarket import AsyncSecureClient


async def main():
    client = await AsyncSecureClient.create(
        private_key=os.environ["PRIVATE_KEY"],
        wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
    )
    # One signature creates a proxy trading key. Orders are signed by the proxy,
    # not by your wallet key. Credentials expire after one week by default.
    session = await client.open_perps_session(
        expires_in=timedelta(days=1),
        label="perps-bot",
    )
    stored = session.credentials.model_dump(mode="json")  # keep it encrypted

    instruments = await client.fetch_perps_instruments()
    btc = next(i for i in instruments if i.symbol == "BTC-USD")
    print(btc.id, btc.max_leverage, btc.min_notional, btc.price_decimals)


asyncio.run(main())
import { createSecureClient } from "@polymarket/client";
import { privateKey } from "@polymarket/client/viem";

const client = await createSecureClient({
  wallet: process.env.POLYMARKET_WALLET_ADDRESS!,
  signer: privateKey(process.env.PRIVATE_KEY!),
});

// One signature creates a proxy trading key. Orders are signed by the proxy,
// not by your wallet key. Credentials expire after one week by default.
const session = await client.openPerpsSession({
  expiresIn: 24 * 60 * 60 * 1000,
  label: "perps-bot",
});
const stored = session.credentials; // keep it encrypted

const instruments = await client.fetchPerpsInstruments();
const btc = instruments.find((i) => i.symbol === "BTC-USD");
if (!btc) throw new Error("BTC-USD not listed");
console.log(btc.id, btc.maxLeverage, btc.minNotional, btc.priceDecimals);

Déposer depuis le code (deposit_to_perps / depositToPerps) nécessite en plus une clé API Relayer, à créer dans polymarket.com, Paramètres, Clés API. Plus simple et plus sûr : approvisionnez le compte depuis l'application web et tenez le bot à l'écart des mouvements de fonds. Depuis le 5 novembre 2026, les comptes qui utilisent le carnet d'adresses de retrait ne peuvent retirer que vers des adresses enregistrées. Pour les tableaux de bord, utilisez une clé en lecture seule (un proxy dont le libellé commence par read-only:, qui refuse les écritures signées), jamais la clé de trading. Le stockage des clés est traité dans notre chapitre sur les portefeuilles et l'authentification.

Étape 2 : lire les données de marché via REST et WebSocket

Le ticker comporte trois prix : l'index (juste valeur calculée à partir de flux comme Pyth, Chainlink Data Streams et Hyperliquid), le prix de marque (utilisé pour le PnL, la marge, la liquidation et les TP/SL) et le dernier prix (exécution uniquement), ainsi que le taux de financement et l'heure du prochain financement. Basez vos signaux sur le prix de marque ou l'index.

# Inside your async main(), after Step 1 (btc is the BTC-USD instrument)
from polymarket import AsyncPublicClient
from polymarket.streams import PerpsBboSpec

client = AsyncPublicClient()

ticker = await client.fetch_perps_ticker(instrument_id=btc.id)
print(ticker.mark_price, ticker.index_price, ticker.funding_rate)

stream = await client.subscribe(PerpsBboSpec(instrument_id=btc.id))
async for event in stream:
    print(event.payload.bid_price, event.payload.ask_price)
// After Step 1 (btc is the BTC-USD instrument)
import { createPublicClient } from "@polymarket/client";

const client = createPublicClient();

const ticker = await client.fetchPerpsTicker({ instrumentId: btc.id });
console.log(ticker.markPrice, ticker.indexPrice, ticker.fundingRate);

const stream = await client.subscribe([{ topic: "perps.bbo", instrumentId: btc.id }]);
for await (const event of stream) {
  console.log(event.payload.bidPrice, event.payload.askPrice);
}

Sans le SDK, abonnez-vous sur le WebSocket brut avec {"id": 1, "req": "sub", "chs": ["bbo::6"]}. Les canaux incluent bbo::<id>, book::<id>, trades::<id>, tickers::<id> et klines::<id>::1m. Chaque mise à jour porte un numéro de séquence sq : après un trou dans la séquence ou une reconnexion, relisez l'état via REST. Pour les backtests, list_perps_candles / listPerpsCandles pagine l'historique (l'endpoint REST renvoie jusqu'à 1 000 bougies par appel).

Étape 3 : passer des ordres avec take-profit et stop-loss

Un ordre comporte un side (BUY ou SELL), une quantity en unités de l'actif de base, un price facultatif en pUSD et une durée de validité (gtc, ioc ou fok). Le post-only exige GTC ; un ordre reduce-only ne peut que réduire une position. Il n'existe pas d'indicateur long ou short : sans position ouverte, BUY ouvre un long et SELL ouvre un short.

Un ordre bracket rattache un take-profit et un stop-loss à l'ordre d'entrée. Ils restent inactifs jusqu'à l'exécution complète de l'entrée, et sont annulés si l'entrée est annulée ou seulement partiellement exécutée. Les prix ci-dessous sont hypothétiques.

# Inside your async main(), after Step 1 (btc is the BTC-USD instrument)
from polymarket import PerpsTpSlTrigger

result = await session.place_order(
    instrument_id=btc.id,
    side="BUY",
    price="100000",
    quantity="0.01",
    time_in_force="gtc",
    take_profit=PerpsTpSlTrigger(trigger_price="104000"),
    stop_loss=PerpsTpSlTrigger(trigger_price="98000"),
)
print(result.order.id, result.order.status)
// After Step 1 (btc is the BTC-USD instrument)
import { OrderSide, PerpsTimeInForce } from "@polymarket/client";

const result = await session.placeOrder({
  instrumentId: btc.id,
  side: OrderSide.BUY,
  price: "100000",
  quantity: "0.01",
  timeInForce: PerpsTimeInForce.GTC,
  takeProfit: { triggerPrice: "104000" },
  stopLoss: { triggerPrice: "98000" },
});
console.log(result.order.id, result.tpSl.stopLoss?.orderId);

Pour une position ouverte, place_position_tp_sl / placePositionTpSl ajoute des déclencheurs qui ferment l'intégralité de la position. Règles :

  • Les déclencheurs surveillent le prix de marque et envoient un ordre reduce-only. Le TP/SL de position sort au marché : attendez-vous à du slippage dans les carnets peu profonds.
  • Un seul take-profit et un seul stop-loss de position par marché. Déplacer un stop implique d'annuler puis de recréer, ce qui n'est pas atomique.
  • Un déclencheur que le prix de marque a déjà franchi est rejeté, et les prix limites trop éloignés du prix de marque sont refusés.

Pour tester le flux d'ordres à la main avant de l'automatiser, ouvrez le marché BTC sur Polymarket Perps et passez le plus petit ordre autorisé. Voir les exécutions, les frais et le panneau de position rend les réponses de l'API plus faciles à interpréter.

Étape 4 : un squelette de bot avec contrôles de risque dans le code

Le squelette Python ci-dessous n'utilise que des appels documentés du SDK ; la logique de risque est la nôtre. Trois niveaux de protection :

  1. Plafond d'effet de levier. L'effet de levier est fixé à 3x ou au maximum du marché, selon la valeur la plus basse, en marge isolée, et les tailles qui tomberaient dans un palier de risque à plafond inférieur sont refusées.
  2. Coupe-circuits (kill switches). Un fichier HALT, une limite de perte journalière de 5 % et une sortie en cas de liquidation. Le coupe-circuit ferme les positions avec des ordres IOC reduce-only, annule les ordres restants, puis vérifie que les deux ont bien disparu.
  3. Un stop sur chaque position. Des entrées fill-or-kill garantissent qu'aucune exécution partielle ne reste sans protection. Un stop et un take-profit de position suivent chaque exécution ; s'ils sont rejetés, la position est fermée immédiatement.
import asyncio
import logging
import os
from datetime import timedelta
from decimal import Decimal, ROUND_DOWN

from polymarket import AsyncSecureClient, PerpsPositionTpSlTrigger

SYMBOL = "BTC-USD"                   # live API symbol; docs examples say "BTC-PERP"
LEVERAGE_CAP = 3                     # our cap, far below the 50x BTC allows
RISK_PER_TRADE = Decimal("20")       # pUSD we accept losing if the stop fills
STOP_PCT = Decimal("0.02")           # stop 2% from entry
TAKE_PCT = Decimal("0.04")           # take profit 4% from entry
MAX_NOTIONAL = Decimal("2000")       # hard cap per position, in pUSD
MAX_SLIPPAGE = Decimal("0.002")      # worst entry price: ask + 0.2%
MAX_FUNDING = Decimal("0.0005")      # skip longs if funding > 0.05% per hour
DAILY_LOSS_LIMIT = Decimal("0.05")   # kill switch at -5% of start equity
HALT_FILE = "/opt/perps-bot/HALT"    # touch this file to stop the bot


def fit(value: Decimal, decimals: int, sig: int = 5) -> str:
    """Round down to the market's decimals and to 5 significant figures."""
    v = value.quantize(Decimal(1).scaleb(-decimals), rounding=ROUND_DOWN)
    if v != 0:
        step = Decimal(1).scaleb(v.adjusted() - sig + 1)
        if step > Decimal(1).scaleb(-decimals):
            v = v.quantize(step, rounding=ROUND_DOWN)
    return format(v, "f")


def tier_cap(inst, notional: Decimal) -> int:
    """Max leverage allowed for this notional by the market's risk tiers."""
    cap = inst.max_leverage
    for tier in inst.risk_tiers:
        if notional >= Decimal(tier.lower_bound):
            cap = tier.max_leverage
    return cap


async def close_all(session):
    """Close every position with reduce-only IOC orders, then cancel the rest."""
    portfolio = await session.fetch_portfolio()
    for pos in portfolio.positions:
        if pos.size != 0:
            await session.place_order(
                instrument_id=pos.instrument_id,
                side="SELL" if pos.size > 0 else "BUY",
                quantity=abs(pos.size),
                time_in_force="ioc",
                reduce_only=True,
            )
    await session.cancel_all_orders()


async def kill_switch(session, reason: str):
    logging.error("KILL SWITCH: %s", reason)
    for attempt in range(3):
        await close_all(session)
        portfolio = await session.fetch_portfolio()
        open_orders = await session.fetch_open_orders()
        if not open_orders and all(p.size == 0 for p in portfolio.positions):
            return
        await asyncio.sleep(2)
    logging.critical("Positions still open after kill switch: act manually")


async def open_long(client, session, inst):
    ticker = await client.fetch_perps_ticker(instrument_id=inst.id)
    if Decimal(ticker.funding_rate) > MAX_FUNDING:
        return                                     # longs would pay too much
    book = await client.fetch_perps_book(instrument_id=inst.id, depth=10)
    if not book.asks:
        return
    ask = Decimal(book.asks[0].price)
    stop = ask * (1 - STOP_PCT)
    qty = RISK_PER_TRADE / (ask - stop)            # size from the stop, not leverage
    qty = min(qty, MAX_NOTIONAL / ask)
    notional = qty * ask
    if notional < Decimal(inst.min_notional):
        return
    if tier_cap(inst, notional) < LEVERAGE_CAP:
        return                                     # size would break our cap

    entry = await session.place_order(
        instrument_id=inst.id,
        side="BUY",
        price=fit(ask * (1 + MAX_SLIPPAGE), inst.price_decimals),
        quantity=fit(qty, inst.quantity_decimals),
        time_in_force="fok",                       # all or nothing
    )
    if entry.order.status != "filled":
        return

    try:                                           # stop on the whole position
        await session.place_position_tp_sl(
            instrument_id=inst.id,
            take_profit=PerpsPositionTpSlTrigger(
                trigger_price=fit(ask * (1 + TAKE_PCT), inst.price_decimals)),
            stop_loss=PerpsPositionTpSlTrigger(
                trigger_price=fit(stop, inst.price_decimals)),
        )
    except Exception:
        logging.exception("TP/SL rejected: closing the unprotected position")
        await close_all(session)


async def my_signal(client, inst) -> bool:
    """PLACEHOLDER: your strategy goes here. Not part of the SDK."""
    return False


async def main():
    logging.basicConfig(level=logging.INFO)
    client = await AsyncSecureClient.create(
        private_key=os.environ["PRIVATE_KEY"],
        wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
    )
    session = await client.open_perps_session(
        expires_in=timedelta(days=1), label="perps-bot")
    inst = next(i for i in await client.fetch_perps_instruments()
                if i.symbol == SYMBOL)

    # Control 1: leverage cap and isolated margin, set before any order
    await session.update_leverage(
        instrument_id=inst.id,
        leverage=min(LEVERAGE_CAP, inst.max_leverage),
        cross_margin=False,
    )

    # Field names below follow the documented portfolio JSON
    # (margin.total_account_value, in_liquidation). Check them in your SDK.
    start_equity = Decimal((await session.fetch_portfolio()).margin.total_account_value)

    while True:
        portfolio = await session.fetch_portfolio()
        equity = Decimal(portfolio.margin.total_account_value)

        # Control 2: kill switches
        if os.path.exists(HALT_FILE):
            await kill_switch(session, "HALT file found")
            break
        if equity < start_equity * (1 - DAILY_LOSS_LIMIT):
            await kill_switch(session, f"daily loss limit hit: {equity}")
            break
        if portfolio.in_liquidation:
            await kill_switch(session, "account in liquidation")
            break

        in_position = any(p.instrument_id == inst.id and p.size != 0
                          for p in portfolio.positions)
        if not in_position and await my_signal(client, inst):
            await open_long(client, session, inst)   # Control 3 lives here

        await asyncio.sleep(5)


asyncio.run(main())

Le calcul de la taille. La taille découle de la distance du stop, pas de l'effet de levier. Avec une offre de vente BTC hypothétique à 100 000 pUSD et un stop à 2 %, le stop se situe à 98 000. Le risque par unité est de 2 000, la quantité est donc de 20 / 2 000 = 0,01 BTC, soit un notionnel de 1 000 pUSD. À 3x, cela immobilise environ 333 pUSD de marge. Le taux de marge de maintenance de BTC est de 1 % (0,5 / 50x), donc le prix de liquidation du long est de 100 000 x (1 - 1/3) / (1 - 0,01) = environ 67 340, soit une baisse de 32,7 %. Le stop à -2 % se déclenche bien avant. Si le stop est exécuté à son prix de déclenchement, la perte est de 20 pUSD plus les frais : 0,40 à l'ouverture et environ 0,39 à la clôture au taux taker de 0,040 %, soit environ 20,79 pUSD avant slippage. L'effet de levier détermine seulement le montant de marge immobilisé. Il ne change pas la perte au stop.

Avant de passer en réel, ajoutez une limite de trades journalière, des alertes sur les exécutions et les coupe-circuits, et une réconciliation au démarrage (fetch_portfolio, fetch_open_orders, fetch_orders, list_fills). Consultez nos chapitres sur le code de gestion du risque et le paper trading, le guide de l'effet de levier et de la liquidation sur Perps et le guide des taux de financement sur Perps.

Erreurs, nouvelles tentatives et dead man's switch

  • 503 service_unavailable ne prouve pas que la requête a échoué. Relancez les lectures et les changements d'effet de levier avec un backoff et respectez Retry-After. Pour les modifications de solde signées (marge, retraits), ne renvoyez que la requête signée d'origine, à l'identique ; une nouvelle signature constitue un second ajustement.
  • signature expired : signature de plus de 5 minutes. Gardez l'horloge synchronisée.
  • insufficient_margin / invalid_leverage : les contrôles tiennent compte de votre position et de tous les ordres en attente dans le carnet.
  • message_rate_limited : quota WebSocket épuisé. Les clés en lecture seule ont droit à 1 000 messages par minute et par IP (pic de 50) et à quatre connexions par compte et par passerelle ; pour le reste, voir la page Rate Limits de la documentation.
  • Erreurs de format : trop de décimales ou plus de 5 chiffres significatifs. D'où la fonction fit().

L'annulation automatique (auto-cancel) annule tous les ordres ouverts si votre bot cesse de la réarmer. L'échéance doit être fixée au moins 5 secondes à l'avance, et le nombre de déclenchements par jour UTC est limité : désarmez-la donc lors d'un arrêt propre.

// For quoting bots: cancel all resting orders if this process dies
await session.armAutoCancel({ cancelAt: Date.now() + 60_000 });
const rearm = setInterval(() => {
  // A missed re-arm is fail-safe: the armed switch still fires.
  session.armAutoCancel({ cancelAt: Date.now() + 60_000 }).catch(console.error);
}, 20_000);

// On a clean shutdown
clearInterval(rearm);
await session.disarmAutoCancel();
Annulation automatique et stops. La documentation cite l'annulation automatique parmi les causes d'annulation d'un ordre TP/SL : un crash peut donc supprimer le stop d'une position ouverte. L'annulation automatique convient aux bots qui cotent en continu, comme les teneurs de marché. Notre squelette n'a pas d'ordres d'entrée en attente dans le carnet : il laisse donc l'annulation automatique désactivée pour préserver ses stops. Dans tous les cas, c'est un faible effet de levier qui protège un bot planté de la liquidation.

Compétitions, builder codes et règles applicables aux bots

La documentation cite les « bots de trading qui réagissent aux signaux du marché » et les teneurs de marché parmi les usages de l'API. Deux ensembles de règles s'appliquent.

  • Compétitions. Le wash trading, le self-trading, les comptes multiples, le trading principalement destiné à générer du volume et « les bots, scripts ou moyens automatisés destinés à manipuler le Programme » sont interdits. Un bot qui trade réellement est accepté ; un bot qui gonfle artificiellement le volume peut être disqualifié.
  • Builder codes. Une application qui trade pour d'autres utilisateurs peut ajouter des frais allant jusqu'à 10 points de base, avec l'accord de chaque trader. Elle doit vérifier la localisation de chaque utilisateur et bloquer les ordres provenant de juridictions restreintes, pas simplement afficher un avertissement.

Les récompenses de liquidité pour les makers et les compétitions sont traitées dans le guide Polymarket Perps.

Héberger le bot

Un bot à effet de levier ne doit pas tourner sur un ordinateur portable. Il doit maintenir son WebSocket actif, réagir aux exécutions en quelques secondes et survivre à une coupure de la connexion internet domestique. Faites-le tourner sur un VPS sous systemd avec redémarrage automatique, conservez la clé dans un fichier d'environnement lisible uniquement par l'utilisateur du bot, et synchronisez l'horloge. Le passage d'ordres n'est pas autorisé depuis les zones restreintes : n'hébergez donc pas le bot aux États-Unis ou au Canada, et n'utilisez jamais un VPS pour contourner un blocage qui vous concerne. Nous faisons tourner nos propres bots sur TradingVPS (lien affilié : nous touchons une petite commission et le prix que vous payez reste le même). Notre chapitre sur l'hébergement VPS le compare à d'autres fournisseurs en termes de latence, de prix et de régions.

Après le paper trading, approvisionnez le compte avec un petit montant depuis la page Polymarket Perps et tournez à la taille minimale pendant une semaine avant d'augmenter.

À retenir

  • Utilisez les SDK officiels, @polymarket/client ou polymarket-client. Votre portefeuille signe une seule fois ; une clé proxy signe les ordres.
  • Identifiez les marchés par leur symbole réel (BTC-USD, pas BTC-PERP) et enregistrez l'ID numérique.
  • Calculez la taille à partir de la distance du stop, plafonnez l'effet de levier dans le code, utilisez la marge isolée et placez un stop sur chaque position juste après l'exécution.
  • Le TP/SL se déclenche sur le prix de marque et sort au marché. L'annulation automatique peut supprimer les stops.
  • Les bots sont autorisés, la manipulation des compétitions ne l'est pas. Ne tradez jamais depuis un pays restreint.

Questions fréquentes

Polymarket Perps propose-t-il une API pour les bots de trading ?
Oui. Il existe une API REST sur api.perpetuals.polymarket.com, un WebSocket sur ws.perpetuals.polymarket.com, et des SDK officiels : @polymarket/client pour TypeScript et polymarket-client pour Python. La documentation de Polymarket cite les bots de trading et les systèmes de tenue de marché parmi les usages pris en charge.
Faut-il utiliser le SDK TypeScript ou le SDK Python ?
L'un ou l'autre. Les deux couvrent le même flux : créer un client sécurisé, ouvrir une session Perps, récupérer les instruments, passer des ordres avec TP/SL et recevoir les événements en streaming. Le SDK TypeScript utilise viem pour la signature. Le SDK Python est asynchrone. Choisissez le langage dans lequel votre bot est déjà écrit.
Mon bot a-t-il besoin de la clé privée de mon portefeuille principal ?
Uniquement pour ouvrir une session. Cette signature unique autorise une clé de trading proxy, qui signe ensuite les ordres. Les identifiants de session expirent par défaut au bout d'une semaine. Conservez-les chiffrés et utilisez des clés en lecture seule pour les tableaux de bord.
Comment placer un stop-loss via l'API Perps ?
Rattachez des déclencheurs takeProfit et stopLoss à l'ordre d'entrée sous forme d'ordre bracket, ou appelez placePositionTpSl (place_position_tp_sl en Python) sur une position ouverte. Les déclencheurs surveillent le prix de marque et sortent avec un ordre reduce-only. Le TP/SL de position ferme l'intégralité de la position au marché.
Quelle est la taille d'ordre minimale sur Polymarket Perps ?
10 $ de notionnel par ordre, et le dépôt minimum est de 10 pUSD (en novembre 2026). Les prix et les tailles doivent aussi respecter le nombre de décimales de chaque marché et ne pas dépasser 5 chiffres significatifs, sinon l'ordre est rejeté.
Existe-t-il un coupe-circuit ou un dead man's switch ?
Oui. L'annulation automatique annule tous les ordres ouverts si votre bot cesse de la réarmer, et cancelAllOrders supprime les ordres à la demande. La documentation cite l'annulation automatique parmi les causes d'annulation d'un ordre TP/SL : un crash peut donc aussi supprimer vos stops. Codez également votre propre coupe-circuit.
Puis-je faire tourner un bot Polymarket Perps depuis les États-Unis ou le Canada ?
Non. Le passage d'ordres sur Perps n'est pas autorisé depuis les États-Unis, le Canada, Cuba, l'Iran, la Corée du Nord, la Syrie, la Crimée, Donetsk ou Louhansk. N'y hébergez pas de bot, et n'utilisez pas de VPS ni de VPN pour contourner un blocage qui vous concerne.
Les bots sont-ils autorisés dans les compétitions de trading Polymarket Perps ?
Trader avec un bot est autorisé. Le règlement des compétitions interdit le wash trading, le self-trading, les comptes multiples, le trading principalement destiné à générer du volume, et les bots ou scripts destinés à manipuler le programme. Toute infraction peut entraîner une disqualification.