Polymarket Bot Tutorial · Розділ 7 із 32

Поглиблений розбір Polymarket Gamma API: endpoints /events і /markets, pagination, tag IDs (864 Tennis, 745 NBA тощо), фільтрація за обсягом за 24 години, rate limits, а також Python і Node code samples.

Що охоплює цей розділ

Gamma - це catalog API Polymarket: вона перелічує кожен event, кожен market, tag, image і resolved outcome, які показує front-end. CLOB API торгує; Gamma описує, що доступне для торгівлі. Більшість bot bugs на рівні discovery виникають через плутанину між цими двома сервісами або через пропущений pagination contract. Цей розділ - польовий довідник по основних endpoints Gamma з точним параметричним поводженням, на яке спираються наші production fetchers.

  • Gamma vs CLOB: коли що використовувати
  • Анатомія endpoint /events
  • Анатомія endpoint /markets
  • Tags і tag IDs (verified list)
  • Фільтрація: active, closed, ordering за volume24hr
  • Pagination і limits
  • Rate limits і caching
  • Code: отримання top market'ів за 24h-volume

Gamma vs CLOB: коли що використовувати

Два різні сервіси для двох різних задач.

Gamma (gamma-api.polymarket.com): catalog. Перелічує events, markets, tags, descriptions, images, resolved outcomes, 24-hour volume, total volume, end dates. Read-only HTTP. Для більшості reads не потрібна authentication. Оновлюється безперервно, але eventually consistent - market, який щойно закрився, ще кілька секунд може показувати closed: false.

CLOB (clob.polymarket.com): trading + order book. Показує поточні best bid/ask, top-N book depth, recent trades. Для write endpoints потрібна authentication (розміщення ордерів, скасування). Доступні real-time WebSocket channels для оновлень book.

Практичне правило: використовуйте Gamma, щоб знайти, що торгувати; використовуйте CLOB, щоб торгувати цим. Bot, який читає ціни з Gamma, працює зі stale data - fields ціни в Gamma оновлюються рідше, ніж order book у CLOB. Bot, який читає market metadata з CLOB, робить більше requests, ніж потрібно.

Анатомія endpoint /events

GET /events повертає дані на рівні event. "Event" - це сторінка Polymarket; один event може містити кілька markets (наприклад, event 2024 Presidential Election має один market на кожного кандидата).

Ключові fields:

  • slug: URL-safe ідентифікатор, стабільний протягом життя event.
  • title, description: відображення для людей.
  • endDate (ISO 8601): коли event закривається.
  • active, closed: boolean; поєднуйте їх у query з ?active=true&closed=false для live events.
  • volume, volume24hr: загальні суми в USD.
  • tags: масив об'єктів tag (див. розділ про tags нижче).
  • markets: масив дочірніх market objects (див. анатомію /markets).

Найпоширеніший шаблон discovery: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Повертає 100 live events з найвищим обсягом.

Анатомія endpoint /markets

GET /markets повертає дані на рівні market. Market - це один контракт Y/N або багатовихідний контракт; він знаходиться всередині event.

Ключові fields:

  • slug: URL-safe ідентифікатор.
  • question: заголовок, що відображається на торговій сторінці (наприклад, "Will Trump be president on January 1, 2027?").
  • outcomes: JSON string із назвами outcome, наприклад '["Yes","No"]'. Для binary завжди два елементи; для NegRisk - більше.
  • outcomePrices: JSON string поточних цін як decimals, наприклад '["0.62","0.38"]'. Обидві сторони сумарно дають ~1.0 мінус spread.
  • clobTokenIds: JSON string ERC-1155 token ID, вирівняних за outcomes. Це токени, які ви фактично купуєте/продаєте.
  • negRisk: boolean; true для багатовихідних markets із сумою до 1. Важливо для розміщення ордерів (розділ 11).

Fields outcomes / outcomePrices / clobTokenIds надходять як JSON strings, а не як розпарсені масиви - зробіть JSON-decode перед використанням.

Tags і tag IDs (verified list)

Tags - це категоріальні labels (Sports, Crypto, Tennis, NBA тощо). Перевірені production tag IDs для найуживаніших категорій:

TagIDTagID
Sports1NBA745
Crypto21NFL450
Politics2Tennis864
Bitcoin100196Esports702
Ethereum100383Soccer1059
Election3EPL739
Middle East1432UCL2186

Фільтруйте за tag за допомогою ?tag_id=745 для конкретного tag або ?tag_slug=nba, використовуючи slug. Фільтрація за slug більш читабельна в code, але трохи повільніша; фільтрація за ID - production default.

Фільтрація: active, closed, ordering за volume24hr

