Come costruire un bot di trading per Polymarket
La maggior parte dei tutorial sui bot per Polymarket si basa su SDK che non esistono più. Questo è il percorso attuale dall’inizio alla fine: cosa installare nel 2026, come funziona davvero l’autenticazione, dove sono i buchi nei dati e i problemi che uccidono i bot nella prima settimana.
La maggior parte dei tutorial sui bot per Polymarket è superata
Polymarket è passata a SDK unificati: polymarket-client per Python e @polymarket/client per TypeScript. Sostituiscono py-clob-client, @polymarket/clob-client-v2, @polymarket/builder-relayer-client e @polymarket/builder-signing-sdk. Se una guida ti dice di eseguire pip install py-clob-client, o se il tuo assistente AI genera quell’import, sta lavorando su materiale vecchio. Tutto ciò che segue usa i pacchetti attuali.
Un bot per Polymarket è fatto di sei pezzi: trovare i mercati, leggere i prezzi, decidere, piazzare ordini, gestire le posizioni e restare in vita. I primi due sono facili, il quarto è macchinoso e il sesto è dove la maggior parte dei bot muore davvero. Questa guida percorre l’intero arco con codice verificato, ed è onesta sulle parti davvero difficili.
Passo 0: decidi su cosa opera il tuo bot
Vale la pena farlo prima di scrivere una sola riga, perché determina tutto il resto. I mercati di Polymarket si dividono in due famiglie che non hanno quasi nulla in comune:
| Mercati su eventi | Mercati crypto Up/Down | |
|---|---|---|
| Esempi | Elezioni, sport, premi | btc-updown-5m, eth-updown-15m |
| Durata | Da settimane a mesi | Da 5 minuti a 24 ore |
| Cosa muove il prezzo | Notizie, informazioni, sentiment | Microstruttura e flusso degli ordini |
| Il vantaggio viene da | Essere meglio informati | Essere più veloci o prezzare meglio |
| Operazioni al giorno | Una manciata | Centinaia |
| Sensibilità alla latenza | Bassa | Alta |
Se stai automatizzando, quasi certamente ti interessa la seconda famiglia: alta frequenza, continua e abbastanza meccanica da poter essere codificata. Sono trattati in dettaglio in i mercati Up/Down spiegati.
Passo 1: installa l’SDK attuale
Entrambi gli SDK ti danno un’unica interfaccia client su tutte le API di Polymarket, modelli tipizzati, paginazione coerente e firma integrata: una grande quantità di lavoro macchinoso che non vuoi reimplementare.
pip install polymarket-client
# or: uv add polymarket-client / poetry add polymarket-clientCi sono quattro client Python, e scegliere quello giusto conta più di quanto sembri:
| Client | Dati pubblici | Trading | Tempo reale |
|---|---|---|---|
AsyncPublicClient | Sì | No | Sì |
AsyncSecureClient | Sì | Sì | Sì |
PublicClient | Sì | No | No |
SecureClient | Sì | Sì | No |
subscribe(). Ai bot servono le varianti async; quelle sincrone sono per script e notebook.Inizia con il client pubblico
Puoi costruire e testare la scoperta dei mercati, la lettura dei prezzi, la generazione dei segnali e l’intera pipeline di dati con AsyncPublicClient: niente chiavi, niente wallet, nessun rischio. Passa ad AsyncSecureClient solo quando sei pronto a piazzare un ordine. La maggior parte dei bug emerge molto prima.
Passo 2: trova i mercati
La scoperta dei mercati pubblici non richiede alcuna credenziale. Il paginatore dell’SDK è coerente su tutti i metodi di elenco, quindi questo schema vale in generale.
import asyncio
from polymarket import AsyncPublicClient
async def main() -> None:
async with AsyncPublicClient() as client:
pages = client.list_markets(closed=False, page_size=50)
# Iterate items directly when page boundaries do not matter.
async for market in pages.iter_items():
if "updown" in (market.slug or ""):
print(market.slug, market.condition_id)
asyncio.run(main())Due cose da tenere a mente. Primo, page.next_cursor è un cursore opaco: salvalo così com’è se vuoi riprendere una scansione in seguito, e non provare ad analizzarlo o a costruirne uno. Secondo, /markets ha il rate limit più stretto di tutta la piattaforma, 300 req / 10s, quindi metti in cache i metadati dei mercati invece di rielencarli in un ciclo stretto. Tutti i numeri sono nel riferimento ai rate limit.
Passo 3: autenticati
Per fare trading serve un wallet. L’SDK Python costruisce il signer a partire da una chiave privata locale:
import os
from polymarket import AsyncSecureClient
client = await AsyncSecureClient.create(
private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
)Sotto il cofano, Polymarket usa due livelli di autenticazione: L1 è una firma del wallet EIP-712 che dimostra che controlli l’indirizzo e ti permette di creare o derivare le credenziali API; L2 firma ogni richiesta privata con quelle credenziali usando HMAC-SHA256. L’SDK gestisce entrambi, ed è il motivo principale per usarlo.
I due errori di autenticazione che incontrerai
Credenziali incomplete: L2 richiede la chiave, il secret e la passphrase. Due su tre producono una richiesta ben formata con una firma non verificabile. Deriva dell’orologio: la firma contiene un timestamp, quindi un container con l’orologio sballato di qualche secondo viene respinto. Entrambi si presentano con lo stesso poco utile Unauthorized/Invalid api key. La decodifica completa è nel riferimento agli errori.
Gestione della chiave
Quella chiave privata può spostare fondi. Tienila in variabili d’ambiente o in un secret manager: mai nel codice sorgente, mai in un’immagine container, mai nel repo che stai per pushare. Usa un wallet dedicato, finanziato solo con quanto il bot può permettersi di perdere, così un bug è limitato dal saldo e non dal tuo giudizio alle 3 di notte.
Passo 4: ottieni i prezzi in tempo reale
L’errore architetturale più comune in un primo bot è fare polling di /book a intervalli regolari. Consuma il tuo budget di rate limit, aggiunge latenza e scala male. Usa invece le sottoscrizioni: l’SDK unisce più feed in un unico stream di eventi.
from polymarket.streams import MarketSpec
async with await client.subscribe([MarketSpec(token_ids=[token_id])]) as stream:
async for event in stream:
# MarketBookEvent | MarketPriceChangeEvent | MarketLastTradePriceEvent
# | MarketTickSizeChangeEvent | MarketBestBidAskEvent
# | NewMarketEvent | MarketResolvedEvent
handle(event)Se ti connetti al WebSocket grezzo invece di usare l’SDK, devi inviare un PING ogni 10 secondi o la connessione viene chiusa, e ti serve custom_feature_enabled: true per ricevere gli eventi best_bid_ask, new_market e market_resolved. Questi aspetti e gli schemi di riconnessione sono trattati nella guida ai WebSocket. A parte questo, i prezzi di riferimento sono passati a PolyBolt il 15 settembre 2026: se il tuo bot riceve lo spot in streaming, vedi la guida alla migrazione.
Passo 5: piazza un ordine
Un ordine a mercato è la cosa più semplice che funzioni, e amount è espresso in pUSD che sei disposto a spendere, non in quote:
market = await client.get_market(slug="<market-slug>")
token_id = market.outcomes.yes.token_id
assert token_id is not None
response = await client.place_market_order(
token_id=token_id,
side="BUY",
amount="10", # spend up to 10 pUSD
)
if not response.ok:
raise RuntimeError(response.message)
# Settlement is on-chain and asynchronous — this waits for it.
hashes = await client.wait_for_order_fill_settlement(response)Per gli ordini limite in attesa, ci sono due regole che ti morderanno prima di qualsiasi altra cosa. I prezzi devono stare sulla griglia dei tick del mercato: chiama GET /tick-size per ogni mercato invece di dare per scontato 0.01, perché la dimensione del tick varia e può restringersi man mano che un mercato matura. E gli ordini sotto la size minima del mercato vengono respinti subito. Entrambi tornano come 400 con messaggi specifici, elencati nel riferimento agli errori.
Un 200 su un batch non significa successo
Quando invii più ordini, gli errori dei singoli ordini vengono restituiti dentro l’array della risposta 200, come campi errorMsg individuali. Itera l’array e controlla ogni voce. I bot che controllano solo lo stato HTTP credono in silenzio di avere posizioni che non hanno: una classe di bug davvero pericolosa.
Passo 6: scopri se la strategia funziona
Tutto ciò che c’è sopra è idraulica, e l’idraulica è la metà facile. La domanda difficile è se la tua strategia fa soldi, ed è qui che costruire un bot per Polymarket si separa nettamente dal costruire un bot per il crypto spot.
Non esiste una testnet. Niente sandbox, niente API demo, niente endpoint di paper trading. Queste parole non compaiono da nessuna parte nella documentazione di Polymarket. Il tuo primo ordine reale è fatto con soldi veri contro controparti reali. Vedi Polymarket ha una testnet? per i quattro modi di aggirare il problema.
E non esiste un order book storico. Una volta che un mercato si risolve, il suo book restituisce 404. Conserva una serie di prezzi di circa un punto al minuto, e solo se la chiedi con un inizio e una fine espliciti:
TOK=<token_id_of_a_resolved_market>
START=<epoch seconds the window opened>
END=$((START + 300))
curl -s "https://clob.polymarket.com/book?token_id=$TOK"
# {"error":"No orderbook exists for the requested token id"} HTTP 404
curl -s "https://clob.polymarket.com/prices-history?market=$TOK&startTs=$START&endTs=$END&fidelity=1"
# about 6 points for a 5-minute market; interval=max returns [] for older onesQuindi non puoi fare backtest partendo da Polymarket. Ti servono snapshot point-in-time che qualcuno ha registrato mentre i mercati erano attivi. È quello che PolyTest fornisce per i mercati crypto Up/Down: 240M+ snapshot, 8 livelli di profondità del book per lato, timestamp sotto il secondo, mercati risolti conservati:
import os, requests
BASE = "https://api.polytest.io/api/v1"
H = {"X-API-Key": os.environ["POLYTEST_KEY"]}
markets = requests.get(f"{BASE}/markets",
params={"coin": "btc", "market_type": "5m", "limit": 50},
headers=H).json()["markets"]
snaps = requests.get(f"{BASE}/markets/{markets[0]['id']}/snapshots",
params={"include_orderbook": "true"},
headers=H).json()["snapshots"]
def simulate_fill(levels, qty):
"""Walk the ladder. Mid-price is not a price you can trade at."""
filled = cost = 0.0
for lvl in levels:
take = min(lvl["size"], qty - filled)
cost += take * lvl["price"]
filled += take
if filled >= qty:
break
return cost / filled if filled >= qty else None
print(simulate_fill(snaps[0]["orderbook"]["asks"], 500))L’errore che rende inutile un backtest
Se fai backtest sul prezzo medio stai testando un’identità aritmetica, non una strategia. Gli spread Up/Down sono regolarmente di 2–5 centesimi su un contratto che si regola a $1, spesso più ampi del vantaggio dichiarato. Scorri il book e prendi l’esecuzione che avresti davvero ottenuto. Questo solo cambiamento uccide la maggior parte delle strategie, ed è esattamente ciò che vuoi che faccia, a basso costo, prima di finanziarle.
Passo 7: sopravvivi al contatto con la produzione
Un bot che opera correttamente per un’ora e poi si blocca è peggio di nessun bot. Questi sono i problemi che si verificano davvero, in ordine approssimativo di frequenza:
| Problema | Cosa vedi | Gestione |
|---|---|---|
| Rate limit | Latenza in aumento, non errori | Cloudflare rallenta invece di rifiutare: tieni d’occhio il p99, non il tasso di errore |
| Riavvio del motore di matching | 425 Too Early | Riprova con backoff; non generare alert sui casi singoli |
| Exchange in pausa | 503 | Smetti di aprire posizioni. Cancella se consentito |
| Modalità cancel-only | 503 sui nuovi ordini | Il percorso di cancellazione deve funzionare indipendentemente da quello di ingresso |
| Modalità post-only | 503 + retry_after_seconds | Aspetta esattamente quel tempo, poi riprova |
| Signer non corrispondente | Errore 400 sul signer dell’ordine | Credenziali vecchie di un altro wallet: derivale di nuovo |
| Caduta del WebSocket | Silenzio | Nessun dato non equivale a nessun cambiamento: tieni traccia dell’età dell’ultimo messaggio |
| Deriva dell’orologio | 401 su un bot che ieri funzionava | Usa NTP; è il problema che fa perdere più tempo |
Il silenzio è lo stato pericoloso
Un WebSocket caduto non genera un’eccezione: smette semplicemente di consegnare messaggi. Un bot che ha una posizione aperta e non riceve aggiornamenti crederà tranquillamente che il mercato sia fermo all’ultimo prezzo visto. Tieni traccia dell’età dell’ultimo messaggio e tratta i dati vecchi come una condizione di errore, non come calma.
- Testa il percorso di cancellazione prima di quello di ingresso. Non riuscire a uscire è molto peggio che non riuscire a entrare.
- Limita l’esposizione nel codice, non nella tua testa. Un limite rigido di posizione trasforma un bug logico in una piccola perdita invece che in una perdita illimitata.
- Costruisci un kill switch e testalo davvero. Un kill switch non testato è un commento.
- Aggiungi jitter al lavoro schedulato. Worker che si svegliano esattamente allo stesso secondo creano un picco sincronizzato molto sopra la tua frequenza media.
- Registra ogni richiesta e risposta per la prima settimana. Ti serviranno, e non potrai ricostruirle dopo.
- Genera alert per categorie, non per messaggi. Polymarket inserisce ID degli ordini e prezzi nelle stringhe di errore, quindi gli alert sulla stringa grezza sono puro rumore.
Un ordine di sviluppo realistico
La sequenza che fa perdere meno tempo e soldi:
- Integrazione in sola lettura, client pubblico, niente chiavi. Verifica scoperta dei mercati, parsing, paginazione e backoff. Un giorno, gratis.
- Backtest della strategia su book storici con una simulazione onesta delle esecuzioni. La maggior parte delle idee muore qui. È proprio questo lo scopo.
- Paper trading live per almeno una settimana: registra gli ordini previsti invece di inviarli. Verifica uptime, riconnessioni e tempistiche.
- Vai live con la size minima, con un limite rigido all’esposizione e un kill switch testato.
- Aumenta le dimensioni solo quando i numeri live corrispondono a quelli su carta. Se divergono, il tuo modello di esecuzione era sbagliato: torna al passo 2.
I passi 1, 3 e 4 li costruisci in pochi giorni. Il passo 2 richiede dati che Polymarket non conserva, ed è anche il passo che più sicuramente fa risparmiare soldi. Inizia una prova gratuita su PolyTest: basta per scoprire se la tua idea sopravvive allo spread.
Domande frequenti
- Come costruisco un bot di trading per Polymarket?
- Installa l’SDK unificato attuale: polymarket-client per Python o @polymarket/client per TypeScript. Usa AsyncPublicClient per trovare i mercati e leggere i prezzi senza credenziali, poi AsyncSecureClient con una chiave privata per fare trading. Iscriviti al canale market del WebSocket invece di fare polling dei prezzi, piazza gli ordini con place_market_order e gestisci le risposte 425, 429 e 503 con un backoff. Prima di andare live, fai backtest su snapshot storici dell’order book con una simulazione realistica delle esecuzioni, perché Polymarket non ha una testnet e non conserva lo storico dell’order book.
- Quale SDK dovrei usare per un bot per Polymarket nel 2026?
- Usa gli SDK unificati: polymarket-client per Python o @polymarket/client per TypeScript. Sostituiscono i vecchi pacchetti py-clob-client, @polymarket/clob-client-v2, @polymarket/builder-relayer-client e @polymarket/builder-signing-sdk. Un SDK Rust unificato è in sviluppo. La maggior parte dei tutorial e del codice generato dall’AI fa ancora riferimento ai pacchetti deprecati, quindi controlla gli import prima di fidarti di uno snippet.
- Posso fare paper trading su Polymarket prima di rischiare soldi veri?
- Non tramite Polymarket: non c’è una testnet, una sandbox né un’API demo. Puoi costruirti da solo uno strato di paper trading facendo girare il ciclo della tua strategia live sui dati di mercato di produzione e registrando gli ordini previsti insieme allo stato del book in quell’istante, invece di inviarli. Questo dimostra che il tuo bot è solido dal punto di vista operativo, ma presume le esecuzioni, quindi non ti insegnerà nulla sulla posizione in coda o sull’impatto sul mercato.
- Come faccio il backtest di un bot di trading per Polymarket?
- Ti servono snapshot storici dell’order book di terzi, perché l’API di Polymarket restituisce 404 per il book di un mercato risolto e conserva solo circa un punto al minuto di storico dei prezzi. Scarica snapshot point-in-time con la profondità completa, riproducili in ordine cronologico senza sbirciare avanti e simula le esecuzioni scorrendo i livelli del book invece di assumere il prezzo medio. Gli spread Up/Down di 2-5 centesimi su un contratto da $1 di solito sono più grandi del vantaggio dichiarato, quindi i backtest sul prezzo medio sono fuorvianti.
- Perché il mio bot per Polymarket riceve Unauthorized/Invalid api key?
- Il più delle volte per uno di due motivi. O il tuo set di credenziali è incompleto (l’autenticazione L2 richiede insieme la chiave API, il secret e la passphrase), oppure l’orologio di sistema è andato alla deriva, perché la firma della richiesta contiene un timestamp e pochi secondi di deriva la invalidano. Meno spesso, hai derivato le credenziali con un wallet diverso da quello con cui stai facendo trading.
- Per un bot per Polymarket mi serve un WebSocket o posso fare polling?
- Usa il WebSocket. Fare polling di /book a intervalli regolari consuma il budget di rate limit, aggiunge latenza e scala male. Iscriviti al canale market del CLOB per gli aggiornamenti pubblici del book e dei prezzi, e al canale user per gli aggiornamenti dei tuoi ordini e delle tue operazioni. Se ti connetti al WebSocket grezzo invece che tramite un SDK, invia un PING ogni 10 secondi per mantenere viva la connessione.
Ottieni i dati storici che Polymarket non conserva
PolyTest registra i mercati crypto Up/Down di Polymarket mentre sono attivi: 240M+ snapshot con 8 livelli di profondità dell’order book, timestamp sotto il secondo e mercati risolti conservati. Inizia con una prova gratuita di 3 giorni.
Continua a leggere
Il vantaggio sul ritardo dello spot su Polymarket è reale. Ed è profondo circa $100.
Compra il lato che lo spot ha già confermato, prima che Polymarket aggiorni il prezzo. A differenza della maggior parte delle strategie decantate, questa sopravvive al confronto con i dati, con uno z-score di 15. Il motivo per cui non ha reso ricchi tutti sta nell’order book.
WebSocket di Polymarket: dati in tempo reale che non cadono
Fare polling dell’order book è il modo più comune di bruciare un budget di rate limit senza alcun beneficio. Ecco i quattro stream, le opzioni di sottoscrizione che nessuno documenta e il guasto in cui il tuo bot riceve silenzio e lo scambia per calma.
L’SDK Python di Polymarket nel 2026 (e la migrazione da py-clob-client)
Se il tuo codice importa ancora ClobClient da py_clob_client, è costruito su un pacchetto superato, come la maggior parte del codice Polymarket che un assistente AI scriverà per te. Ecco l’SDK attuale e come fare il passaggio.