Polymarket Bot Tutorial · Rozdział 7 z 32
Dogłębne omówienie Polymarket Gamma API: endpointy /events i /markets, paginacja, tag IDs (864 Tennis, 745 NBA itd.), filtrowanie po volume 24h, rate limits oraz przykłady kodu w Python i Node.
Co obejmuje ten rozdział
Gamma to katalogowe API Polymarket — listuje każde wydarzenie, każdy market, tag, obraz i rozstrzygnięty wynik, które wyświetla front-end. CLOB API służy do tradingu; Gamma opisuje to, czym można handlować. Większość błędów botów na warstwie discovery wynika z mylenia tych dwóch usług albo z pominięcia kontraktu paginacji. Ten rozdział jest praktycznym kompendium głównych endpointów Gamma wraz z dokładnym zachowaniem parametrów, na których polegają nasze produkcyjne fetchery.
To jest rozdział 7 z naszej 32-częściowej serii o budowie Polymarket trading bota. Temat omawiamy szczegółowo w sekcjach poniżej. Treść każdej sekcji jest pisana i publikowana rozdział po rozdziale; odpowiedzi FAQ i materiały referencyjne są już kompletne i odzwierciedlają produkcyjne doświadczenie z uruchamiania naszego własnego tradera.
- Gamma vs CLOB: kiedy używać którego
- Anatomia endpointu /events
- Anatomia endpointu /markets
- Tags i tag IDs (zweryfikowana lista)
- Filtrowanie: active, closed, sortowanie po volume24hr
- Paginacja i limity
- Rate limits i caching
- Kod: pobieranie marketów z najwyższym volume 24h
Gamma vs CLOB: kiedy używać którego
Dwie różne usługi do dwóch różnych zadań.
Gamma (gamma-api.polymarket.com): katalog. Listuje eventy, markets, tags, opisy, obrazy, rozstrzygnięte wyniki, volume 24h i total volume oraz daty zakończenia. Tylko odczyt HTTP. W przypadku większości odczytów nie wymaga uwierzytelniania. Aktualizuje się na bieżąco, ale w sposób eventual consistent — market, który właśnie się zamknął, może jeszcze przez kilka sekund pokazywać closed: false.
CLOB (clob.polymarket.com): trading + order book. Listuje aktualny best bid/ask, głębokość top-N booka oraz ostatnie transakcje. Wymaga uwierzytelnienia dla endpointów zapisu (składanie i anulowanie orderów). Dostępne są kanały WebSocket do aktualizacji booka w czasie rzeczywistym.
Zasada ogólna: używaj Gamma, aby znaleźć, czym handlować; używaj CLOB, aby handlować. Bot, który odczytuje ceny z Gamma, korzysta ze starych danych — pola cenowe Gamma aktualizują się rzadziej niż order book w CLOB. Bot, który pobiera metadane marketu z CLOB, wykonuje więcej requestów, niż to konieczne.
Anatomia endpointu /events
GET /events zwraca dane na poziomie eventu. „Event” to strona Polymarket; pojedynczy event może zawierać wiele marketów (np. event 2024 Presidential Election ma jeden market na każdego kandydata).
Najważniejsze pola:
slug: identyfikator bezpieczny dla URL, stabilny przez cały czas trwania eventu.title,description: do wyświetlania dla użytkownika.endDate(ISO 8601): kiedy event się zamyka.active,closed: booleans; połącz je w query z?active=true&closed=falsedla aktywnych eventów.volume,volume24hr: sumy w USD.tags: tablica obiektów tagów (patrz sekcja o tagach poniżej).markets: tablica podrzędnych obiektów marketów (patrz anatomia/markets).
Najczęstszy pattern discovery: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Zwraca 100 obecnie aktywnych eventów o najwyższym volume.
Anatomia endpointu /markets
GET /markets zwraca dane na poziomie marketu. Market to pojedynczy kontrakt Y/N albo wielowymiarowy; znajduje się wewnątrz eventu.
Najważniejsze pola:
slug: identyfikator bezpieczny dla URL.question: tytuł wyświetlany na stronie tradingowej (np. „Czy Trump będzie prezydentem 1 stycznia 2027?”).outcomes: JSON string z nazwami outcome, np.'["Yes","No"]'. Dla binary zawsze dwa elementy; więcej dla NegRisk.outcomePrices: JSON string z aktualnymi cenami jako decimal, np.'["0.62","0.38"]'. Obie strony sumują się do ~1.0 minus spread.clobTokenIds: JSON string z identyfikatorami tokenów ERC-1155 dopasowanymi do outcome. To właśnie te tokeny kupujesz/sprzedajesz.negRisk: boolean; true dla marketów wielowymiarowych, w których suma wynosi 1. Ma znaczenie przy składaniu orderów (rozdział 11).
Pola outcomes / outcomePrices / clobTokenIds są zwracane jako JSON strings, a nie sparsowane tablice — przed użyciem trzeba je zdekodować z JSON.
Tags i tag IDs (zweryfikowana lista)
Tags to etykiety kategorii (Sports, Crypto, Tennis, NBA itd.). Zweryfikowane produkcyjne tag IDs dla najczęściej używanych kategorii:
| 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 |
Filtruj po tagu za pomocą ?tag_id=745 dla konkretnego tagu albo ?tag_slug=nba, używając slug. Filtrowanie po slug jest czytelniejsze w kodzie, ale trochę wolniejsze; filtracja po ID to domyślny standard produkcyjny.
Filtrowanie: active, closed, sortowanie po volume24hr
Cztery wymiary filtrowania, których będziesz używać w 95% przypadków.
active=true|false:truewyklucza markets ukryte przez zespół Polymarket z UI.closed=true|false:falsewyklucza rozstrzygnięte markets. Połączenieactive=true&closed=falseto najczęstszy filtr dla live marketów.order=volume24hr,order=volume,order=endDate: klucz sortowania. Najbardziej użyteczne jestvolume24hrdo znajdowania obecnie aktywnych marketów.ascending=true|false: domyślnie true na większości endpointów; przy sortowaniu po volume prawie zawsze chceszfalse.
Uwaga: filtrowanie po tag_id w połączeniu z order=volume24hr i ascending=false czasem zwraca pustą stronę, gdy tag ma bardzo mało live marketów. Zawsze pobieraj nadmiarowo (requestuj więcej, niż wyświetlasz) i filtruj po stronie aplikacji, aby to obsłużyć.
Paginacja i limity
Parametr limit akceptuje 1-500 na jedno wywołanie. Jeśli nie zostanie podany, domyślna wartość to 100. Powyżej 500 serwer cicho nakłada limit — otrzymasz 500, ale odpowiedź nie zawiera żadnej informacji o dalszych wynikach.
Paginacja jest oparta na offset: ?limit=500&offset=500 dla drugiej strony. Nie ma paginacji opartej na cursorach, więc równoległe inserty mogą powodować przesuwanie się granic stron między wywołaniami. Dla większości potrzeb discovery bota jest to akceptowalne; przy skanowaniu archiwum sortuj po stabilnym polu (endDate lub createdAt) i wykrywaj nakładanie po slug.
Praktyczny pattern dla „wszystkich live marketów”: pobierz limit=500&order=volume24hr&ascending=false. To obejmuje top 500 według volume, czyli praktycznie każdy market z istotną aktywnością. Wchodzenie poza pierwszą stronę rzadko ma sens — markety w ogonie rozkładu volume z definicji nie są tam, gdzie dzieje się akcja.
Rate limits i caching
Gamma jest chroniona przez Cloudflare i ma miękkie rate limits per IP. Empiryczne progi zaobserwowane przy produkcyjnym obciążeniu:
- Do około 30 req/sec z jednego IP utrzymane stabilnie: bez problemu.
- Wybuchy 100+ req/sec: okazjonalnie 429, retry zwykle się udają.
- Około 500 req/sec utrzymane: strona rate-limit albo tymczasowy blok (10-60s).
Opublikowane nagłówki odpowiedzi zawierają wartości Cache-Control dla większości endpointów na 30-60 sekund. Przestrzegaj ich — ponowne pobieranie tego samego eventu 10 razy w ciągu minuty nie daje żadnej korzyści. Produkcyjny pattern cachowania: in-process LRU + TTL, kluczowany pełnym URL-em, TTL 30s. Oszczędza liczbę requestów i zmniejsza latencję.
W strategiach wysokiej częstotliwości zmirroruj dane Gamma do lokalnego store aktualizowanego przez jeden proces fetchera; niech wielu consumerów czyta z tego store. Jeden fetcher × wielu consumerów > wielu fetcherów × Gamma.
Kod: pobieranie marketów z najwyższym volume 24h
Referencyjny fetcher w trzech językach, zwracający top 50 live marketów według volume 24-godzinnego.
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'
Endpoint Polymarket Gamma /events NIE obsługuje parametru free-text search — dodanie ?q=foo albo ?search=foo cicho zwraca domyślne sortowanie. Zamiast tego filtruj po slug albo tagu.