Чотири параметри фільтрації, які ви будете використовувати у 95% випадків.

  • active=true|false: true виключає markets, які команда Polymarket приховала з UI.
  • closed=true|false: false виключає resolved markets. Комбінація active=true&closed=false - найпоширеніший live filter.
  • order=volume24hr, order=volume, order=endDate: ключ сортування. Найкорисніший - volume24hr для пошуку поточних active markets.
  • ascending=true|false: за замовчуванням true на більшості endpoints; для volume ordering майже завжди потрібне false.

Застереження: фільтрація за tag_id у поєднанні з order=volume24hr і ascending=false іноді повертає порожню сторінку, коли у tag дуже мало live markets. Завжди over-fetch (запитуйте більше, ніж показуєте) і post-filter, щоб це обробити.

Pagination і limits

Параметр limit приймає від 1 до 500 на один виклик. Якщо не вказати, значення за замовчуванням - 100. Понад 500 сервер тихо обмежує запит - ви отримаєте 500, але response не міститиме ознак більшого обсягу.

Pagination базується на offset: ?limit=500&offset=500 для другої сторінки. Cursor-based pagination немає, тому паралельні вставки можуть зсувати межі сторінок між викликами. Для більшості задач bot discovery це прийнятно; для archive scrapes сортуйте за стабільним field (endDate або createdAt) і виявляйте overlap за slug.

Практичний шаблон для "усіх live markets": запитуйте limit=500&order=volume24hr&ascending=false. Це покриває топ-500 за volume, тобто практично всі markets із помітною активністю. Переходити далі першої сторінки рідко має сенс - markets у хвості розподілу volume за визначенням не там, де відбувається основна дія.

Rate limits і caching

Gamma стоїть за Cloudflare і має soft rate limits на IP. Емпіричні пороги, які спостерігалися під production load:

  • До ~30 req/sec з однієї IP стабільно: нормально.
  • Сплески 100+ req/sec: іноді 429, повторні спроби успішні.
  • ~500 req/sec стабільно: rate-limit page або тимчасовий block (10-60 с).

Публічні response headers містять значення Cache-Control 30-60 секунд для більшості endpoints. Дотримуйтеся їх - немає користі перезапитувати той самий event 10 разів за хвилину. Production-патерн caching: in-process LRU + TTL, ключований на повний URL, TTL 30 с. Це економить кількість requests і зменшує latency.

Для high-frequency стратегій віддзеркалюйте дані Gamma в local store, який оновлює один fetcher process; кілька consumers читають із цього store. Один fetcher × багато consumers > багато fetchers × Gamma.

Code: отримання top market'ів за 24h-volume

Reference fetcher трьома мовами, який повертає top 50 live markets за 24-hour volume.

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 НЕ підтримує free-text search parameter - додавання ?q=foo або ?search=foo тихо повертає default ordering. Замість цього фільтруйте за slug або tag.

Часті запитання

Що таке Polymarket Gamma API?
Gamma - це metadata та discovery API Polymarket. Вона віддає списки event/market, titles, descriptions, end dates, tags і aggregate volume. Вона НЕ віддає real-time order book data - це знаходиться в CLOB API. Для більшості use cases з discovery та analytics ви починаєте з Gamma.
У чому різниця між event і market на Polymarket?
Event об'єднує один або кілька markets, які мають спільну тему питання. Market - це конкретний Yes/No outcome з власним order book і token IDs. Event "2026 NBA Champion" містить 30 markets (по одному на кожну команду). Для binary Yes/No events event має 1 underlying market.
Як знайти Polymarket tag IDs?
Tags доступні через gamma endpoint /tags. Перевірені IDs, які ми використовуємо в production: 864 Tennis, 745 NBA. Tag slugs в URL (?tag_slug=tennis) і free-text query (?q=tennis) ненадійні - використовуйте лише числовий tag_id. Перевіряйте /tags, перш ніж покладатися на slug.
Як відсортувати Polymarket events за 24h volume?
/events?order=volume24hr&ascending=false - саме це лежить в основі більшості віджетів "trending markets". Поєднуйте з active=true&closed=false, щоб відфільтрувати expired або paused markets. Limit за замовчуванням - 25; максимум - 500 на виклик.
Чи є на Gamma обмеження pagination?
Так. Endpoints /events і /markets приймають limit (максимум 500 на виклик) і offset для pagination. Більшість libraries не виконують pagination автоматично - якщо вам потрібен увесь набір, циклічно збільшуйте offset, доки не отримаєте сторінку з менш ніж `limit` результатами.
Чи підтримує Gamma WebSocket?
Ні. Gamma працює лише через REST. Для real-time оновлень (зміни цін, нові markets, order book) використовуйте CLOB WebSocket - це буде розглянуто в розділі 8 цієї серії.