Tutorial sui bot di Polymarket · Capitolo 24 di 32

Polymarket Perps ha un'API pubblica completa, con SDK ufficiali per TypeScript e Python. In questo capitolo costruiamo un bot sull'interfaccia reale: autenticazione con una chiave di trading proxy, dati di mercato via REST e WebSocket, ordini con take-profit e stop-loss, e i controlli del rischio che impediscono a un bot con leva di svuotare il conto.

Build your own theme park, free in your browserPubblicità Fai pubblicità qui
Prima di iniziare. Non è consentito inviare ordini su Perps da Stati Uniti, Canada, Cuba, Iran, Corea del Nord, Siria, Crimea, Donetsk o Luhansk, e polymarket.com blocca anche altri paesi. Usare un bot o un server all'estero non cambia nulla. Con la leva un bug fa perdere denaro in fretta, quindi fai i test con la dimensione minima. Non conosci ancora Perps? Parti dalla guida a Polymarket Perps.

Cosa trovi in questo capitolo

  • I numeri chiave per chi sviluppa bot
  • Com'è strutturata l'API di Perps
  • Passo 1: installa l'SDK e apri una sessione
  • Passo 2: leggi i dati di mercato via REST e WebSocket
  • Passo 3: invia ordini con take-profit e stop-loss
  • Passo 4: lo scheletro di un bot con i controlli del rischio nel codice
  • Errori, dead man's switch, regole per i bot e hosting

Ogni metodo dell'SDK ed ogni endpoint citati qui provengono dalla documentazione di Polymarket su Perps (docs.polymarket.com/perps, consultata il 6 novembre 2026). La logica scritta da noi è segnalata nei commenti, e la funzione della strategia è un segnaposto dichiarato.

I numeri chiave per chi sviluppa bot (a novembre 2026)

