Polymarket Bot Tutorial · 第32章中7章目
Polymarket Gamma APIの徹底解説:/events と /markets エンドポイント、ページネーション、タグID(864 Tennis、745 NBA など)、24h volumeによるフィルタリング、rate limits、そしてPythonとNodeのコードサンプル。
この章で扱う内容
GammaはPolymarketのカタログAPIです。あらゆるイベント、あらゆるマーケット、タグ、画像、そしてフロントエンドに表示される確定済み結果を一覧できます。CLOB APIは取引を担い、Gammaは「何が取引可能か」を示します。ボットの検出レイヤーで起きるバグの多くは、この2つを混同するか、ページネーションの契約を見落とすことが原因です。この章は、本番のフェッチ処理が依存している正確なパラメータ挙動を含め、Gammaの主要エンドポイントの実践的なリファレンスです。
- Gamma vs CLOB: どちらをいつ使うか
- /events エンドポイントの構成
- /markets エンドポイントの構成
- タグとtag ID(検証済みリスト)
- フィルタリング:active、closed、volume24hr順
- ページネーションと制限
- rate limitsとキャッシュ
- コード:24h volume上位のマーケットを取得
Gamma vs CLOB: どちらをいつ使うか
2つの異なるサービスは、2つの異なる役割のためにあります。
Gamma(gamma-api.polymarket.com):カタログ。イベント、マーケット、タグ、説明、画像、確定済み結果、24時間出来高、総出来高、終了日時を一覧します。読み取り専用のHTTPです。多くの読み取りでは認証不要です。継続的に更新されますが、最終的整合性です。たとえば、ちょうどクローズしたマーケットが数秒間はclosed: falseのまま表示されることがあります。
CLOB(clob.polymarket.com):取引 + order book。現在の最良bid/ask、top-Nの板厚、直近の約定を一覧します。書き込み系エンドポイント(注文発行、キャンセル)では認証が必要です。板更新用のリアルタイムWebSocketチャンネルも利用できます。
目安としては、Gammaで何を取引するかを探し、CLOBで実際に取引します。Gammaから価格を読んでいるボットは古いデータを使っています。Gammaの価格フィールドは、CLOBのorder bookほど頻繁には更新されません。CLOBからマーケットメタデータを読むボットは、不要なリクエストを増やしています。
/events エンドポイントの構成
GET /events はイベント単位のデータを返します。イベントとはPolymarketのページ1つで、1つのイベントに複数のマーケットが含まれることがあります(たとえば、2024年米大統領選挙イベントには候補者ごとに1マーケットずつあります)。
主なフィールド:
slug: URL安全な識別子。イベントの存続期間中は安定しています。title,description: 人間向けの表示。endDate(ISO 8601): イベントが終了する時刻。active,closed: 真偽値。ライブイベントには?active=true&closed=falseでクエリに組み合わせます。volume,volume24hr: USD建ての合計値。tags: タグオブジェクトの配列(下のタグセクション参照)。markets: 子マーケットオブジェクトの配列(/marketsの構成参照)。
最もよく使う発見パターンは、GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100 です。これは、現在ライブのイベントのうち、出来高上位100件を返します。
/markets エンドポイントの構成
GET /markets はマーケット単位のデータを返します。マーケットとは、Yes/Noまたは複数結果の契約1つで、イベントの中に存在します。
主なフィールド:
slug: URL安全な識別子。question: 取引ページに表示されるタイトル(例:"Will Trump be president on January 1, 2027?")。outcomes: 結果名のJSON文字列。例:'["Yes","No"]'。binaryでは常に2要素、NegRiskではそれ以上になります。outcomePrices: 現在価格の小数表現を含むJSON文字列。例:'["0.62","0.38"]'。両側の合計はスプレッドを除いておよそ1.0になります。clobTokenIds: 結果に対応したERC-1155トークンIDのJSON文字列。実際に売買するのはこれらのトークンです。negRisk: 真偽値。結果の合計が1になる複数結果マーケットではtrue。注文発行(第11章)に関係します。
outcomes / outcomePrices / clobTokenIds の各フィールドは、パース済み配列ではなくJSON文字列として返されます。使う前にJSONデコードしてください。
タグとtag ID(検証済みリスト)
タグはカテゴリラベルです(Sports、Crypto、Tennis、NBA など)。最もよく使われるカテゴリについて、本番環境で検証済みのtag IDは以下のとおりです。
| 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を使うか、slugを使って?tag_slug=nbaで指定します。slugベースのフィルタリングはコード上では読みやすいものの、少し遅くなります。IDベースが本番のデフォルトです。
フィルタリング:active、closed、volume24hr順
95%の場面で使う4つのフィルタ軸です。
active=true|false:trueにすると、PolymarketチームがUIから非表示にしたマーケットを除外します。closed=true|false:falseにすると、確定済みマーケットを除外します。active=true&closed=falseの組み合わせが、最も一般的なライブフィルタです。order=volume24hr,order=volume,order=endDate: ソートキーです。現在アクティブなマーケットを探すなら、最も有用なのはvolume24hrです。ascending=true|false: 多くのエンドポイントでデフォルトはtrueです。出来高順ではほぼ常にfalseを使います。
注意点として、tag_idでのフィルタリングにorder=volume24hrとascending=falseを組み合わせると、そのタグにライブマーケットが極端に少ない場合、空のページが返ることがあります。常に多めに取得し(表示数より多くリクエストし)、後段で再フィルタしてください。
ページネーションと制限
limit パラメータは1回あたり1〜500を受け付けます。未指定時のデフォルトは100です。500を超えるとサーバー側で静かに上限がかかり、500件だけ返りますが、それ以上あることを示す表示はありません。
ページネーションはoffsetベースです。2ページ目は?limit=500&offset=500です。cursorベースのページネーションはないため、並行してデータが追加されると、呼び出し間でページ境界がずれることがあります。多くのボットの探索用途では問題ありません。アーカイブのスクレイプでは、安定したフィールド(endDate または createdAt)でソートし、slugで重複を検出してください。
「ライブマーケットをすべて取る」実用パターンは、limit=500&order=volume24hr&ascending=false で取得することです。これで、出来高上位500件、つまり実質的に大きな動きがあるマーケットはほぼ網羅できます。2ページ目以降に進むのは、ほとんどの場合あまり意味がありません。出来高分布の末端にあるマーケットは、定義上、動きの中心ではないからです。
rate limitsとキャッシュ
GammaはCloudflareの背後にあり、IPごとにソフトなrate limitsがあります。本番負荷で観測された経験則のしきい値は以下のとおりです。
- 1つのIPから継続的に秒間約30リクエストまで:問題なし。
- 秒間100リクエスト超のバースト:ときどき429が出るが、リトライは成功する。
- 継続的に秒間約500リクエスト:rate limitページまたは一時ブロック(10〜60秒)。
公開されるレスポンスヘッダーには、多くのエンドポイントでCache-Controlの値として30〜60秒が含まれます。これに従ってください。1分の間に同じイベントを10回再取得しても、メリットはありません。本番でのキャッシュパターンは、完全なURLをキーにしたプロセス内LRU + TTLで、TTLは30秒です。リクエスト数を節約し、レイテンシを下げられます。
高頻度戦略では、単一のフェッチャープロセスで更新するローカルストアにGammaデータをミラーリングし、複数のコンシューマーはそのストアを読みます。1つのフェッチャー × 多数のコンシューマー は、多数のフェッチャー × Gamma より優れています。
コード:24h volume上位のマーケットを取得
3つの言語での参照用フェッチャーです。24時間出来高上位50件のライブマーケットを返します。
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'
Polymarket gammaの/eventsエンドポイントは、自由記述の検索パラメータをサポートしていません。?q=foo や ?search=foo を追加しても、黙ってデフォルト順のまま返ります。代わりに、slugまたはtagで絞り込んでください。












