Polymarket Bot Tutorial · Capitolo 8 di 32
Polymarket CLOB API per bot: endpoint REST per snapshot del order book, iscrizioni WebSocket per aggiornamenti in tempo reale, parsing di bids/asks, calcolo di mid-price e depth, esempi di codice.
Cosa copre questo capitolo
La CLOB API è il punto in cui gli ordini vengono firmati, inviati, matched e dove vive il order book. Polymarket ha due generazioni di SDK — la v1 deprecata e la v2 attuale. Questo capitolo copre solo la v2; la v1 non dovrebbe comparire in nessun bot che distribuisci nel 2026. Vediamo il percorso REST per lo snapshot, il canale WebSocket di update, i dettagli di parsing che mettono in difficoltà i nuovi builder e la logica di reconnect senza la quale un bot a lunga esecuzione finisce fuori sync nel giro di poche ore.
Questo è il capitolo 8 della nostra serie in 32 parti sulla costruzione di un Polymarket trading bot. Trattiamo l'argomento in profondità nelle sezioni qui sotto. I contenuti principali di ogni sezione vengono scritti e rilasciati capitolo per capitolo; le risposte FAQ e i riferimenti sono già completi e riflettono l'esperienza di produzione maturata gestendo il nostro trader.
- CLOB v1 vs v2 (usa v2)
- Snapshot REST del order book
- WebSocket subscriptions: canali market e user
- Parsing di bids/asks/depth
- Calcolo di mid-price e best-bid/ask
- Maker fees, taker fees, rebates
- Code: connect WS e process price-change events
- Reconnect e gap-handling
CLOB v1 vs v2 (usa v2)
Polymarket mantiene due generazioni di SDK. La v1 (@polymarket/clob-client su npm, py-clob-client <0.30) è deprecata e manca di diversi order types aggiunti nel 2024. La v2 (@polymarket/clob-client-v2 v1.0.2 in Node, py-clob-client 0.34.6+ in Python) è lo standard attuale.
Tre differenze concrete. La v2 supporta il flag negRisk per i mercati multi-outcome — richiesto da quando il NegRisk exchange è stato lanciato alla fine del 2024. La v2 include tipi TypeScript per le forme dei messaggi WebSocket; la v1 restituisce any. La v2 gestisce nativamente il flusso di firma Gnosis Safe di agosto 2025; la v1 richiede glue di signing personalizzato.
Il resto di questo capitolo è scritto assumendo sempre la v2. Se in un tutorial vecchio vedi codice v1, consideralo rotto finché non è dimostrato il contrario — in particolare, il placement degli ordini sui mercati NegRisk sotto v1 può instradare silenziosamente verso il contract di exchange sbagliato.
Snapshot REST del order book
L'endpoint REST per lo snapshot restituisce il book completo di un singolo token in un dato momento.
GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>
Forma della response:
{
"market": "0x...",
"asset_id": "5413...",
"timestamp": "1715600000000",
"hash": "0x...",
"bids": [{"price":"0.45","size":"120"}, {"price":"0.44","size":"380"}, ...],
"asks": [{"price":"0.47","size":"85"}, {"price":"0.48","size":"210"}, ...]
}
I prezzi sono stringhe con 2-3 decimali; le size sono stringhe che rappresentano il numero di share (non dollari). I bids sono ordinati dal più alto al più basso, gli asks dal più basso al più alto. hash è un marker di deduplica — poll ripetuti di un book invariato restituiscono lo stesso hash e il tuo bot può saltare il processing.
Lo snapshot REST è la scelta giusta per lookup one-off (controllo del prezzo in fase decisionale). Per il monitoraggio continuo, usa il canale WebSocket qui sotto.
WebSocket subscriptions: canali market e user
Due canali WebSocket contano davvero.
Market channel: wss://ws-subscriptions-clob.polymarket.com/ws/market. Iscriviti a uno o più token; ricevi gli aggiornamenti del order book in tempo reale.
{"type":"Market","markets":["0xCondId1","0xCondId2"]}
I messaggi arrivano a ogni cambio. I tipi includono book (snapshot completo), price_change (delta), tick_size_change (raro) e last_trade_price (ultimo fill).
User channel: wss://ws-subscriptions-clob.polymarket.com/ws/user. Autenticato; ricevi gli eventi dei tuoi ordini — fill, partial fill, cancellazioni.
{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}
Il canale user è il modo più pulito per rilevare un fill. Fare polling dell'endpoint REST degli ordini costa di più e può perdere cambi di stato tra un poll e l'altro; il WebSocket spinge l'evento nel momento in cui il matcher lo conferma.
Parsing di bids/asks/depth
Il order book è un elenco di livelli di prezzo con size aggregata. Ci sono due convenzioni di parsing da gestire correttamente.
Direzione dell'ordine: i bids sono ordini di acquisto (qualcuno vuole COMPRARE a questo prezzo). Quando il TUO bot vende, colpisce un bid. Quando il tuo bot compra, solleva un ask. La UI di Polymarket mostra la stessa direzione; alcuni altri exchange la invertono.
Sorting: i bids arrivano ordinati in modo decrescente (best bid per primo). Gli asks arrivano ordinati in modo crescente (best ask per primo). Il best bid è bids[0]; il best ask è asks[0]. Attenzione: il WebSocket pubblico a volte invia update parziali del book che non sono pre-ordinati — fai sempre un re-sort difensivo dopo ogni merge.
La depth a un livello è il valore transabile in dollari: price * size. La depth sui primi 5 livelli è una metrica di liquidità molto comune: sum(b.price * b.size for b in bids[:5]). Se la depth top-5 è sotto i $100, il book è illiquido e la maggior parte delle assunzioni di strategia si rompe.
Calcolo di mid-price e best-bid/ask
Tre punti di prezzo derivati che il tuo bot deve conoscere.
- Best bid / best ask:
bids[0].priceeasks[0].price. I prezzi a cui puoi effettivamente tradare, per una share. - Mid-price:
(best_bid + best_ask) / 2. Il centro matematico dello spread. Utile per la valutazione; non tradi mai al mid. - Prezzo VWAP per size N: scorri il book finché la size cumulata raggiunge N, poi restituisci il prezzo medio ponderato per size. Il costo reale per COMPRARE N share adesso, tenendo conto dello sweep nei livelli più profondi.
Edge case: un lato bid o ask vuoto (nessuno vende, o nessuno compra) significa che il book è one-sided. Nella market structure di Polymarket succede nei mercati risolti o quasi risolti, dove un lato è a 0.999 e nessuno offre liquidità dal lato perdente. Tratta best-bid = 0 o best-ask = 1 come segnali "do not trade".
Maker fees, taker fees, rebates
Polymarket usa un modello di fee maker-taker. Numeri a maggio 2026:
- Taker fee: 0 (zero) — gli ordini che sollevano liquidità già presente nel book non pagano fee. Nota che per le operazioni via proxy si applicano i costi di gas / network.
- Maker rebate: piccolo valore positivo, erogato in modo programmatico per ogni rested order riempito nei mercati idonei al programma reward. Non tutti i mercati hanno rewards.
- Mercati NegRisk: stessa struttura di fee ma su un contract di exchange separato; i rewards maturano separatamente.
La zero taker fee rende Polymarket molto diverso dai venue CFD tradizionali — la maggior parte del "costo" di trading è lo spread bid-ask stesso, non una fee esplicita. Per una strategia che attraversa lo spread a ogni trade, la spread tax è il vero costo; considera 1-3 centesimi round-trip sui book tipici, di più su quelli illiquidi.
I maker rebates valgono la pena solo quando i mercati idonei ai liquidity rewards si allineano con le idee di strategia. Il Capitolo 19 copre il liquidity-rewards farming come approccio dedicato.
Code: connect WS e process price-change events
Esempio Node minimale: connect, subscribe, logga ogni price-change event per un token.
import WebSocket from "ws";
const ws = new WebSocket("wss://ws-subscriptions-clob.polymarket.com/ws/market");
ws.on("open", () => {
ws.send(JSON.stringify({ type: "Market", markets: ["<CONDITION_ID>"] }));
});
ws.on("message", (data) => {
const msg = JSON.parse(data.toString());
if (msg.event_type === "price_change") {
console.log("price_change", msg.asset_id, msg.changes);
} else if (msg.event_type === "book") {
console.log("book snapshot", msg.bids?.[0], msg.asks?.[0]);
}
});
ws.on("close", () => console.log("closed"));
ws.on("error", (e) => console.error("err", e.message));
Iscriversi a circa 30 token per connessione WebSocket è gestibile senza problemi. Oltre quel limite, distribuisci su più connessioni — il server a volte scarta le subscription grandi senza segnalare errore, producendo letture del book stale in modo silenzioso.
Reconnect e gap-handling
Una connessione WebSocket a lunga durata può cadere. Cloudflare cicla le connessioni ogni poche ore; le reti hanno momenti di buio; Polymarket a volte fa deploy. Pianifica tutto questo.
Strategia di reconnect: su close o error, attendi min(2^attempt, 30) secondi con jitter, poi fai di nuovo subscribe. Resetta il contatore degli attempt al primo messaggio ricevuto con successo dopo il reconnect.
Il gap-handling conta più della velocità di reconnect. Mentre il WebSocket era disconnesso, il book si è mosso. A ogni reconnect, rifai il fetch dello snapshot REST di ogni token sottoscritto e riconcilia: qualsiasi posizione aperta il cui book si è mosso in modo significativo richiede un nuovo state check, gli exit potrebbero dover scattare, gli alert potrebbero essere stale. Il caso "ho perso 30 secondi di aggiornamenti del book" è il killer silenzioso dei bot a lunga esecuzione — continuano a girare su uno stato obsoleto e piazzano ordini a prezzi che non esistono più.
Pattern difensivo: snapshot di ogni book sottoscritto una volta al minuto indipendentemente dallo stato del WebSocket, e considera il WS come una fast-path optimization sopra il polling dello snapshot.











