آموزش Polymarket Bot · فصل ۷ از ۳۲
بررسی عمیق Polymarket Gamma API: endpointهای /events و /markets، pagination، tag IDها (864 Tennis، 745 NBA، و غیره)، فیلتر بر اساس volume 24h، rate limitها، و نمونهکدهای Python و Node.
این فصل چه چیزهایی را پوشش میدهد
Gamma API کاتالوگ Polymarket است - هر event، هر market، tag، image، و resolved outcome را که front-end نمایش میدهد فهرست میکند. CLOB API برای trade است؛ Gamma مشخص میکند چه چیزی قابل معامله است. بیشتر bugهای bot در لایه discovery از قاطی کردن این دو با هم، یا از نادیده گرفتن قرارداد pagination میآیند. این فصل مرجع میدانی endpointهای اصلی Gamma است، با رفتار دقیق parameterها که fetcherهای production ما به آن وابستهاند.
این فصل ۷ از سری ۳۲ بخشی ما درباره ساختن Polymarket trading bot است. ما این موضوع را در بخشهای زیر بهصورت عمیق پوشش میدهیم. محتوای بدنه برای هر بخش در حال نوشته شدن و انتشار مرحلهبهمرحله است؛ پاسخهای FAQ و referenceها از قبل کامل هستند و تجربه production از اجرای trader خودمان را منعکس میکنند.
- Gamma در برابر CLOB: چه زمانی از کدام استفاده کنیم
- آشنایی با endpoint /events
- آشنایی با endpoint /markets
- Tags و tag IDها (فهرست تأییدشده)
- Filtering: active، closed، و مرتبسازی بر اساس volume24hr
- Pagination و limitها
- Rate limitها و caching
- Code: دریافت marketهای برتر بر اساس volume 24h
Gamma در برابر CLOB: چه زمانی از کدام استفاده کنیم
دو service متفاوت برای دو کار متفاوت.
Gamma (gamma-api.polymarket.com): catalog. eventها، marketها، tagها، descriptionها، imageها، resolved outcomeها، volume 24 ساعته، total volume، و end dateها را فهرست میکند. Read-only HTTP. برای بیشتر readها authentication لازم نیست. بهصورت پیوسته بهروزرسانی میشود اما eventually consistent است - یک market که تازه بسته شده ممکن است برای چند ثانیه هنوز closed: false نشان داده شود.
CLOB (clob.polymarket.com): trading + order book. best bid/ask فعلی، top-N depth دفتر سفارش، و recent tradeها را فهرست میکند. برای write endpointها (ثبت order، لغو) authenticated است. کانالهای WebSocket بلادرنگ برای بهروزرسانی book موجود است.
قاعده سرانگشتی: برای پیدا کردن چیزی که میخواهید معامله کنید از Gamma استفاده کنید؛ برای معامله کردن از CLOB استفاده کنید. botی که price را از Gamma میخواند از data قدیمی استفاده میکند - فیلدهای price در Gamma کمتر از order book در CLOB بهروزرسانی میشوند. botی که metadata بازار را از CLOB میخواند، درخواستهای بیشتری از حد لازم میفرستد.
آشنایی با endpoint /events
GET /events data در سطح event را برمیگرداند. یک "event" یک صفحه Polymarket است؛ یک event واحد میتواند چندین market داشته باشد (مثلاً event انتخابات ریاستجمهوری 2024 برای هر نامزد یک market دارد).
فیلدهای کلیدی:
slug: شناسه URL-safe، ثابت در طول عمر event.title،description: نمایش برای انسان.endDate(ISO 8601): زمان بسته شدن event.active،closed: boolean؛ برای eventهای زنده، در query با?active=true&closed=falseترکیب شوند.volume،volume24hr: مجموع USD.tags: آرایهای از objectهای tag (بخش tags را ببینید).markets: آرایهای از objectهای market فرزند (آشنایی با/marketsرا ببینید).
رایجترین الگوی discovery: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. این 100 event زنده با بالاترین volume را برمیگرداند.
آشنایی با endpoint /markets
GET /markets data در سطح market را برمیگرداند. یک market یک contract از نوع Y/N یا multi-outcome است؛ داخل یک event قرار دارد.
فیلدهای کلیدی:
slug: شناسه URL-safe.question: عنوانی که در صفحه trading نمایش داده میشود (مثلاً "Will Trump be president on January 1, 2027?").outcomes: رشته JSON از نام outcomeها، مثلاً'["Yes","No"]'. برای binary همیشه دو عنصر دارد؛ برای NegRisk بیشتر.outcomePrices: رشته JSON از priceهای فعلی بهصورت decimal، مثلاً'["0.62","0.38"]'. دو طرف تقریباً به 1.0 منهای spread جمع میشوند.clobTokenIds: رشته JSON از ERC-1155 token IDها که با outcomeها همراستا هستند. اینها tokenهایی هستند که واقعاً میخرید/میفروشید.negRisk: boolean؛ برای marketهای multi-outcome که جمعشان 1 میشود true است. برای order placement مهم است (فصل 11).
فیلدهای outcomes / outcomePrices / clobTokenIds بهصورت رشته JSON میآیند، نه آرایههای parse شده - قبل از استفاده JSON-decode کنید.
Tags و tag IDها (فهرست تأییدشده)
Tags برچسبهای دستهبندی هستند (Sports، Crypto، Tennis، NBA، و غیره). tag IDهای production تأییدشده برای رایجترین دستهها:
| 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 |
با ?tag_id=745 برای یک tag خاص فیلتر کنید، یا با استفاده از slug از ?tag_slug=nba استفاده کنید. فیلتر کردن بر اساس slug در code خواناتر است اما کمی کندتر است؛ ID-based در production پیشفرض است.
Filtering: active، closed، مرتبسازی بر اساس volume24hr
چهار بُعد filtering که 95٪ مواقع از آنها استفاده میکنید.
active=true|false: مقدارtruemarketهایی را که تیم Polymarket از UI مخفی کرده است حذف میکند.closed=true|false: مقدارfalsemarketهای resolved را حذف میکند. ترکیبactive=true&closed=falseرایجترین فیلتر برای live marketها است.order=volume24hr،order=volume،order=endDate: کلید مرتبسازی. مفیدترین گزینهvolume24hrبرای پیدا کردن marketهای فعال فعلی است.ascending=true|false: در بیشتر endpointها پیشفرض true است؛ برای مرتبسازی بر اساس volume تقریباً همیشهfalseرا میخواهید.
نکته: فیلتر کردن با tag_id همراه با order=volume24hr و ascending=false گاهی وقتی آن tag تعداد کمی live market دارد، یک صفحه خالی برمیگرداند. همیشه over-fetch کنید (بیشتر از چیزی که نمایش میدهید request بفرستید) و برای مدیریت این حالت، بعداً post-filter انجام دهید.
Pagination و limitها
پارامتر limit در هر call مقدار 1 تا 500 را میپذیرد. اگر مشخص نشود، مقدار پیشفرض 100 است. بالاتر از 500، server بیصدا cap میکند - شما 500 دریافت میکنید اما response هیچ نشانهای از بیشتر بودن ندارد.
Pagination بر پایه offset است: ?limit=500&offset=500 برای صفحه دوم. pagination بر پایه cursor وجود ندارد، بنابراین درج همزمان دادههای جدید میتواند باعث جابهجایی مرز صفحات بین callها شود. برای بیشتر اهداف discovery در bot این قابل قبول است؛ برای archive scrapeها، بر اساس یک فیلد پایدار (endDate یا createdAt) مرتب کنید و همپوشانی را با slug تشخیص دهید.
الگوی عملی برای "همه live marketها": limit=500&order=volume24hr&ascending=false را fetch کنید. این top 500 بر اساس volume را پوشش میدهد که عملاً هر market با فعالیت غیرtrivial را شامل میشود. رفتن فراتر از page 1 بهندرت مفید است - marketهای انتهای توزیع volume، بهتعریف، جایی نیستند که action در آن رخ میدهد.
Rate limitها و caching
Gamma پشت Cloudflare قرار دارد و soft rate limitهایی به ازای هر IP دارد. آستانههای تجربی مشاهدهشده در بار production:
- تا حدود 30 req/sec از یک IP بهصورت پایدار: مشکلی ندارد.
- burstهای 100+ req/sec: گاهی 429 میگیرند، retry موفق میشود.
- حدود 500 req/sec بهصورت پایدار: rate-limit page یا block موقت (10 تا 60 ثانیه).
response headerهای منتشرشده شامل مقادیر Cache-Control برابر 30 تا 60 ثانیه برای بیشتر endpointها هستند. به آنها احترام بگذارید - هیچ فایدهای ندارد که همان event را در یک دقیقه 10 بار دوباره fetch کنید. الگوی caching در production: LRU درونفرایندی + TTL با کلید full URL، و TTL برابر 30 ثانیه. این کار تعداد request را کم میکند و latency را کاهش میدهد.
برای استراتژیهای high-frequency، دادههای Gamma را به یک local store mirror کنید که توسط یک fetcher process بهروزرسانی میشود؛ چندین consumer از همان store بخوانند. یک fetcher × چندین consumer > چندین fetcher × Gamma.
Code: دریافت marketهای برتر بر اساس volume 24h
Reference fetcher در سه زبان، که top 50 live market را بر اساس volume 24 ساعته برمیگرداند.
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 /events در Polymarket gamma از free-text search parameter پشتیبانی نمیکند - اضافه کردن ?q=foo یا ?search=foo بیصدا ترتیب پیشفرض را برمیگرداند. بهجای آن بر اساس slug یا tag فیلتر کنید.












