Tutorial sui bot di Polymarket · Capitolo 7 di 32
Approfondimento della Polymarket Gamma API: endpoint /events e /markets, paginazione, ID dei tag (864 Tennis, 745 NBA, ecc.), filtraggio per volume 24h, limiti di frequenza ed esempi di codice Python e Node.
Cosa copre questo capitolo
Gamma è l’API di catalogo di Polymarket: elenca ogni evento, ogni mercato, tag, immagine ed esito risolto mostrato dal front-end. La CLOB API gestisce i trade; Gamma descrive ciò che è negoziabile. La maggior parte dei bug dei bot nel livello di discovery nasce dal confondere le due cose, oppure dal perdere il contratto di paginazione. Questo capitolo è il riferimento pratico per i principali endpoint di Gamma, con il comportamento esatto dei parametri su cui fanno affidamento i nostri fetcher in produzione.
Questo è il capitolo 7 della nostra serie in 32 parti su come costruire un Polymarket trading bot. Trattiamo l’argomento in profondità nelle sezioni qui sotto. Il contenuto del corpo di ogni sezione viene scritto e pubblicato capitolo per capitolo; le risposte FAQ e i riferimenti sono già completi e riflettono l’esperienza in produzione derivata dall’esecuzione del nostro trader.
- Gamma vs CLOB: quando usare l’uno o l’altro
- Anatomia dell’endpoint /events
- Anatomia dell’endpoint /markets
- Tag e ID dei tag (lista verificata)
- Filtraggio: active, closed, ordinamento per volume24hr
- Paginazione e limiti
- Limiti di frequenza e caching
- Codice: fetch dei mercati con volume 24h più alto
Gamma vs CLOB: quando usare l’uno o l’altro
Due servizi diversi per due lavori diversi.
Gamma (gamma-api.polymarket.com): catalogo. Elenca eventi, mercati, tag, descrizioni, immagini, esiti risolti, volume a 24 ore, volume totale, date di fine. HTTP di sola lettura. Per la maggior parte delle letture non richiede autenticazione. Viene aggiornata continuamente ma è a consistenza eventuale: un mercato appena chiuso può ancora mostrare closed: false per alcuni secondi.
CLOB (clob.polymarket.com): trading + order book. Elenca i migliori bid/ask, la profondità del book top-N, i trade recenti. Autenticato per gli endpoint di scrittura (inserimento ordini, cancellazione). Sono disponibili canali WebSocket in tempo reale per gli aggiornamenti del book.
Regola pratica: usa Gamma per trovare cosa negoziare; usa CLOB per negoziarlo. Un bot che legge i prezzi da Gamma sta usando dati obsoleti - i campi prezzo di Gamma si aggiornano meno frequentemente dell’order book di CLOB. Un bot che legge i metadati del mercato da CLOB sta facendo più richieste del necessario.
Anatomia dell’endpoint /events
GET /events restituisce dati a livello di evento. Un "evento" è una pagina di Polymarket; un singolo evento può contenere più mercati (ad esempio, l’evento 2024 Presidential Election ha un mercato per ciascun candidato).
Campi chiave:
slug: identificatore URL-safe, stabile per tutta la durata dell’evento.title,description: visualizzazione umana.endDate(ISO 8601): quando l’evento si chiude.active,closed: booleani; combinarli in una query con?active=true&closed=falseper gli eventi live.volume,volume24hr: totali in USD.tags: array di oggetti tag (vedi la sezione tag sotto).markets: array di oggetti mercato figli (vedi anatomia di/markets).
Il pattern di discovery più comune in assoluto: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Restituisce i 100 eventi attualmente live con il volume più alto.
Anatomia dell’endpoint /markets
GET /markets restituisce dati a livello di mercato. Un mercato è un contratto Y/N o multi-esito; vive all’interno di un evento.
Campi chiave:
slug: identificatore URL-safe.question: il titolo mostrato nella pagina di trading (ad esempio "Will Trump be president on January 1, 2027?").outcomes: JSON string dei nomi degli esiti, ad esempio'["Yes","No"]'. Sempre due elementi per i binari; di più per i NegRisk.outcomePrices: JSON string dei prezzi correnti come decimali, ad esempio'["0.62","0.38"]'. Entrambi i lati sommano a circa 1,0 meno lo spread.clobTokenIds: JSON string degli ERC-1155 token IDs allineati con gli esiti. Sono i token che compri/vendi davvero.negRisk: booleano; true per i mercati multi-esito che sommano a 1. Importante per il piazzamento dell’ordine (capitolo 11).
I campi outcomes / outcomePrices / clobTokenIds arrivano come JSON string, non come array già parsati: fai il JSON-decode prima di usarli.
Tag e ID dei tag (lista verificata)
I tag sono etichette categoriali (Sports, Crypto, Tennis, NBA, ecc.). Gli ID dei tag verificati in produzione per le categorie più usate:
| Tag | ID | Tag | ID |
|---|---|---|---|
| Sports | 1 | NBA | 745 |
| Crypto | 21 | NFL | 450 |
| Politics | 2 | Tennis | 864 |
| Bitcoin | 100196 | Esports | 702 |
| Ethereum | 100383 | Soccer | 1059 |
| Election | 3 | EPL | 739 |
| Middle East | 1432 | UCL | 2186 |
Filtra per tag con ?tag_id=745 per un tag specifico, oppure con ?tag_slug=nba usando lo slug. Il filtraggio basato sullo slug è più leggibile nel codice ma leggermente più lento; quello basato sull’ID è quello predefinito in produzione.
Filtraggio: active, closed, ordinamento per volume24hr
Le quattro dimensioni di filtraggio che userai nel 95% dei casi.
active=true|false:trueesclude i mercati che il team di Polymarket ha nascosto dalla UI.closed=true|false:falseesclude i mercati risolti. La combinazioneactive=true&closed=falseè il filtro live più comune.order=volume24hr,order=volume,order=endDate: chiave di ordinamento. Il più utile èvolume24hrper trovare i mercati attualmente attivi.ascending=true|false: per la maggior parte degli endpoint il valore predefinito è true; quasi sempre vuoifalseper gli ordinamenti per volume.
Attenzione: il filtraggio per tag_id combinato con order=volume24hr e ascending=false a volte restituisce una pagina vuota quando il tag ha pochissimi mercati live. Recupera sempre in eccesso (richiedi più di quanto mostri) e applica un filtraggio a valle per gestire questo caso.
Paginazione e limiti
Il parametro limit accetta da 1 a 500 per chiamata. Il valore predefinito è 100 se non specificato. Sopra 500 il server applica un limite in modo silenzioso: ricevi 500 ma la risposta non indica che ce ne siano altri.
La paginazione è basata su offset: ?limit=500&offset=500 per la seconda pagina. Non esiste paginazione basata su cursore, quindi gli inserimenti concorrenti possono spostare i confini tra le pagine da una chiamata all’altra. Per la maggior parte delle esigenze di discovery di un bot questo è accettabile; per lo scraping d’archivio, ordina per un campo stabile (endDate o createdAt) e rileva le sovrapposizioni tramite slug.
Pattern pratico per "tutti i mercati live": fetch con limit=500&order=volume24hr&ascending=false. Copre i primi 500 per volume, che sono sostanzialmente tutti i mercati con attività non banale. Andare oltre la pagina 1 è raramente utile: i mercati nella coda della distribuzione del volume, per definizione, non sono dove c’è l’azione.
Limiti di frequenza e caching
Gamma è dietro Cloudflare e ha limiti di frequenza flessibili per IP. Soglie empiriche osservate sotto carico di produzione:
- Fino a circa 30 req/sec da un singolo IP in modo sostenuto: nessun problema.
- Raffiche di 100+ req/sec: 429 occasionali, i retry vanno a buon fine.
- Circa 500 req/sec sostenuti: pagina di limitazione della frequenza o blocco temporaneo (10-60s).
Gli header di risposta pubblicati includono valori Cache-Control di 30-60 secondi per la maggior parte degli endpoint. Rispettali: non c’è alcun vantaggio nel richiedere di nuovo lo stesso evento 10 volte in un minuto. Pattern di caching in produzione: LRU + TTL in-process, indicizzato sulla URL completa, TTL di 30s. Riduce il numero di richieste e la latenza.
Per strategie ad alta frequenza, replica i dati di Gamma in un archivio locale aggiornato da un singolo processo fetcher; fai leggere più consumer da quell’archivio. Un fetcher × molti consumer > molti fetcher × Gamma.
Codice: fetch dei mercati con volume 24h più alto
Fetcher di riferimento in tre linguaggi, che restituisce i primi 50 mercati live per volume nelle ultime 24 ore.
Python:
import requests
r = requests.get("https://gamma-api.polymarket.com/events",
params={"active":"true","closed":"false",
"order":"volume24hr","ascending":"false","limit":50},
timeout=10)
for ev in r.json()[:50]:
print(ev["slug"], ev.get("volume24hr"))
Node:
const url = "https://gamma-api.polymarket.com/events?active=true&closed=false" +
"&order=volume24hr&ascending=false&limit=50";
const events = await fetch(url).then(r => r.json());
for (const ev of events) console.log(ev.slug, ev.volume24hr);
Curl:
curl -s "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=50" \
| jq '.[].slug'
L’endpoint /events di Polymarket gamma NON supporta un parametro di ricerca a testo libero: aggiungere ?q=foo o ?search=foo restituisce in modo silenzioso l’ordinamento predefinito. Filtra invece per slug o tag.