VoceValore
URL di base RESThttps://api.perpetuals.polymarket.com
WebSocketwss://ws.perpetuals.polymarket.com/v1/ws
SDK TypeScript@polymarket/client (con viem per la firma)
SDK Pythonpolymarket-client (asincrono)
Dati pubblici/v1/info/*, senza autenticazione
Letture private/v1/account/* con gli header polymarket-proxy e polymarket-secret
Scritture firmate/v1/trade/*, firma EIP-712 della chiave proxy, valida 5 minuti
Credenziali di sessioneScadono dopo una settimana, salvo impostazioni diverse
Ordine minimo10 $ di valore nozionale; deposito minimo 10 pUSD
Ordine a mercato massimo1 milione di $ sui mercati a 50x e 20x, 500.000 $ sulla maggior parte degli altri, 50.000 $ sulle monete a 3x e 5x
Formato di prezzo e quantitàStringhe decimali, entro i decimali del mercato e con al massimo 5 cifre significative
Leva massima50x (BTC, ETH, USA500, US100), altrimenti 20x, 10x, 5x o 3x a seconda del mercato, più bassa per le posizioni grandi
Commissioni (livello base)Taker 0,040%, maker 0,0125%; ANT a metà prezzo
FinanziamentoOrario, con un tetto di +/-4% all'ora
Attivazione TP/SLPrezzo di riferimento (mark), non l'ultimo scambio
Keepalive WebSocketPing circa ogni 25 secondi; considera la connessione inattiva dopo circa 65 secondi di silenzio
Aggiornamento del tickerFino a 10 secondi di ritardo

Com'è strutturata l'API di Perps

Perps è un exchange ibrido: l'abbinamento degli ordini avviene offchain, mentre custodia e regolamento sono su Polygon. Solo depositi e prelievi sono onchain, quindi non si paga gas per ogni ordine. L'API ha tre livelli:

  • Dati pubblici (/v1/info/): strumenti, ticker, libro ordini, candele, scambi, finanziamento, commissioni. Non serve una chiave e non c'è blocco geografico.
  • Letture private (/v1/account/): portafoglio, saldi, ordini, esecuzioni, configurazione.
  • Scritture firmate (/v1/trade/): ordini, cancellazioni, leva, margine isolato, cancellazione automatica. Ogni scrittura viene codificata in MessagePack, sottoposta a hash con keccak256 e firmata come dati tipizzati EIP-712 dalla chiave proxy.

Gli SDK gestiscono la firma al posto tuo. Esistono anche una specifica OpenAPI (/api-spec/perps-openapi.json sul sito della documentazione) e una specifica AsyncAPI per il WebSocket.

I simboli sono diversi da quelli degli esempi nella documentazione. La documentazione mostra BTC-PERP. L'API reale restituisce BTC-USD, SP500-USD (USA500), NAS100-USD (US100), ANT-USD e così via. Scarica l'elenco degli strumenti, cerca il symbol reale e salva l'id numerico. Non copiare gli ID dagli esempi: nell'API reale BTC è 6 e SP500 è 1.

Passo 1: installa l'SDK e apri una sessione

Installa con pip install polymarket-client oppure npm install @polymarket/client@latest viem. Il bot ha bisogno dell'indirizzo del tuo wallet Polymarket e della chiave privata del firmatario che possiede il conto Perps (il conto è legato all'EOA firmatario, non al Safe). Aprire una sessione richiede una sola firma per autorizzare una nuova chiave di trading proxy, che poi firma ogni ordine: così la chiave che custodisce i fondi non fa mai trading. Salva session.credentials in forma cifrata per riprendere la sessione in seguito.

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);

Per depositare dal codice (deposit_to_perps / depositToPerps) serve anche una chiave API del Relayer, da polymarket.com, Impostazioni, Chiavi API. La soluzione più semplice e sicura: finanzia il conto dall'app web e tieni il bot lontano dai movimenti di denaro. Dal 5 novembre 2026, i conti che usano la rubrica degli indirizzi di prelievo possono prelevare solo verso indirizzi salvati. Per le dashboard usa una chiave di sola lettura (un proxy con etichetta read-only:, che rifiuta le scritture firmate), mai la chiave di trading. La custodia delle chiavi è trattata nel nostro capitolo su wallet e autenticazione.

Passo 2: leggi i dati di mercato via REST e WebSocket

Il ticker riporta tre prezzi: index (il valore equo ricavato da fonti come Pyth, Chainlink Data Streams e Hyperliquid), mark (il prezzo di riferimento usato per PnL, margine, liquidazione e TP/SL) e last (solo per l'esecuzione), oltre al tasso di finanziamento e all'orario del prossimo pagamento. Basa i segnali sul mark o sull'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);
}

Senza SDK, iscriviti sul WebSocket grezzo con {"id": 1, "req": "sub", "chs": ["bbo::6"]}. Tra i canali ci sono bbo::<id>, book::<id>, trades::<id>, tickers::<id> e klines::<id>::1m. Ogni aggiornamento ha un numero di sequenza sq: dopo un buco nella sequenza o una riconnessione, rileggi lo stato via REST. Per i backtest, list_perps_candles / listPerpsCandles scorre lo storico a pagine (l'endpoint REST restituisce fino a 1.000 candele per chiamata).

Passo 3: invia ordini con take-profit e stop-loss

Un ordine ha un side (BUY o SELL), una quantity in unità dell'asset sottostante, un price facoltativo in pUSD e una validità temporale (gtc, ioc o fok). Il post-only richiede GTC; il reduce-only può solo ridurre una posizione. Non esiste un flag long o short: senza posizioni aperte, BUY apre un long e SELL apre uno short.

Un ordine bracket collega all'ingresso un take-profit e uno stop-loss. Restano inattivi finché l'ingresso non viene eseguito per intero, e vengono cancellati se l'ingresso è cancellato o eseguito solo in parte. I prezzi qui sotto sono ipotetici.

# 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);

Per una posizione già aperta, place_position_tp_sl / placePositionTpSl aggiunge trigger che chiudono l'intera posizione. Le regole:

  • I trigger osservano il prezzo di riferimento (mark) e inviano un ordine reduce-only. Il TP/SL di posizione esce a mercato, quindi aspettati slippage sui book poco profondi.
  • Un solo take-profit e un solo stop-loss di posizione per mercato. Spostare uno stop significa cancellarlo e poi crearne uno nuovo, un'operazione non atomica.
  • Un trigger già superato dal prezzo di riferimento viene rifiutato, e anche i prezzi limite troppo lontani dal prezzo di riferimento vengono respinti.

Per provare il flusso degli ordini a mano prima di automatizzarlo, apri il mercato BTC su Polymarket Perps e invia l'ordine più piccolo consentito. Vedere esecuzioni, commissioni e pannello delle posizioni rende più facile interpretare le risposte dell'API.

Passo 4: lo scheletro di un bot con i controlli del rischio nel codice

Lo scheletro Python qui sotto usa solo chiamate documentate dell'SDK; la logica di rischio è nostra. Tre livelli di protezione:

  1. Tetto alla leva. La leva è impostata a 3x o al massimo del mercato, se più basso, con margine isolato, e le dimensioni che ricadono in una fascia di rischio con tetto più basso vengono rifiutate.
  2. Interruttori di emergenza. Un file HALT, un limite di perdita giornaliera del 5% e l'uscita in caso di liquidazione. L'interruttore chiude le posizioni con ordini IOC reduce-only, cancella gli ordini rimasti e poi verifica che non ci sia più nulla di aperto.
  3. Uno stop su ogni posizione. Gli ingressi fill-or-kill evitano esecuzioni parziali non protette. Dopo ogni esecuzione vengono impostati stop e take-profit di posizione; se vengono rifiutati, la posizione viene chiusa subito.
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())

Il calcolo della dimensione. La dimensione dipende dalla distanza dello stop, non dalla leva. Con un ask ipotetico di BTC a 100.000 pUSD e uno stop al 2%, lo stop si trova a 98.000. Il rischio per unità è 2.000, quindi la quantità è 20 / 2.000 = 0,01 BTC, per un valore nozionale di 1.000 pUSD. A 3x servono circa 333 pUSD di margine. Il tasso di margine di mantenimento di BTC è 1% (0,5 / 50x), quindi il prezzo di liquidazione del long è 100.000 x (1 - 1/3) / (1 - 0,01) = circa 67.340, cioè un calo del 32,7%. Lo stop a -2% scatta molto prima. Se lo stop viene eseguito al prezzo di attivazione, la perdita è di 20 pUSD più le commissioni: 0,40 in apertura e circa 0,39 in chiusura con la tariffa taker dello 0,040%, quindi circa 20,79 pUSD prima dello slippage. La leva decide solo quanto margine resta impegnato. Non cambia la perdita allo stop.

Prima di andare live, aggiungi un limite giornaliero di operazioni, avvisi su esecuzioni e interruttori di emergenza, e una riconciliazione all'avvio (fetch_portfolio, fetch_open_orders, fetch_orders, list_fills). Consulta i nostri capitoli sul codice per la gestione del rischio e sul paper trading, la guida a leva e liquidazione su Perps e la guida ai tassi di finanziamento su Perps.

Errori, nuovi tentativi e dead man's switch

  • 503 service_unavailable non dimostra che la richiesta sia fallita. Ripeti letture e modifiche della leva con un backoff e rispetta Retry-After. Per le variazioni di saldo firmate (margine, prelievi), invia di nuovo solo l'esatta richiesta firmata originale: una nuova firma equivale a una seconda modifica.
  • signature expired: firma più vecchia di 5 minuti. Tieni l'orologio sincronizzato.
  • insufficient_margin / invalid_leverage: i controlli considerano la tua posizione più tutti gli ordini in attesa.
  • message_rate_limited: hai esaurito il budget del WebSocket. Le chiavi di sola lettura hanno 1.000 messaggi al minuto per IP (burst di 50) e quattro connessioni per conto per gateway; per il resto consulta la pagina Rate Limits della documentazione.
  • Errori di formato: troppi decimali o più di 5 cifre significative. Da qui la funzione fit().

La cancellazione automatica cancella tutti gli ordini aperti se il bot smette di riattivarla. La scadenza deve essere almeno 5 secondi nel futuro e le attivazioni per giorno UTC sono limitate, quindi disattivala quando arresti il bot in modo ordinato.

// 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();
Cancellazione automatica e stop. La documentazione indica la cancellazione automatica come uno dei modi in cui un ordine TP/SL può essere cancellato, quindi un crash può eliminare lo stop di una posizione aperta. La cancellazione automatica è adatta ai bot che quotano prezzi, come i market maker. Il nostro scheletro non ha ingressi in attesa nel libro ordini, quindi la lascia disattivata per mantenere attivi gli stop. In ogni caso, è la leva bassa che protegge dalla liquidazione un bot andato in crash.

Competizioni, builder code e regole per i bot

La documentazione elenca "trading bots that react to market signals" (bot di trading che reagiscono ai segnali di mercato) e i market maker tra gli usi previsti dell'API. Valgono due insiemi di regole.

  • Competizioni. Sono vietati wash trading, self-trading, account multipli, trading fatto principalmente per generare volume e "bots, scripts, or automated means intended to manipulate the Program" (bot, script o mezzi automatici volti a manipolare il programma). Un bot che fa trading reale va bene; uno che gonfia il volume può essere squalificato.
  • Builder code. Un'app che fa trading per conto di altri utenti può aggiungere una commissione fino a 10 punti base, con l'approvazione di ciascun trader. Deve verificare la posizione geografica di ogni utente e bloccare gli ordini provenienti da giurisdizioni soggette a restrizioni, non limitarsi a un avviso.

Le ricompense per la liquidità dei maker e le competizioni sono trattate nella guida a Polymarket Perps.

Hosting del bot

Un bot con leva non dovrebbe girare su un portatile. Deve mantenere attivo il WebSocket, reagire alle esecuzioni in pochi secondi e resistere a un'interruzione della connessione di casa. Eseguilo su un VPS sotto systemd con riavvio automatico, conserva la chiave in un file di ambiente leggibile solo dall'utente del bot e sincronizza l'orologio. Non è consentito inviare ordini da località soggette a restrizioni, quindi non ospitare il bot negli Stati Uniti o in Canada, e non usare mai un VPS per aggirare un blocco che si applica a te. Facciamo girare i nostri bot su TradingVPS (link di affiliazione: riceviamo una piccola commissione e il prezzo per te resta lo stesso). Il nostro capitolo sull'hosting VPS lo confronta con altri fornitori per latenza, prezzo e regioni.

Dopo il paper trading, finanzia il conto con un piccolo importo dalla pagina di Polymarket Perps e opera con la dimensione minima per una settimana prima di aumentare.

Punti chiave

  • Usa gli SDK ufficiali, @polymarket/client o polymarket-client. Il tuo wallet firma una sola volta; poi è una chiave proxy a firmare gli ordini.
  • Identifica i mercati tramite il simbolo reale (BTC-USD, non BTC-PERP) e salva l'ID numerico.
  • Calcola la dimensione dalla distanza dello stop, limita la leva nel codice, usa il margine isolato e metti uno stop su ogni posizione subito dopo l'esecuzione.
  • Il TP/SL si attiva sul prezzo di riferimento (mark) ed esce a mercato. La cancellazione automatica può eliminare gli stop.
  • I bot sono ammessi, manipolare le competizioni no. Non fare mai trading da un paese soggetto a restrizioni.

Domande frequenti

Polymarket Perps ha un'API per i bot di trading?
Sì. C'è un'API REST su api.perpetuals.polymarket.com, un WebSocket su ws.perpetuals.polymarket.com e gli SDK ufficiali: @polymarket/client per TypeScript e polymarket-client per Python. La documentazione di Polymarket indica i bot di trading e i sistemi di market making tra gli usi supportati.
Meglio l'SDK TypeScript o quello Python?
Vanno bene entrambi. Coprono lo stesso flusso: creare un client sicuro, aprire una sessione Perps, scaricare gli strumenti, inviare ordini con TP/SL e ricevere gli eventi in streaming. L'SDK TypeScript usa viem per la firma. L'SDK Python è asincrono. Scegli il linguaggio in cui è già scritto il tuo bot.
Il mio bot ha bisogno della chiave privata del mio wallet principale?
Solo per aprire una sessione. Quella singola firma autorizza una chiave di trading proxy, e da quel momento è il proxy a firmare gli ordini. Le credenziali di sessione scadono dopo una settimana, salvo impostazioni diverse. Salvale in forma cifrata e usa chiavi di sola lettura per le dashboard.
Come imposto uno stop-loss tramite l'API di Perps?
Collega i trigger takeProfit e stopLoss all'ordine di ingresso come bracket, oppure chiama placePositionTpSl (place_position_tp_sl in Python) su una posizione aperta. I trigger osservano il prezzo di riferimento (mark) ed escono con un ordine reduce-only. Il TP/SL di posizione chiude l'intera posizione a mercato.
Qual è la dimensione minima di un ordine su Polymarket Perps?
10 $ di valore nozionale per ordine, e il deposito minimo è di 10 pUSD (a novembre 2026). Inoltre prezzi e quantità devono rispettare i decimali di ciascun mercato e avere al massimo 5 cifre significative, altrimenti l'ordine viene rifiutato.
Esiste un interruttore di emergenza o un dead man's switch?
Sì. La cancellazione automatica cancella tutti gli ordini aperti se il bot smette di riattivarla, e cancelAllOrders elimina gli ordini su richiesta. La documentazione indica la cancellazione automatica come uno dei modi in cui un ordine TP/SL può essere cancellato, quindi un crash può eliminare anche i tuoi stop. Scrivi anche un tuo interruttore di emergenza nel codice.
Posso far girare un bot per Polymarket Perps dagli Stati Uniti o dal Canada?
No. Non è consentito inviare ordini su Perps da Stati Uniti, Canada, Cuba, Iran, Corea del Nord, Siria, Crimea, Donetsk o Luhansk. Non ospitare lì un bot e non usare un VPS o una VPN per aggirare un blocco che si applica a te.
I bot sono ammessi nelle competizioni di trading di Polymarket Perps?
Fare trading con un bot è consentito. Il regolamento delle competizioni vieta wash trading, self-trading, account multipli, trading fatto principalmente per generare volume e bot o script volti a manipolare il programma. Violare queste regole può portare alla squalifica.