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=false per 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:

TagIDTagID
Sports1NBA745
Crypto21NFL450
Politics2Tennis864
Bitcoin100196Esports702
Ethereum100383Soccer1059
Election3EPL739
Middle East1432UCL2186

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: true esclude i mercati che il team di Polymarket ha nascosto dalla UI.
  • closed=true|false: false esclude i mercati risolti. La combinazione active=true&closed=false è il filtro live più comune.
  • order=volume24hr, order=volume, order=endDate: chiave di ordinamento. Il più utile è volume24hr per trovare i mercati attualmente attivi.
  • ascending=true|false: per la maggior parte degli endpoint il valore predefinito è true; quasi sempre vuoi false per 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.

Domande frequenti

Cos’è la Polymarket Gamma API?
Gamma è l’API di metadata e discovery di Polymarket. Fornisce liste di eventi/mercati, titoli, descrizioni, date di fine, tag e volume aggregato. NON fornisce dati in tempo reale dell’order book: quelli si trovano nella CLOB API. Per la maggior parte dei casi d’uso di discovery e analytics, si parte da Gamma.
Qual è la differenza tra un evento e un mercato su Polymarket?
Un evento raggruppa uno o più mercati che condividono un tema di domanda. Un mercato è uno specifico esito Sì/No con il proprio order book e i propri token ID. Un evento "2026 NBA Champion" contiene 30 mercati (uno per squadra). Per gli eventi binari Sì/No, l’evento ha 1 mercato sottostante.
Come trovo gli ID dei tag di Polymarket?
I tag sono esposti tramite l’endpoint gamma /tags. Gli ID verificati che usiamo in produzione: 864 Tennis, 745 NBA. I tag slug nelle URL (?tag_slug=tennis) e le query a testo libero (?q=tennis) non sono affidabili: usa solo il tag_id numerico. Controlla /tags prima di affidarti a uno slug.
Come ordino gli eventi Polymarket per volume 24h?
/events?order=volume24hr&ascending=false - è ciò che alimenta la maggior parte dei widget "trending markets". Combinalo con active=true&closed=false per filtrare i mercati scaduti o in pausa. Il limit predefinito è 25; il massimo è 500 per chiamata.
Ci sono limiti di paginazione su Gamma?
Sì. Gli endpoint /events e /markets accettano limit (massimo 500 per chiamata) e offset per la paginazione. La maggior parte delle librerie non gestisce la paginazione automaticamente: se ti serve l’universo completo, fai un ciclo con offset finché non ottieni una pagina con meno risultati di `limit`.
Gamma supporta WebSocket?
No. Gamma è solo REST. Per aggiornamenti in tempo reale (variazioni di prezzo, nuovi mercati, order book) usa il WebSocket di CLOB, trattato nel capitolo 8 di questa serie.