第27章 / 33

短縮版

ポリマーケット は 3つの公開API を提供しています: CLOB (取引), Gamma (市場の発見), Data (分析) です。公式の Python SDK は py-clob-client 0.34.6 です。認証は APIキー + ECDSA署名 を使用し、注文は Polygon のプロキシウォレットを通じて EIP-712 で署名されます。レート制限は1キーあたりおおむね 60注文/分 です。新しい開発者にとって最大の落とし穴は、Gamma と CLOB の間にある condition_id → token_id の対応付けです - まずそこを解決すれば、他はすべてうまく進みます。ポリマーケット では、月あたりおよそ $40M の流動性報酬とボットが獲得したスプレッドが発生しており、そのほぼすべてが API ユーザーによって得られています。

学べること: 3つのAPIがどのように連携するか、py-clob-client のインストールと設定方法、プロキシウォレットでの認証方法、市場とオーダーブックの取得方法、注文の発注とキャンセル方法、WebSocket でリアルタイム価格更新をストリーミングする方法、正確なレート制限と適切なバックオフ方法、そして拡張可能な本番対応ボットのアーキテクチャです。
前提条件: 入金済みの ポリマーケット アカウントで、少なくとも1回は手動取引を完了していること、Python 3.8+ (または Node.js)、および HTTP、JSON、async コードの基本的な理解が必要です。まだ手動で取引したことがない場合は、ボットを組み込む前に 最初の取引 から始めてください。
01
第1章

パート1: 3つのAPI

ポリマーケットは、3つの異なるサービスにまたがって役割を明確に分離しています。各作業に適切なAPIを使うことで、ボットは高速でシンプルになり、レート制限の範囲内に収まります。

APIベースURL用途認証が必要
CLOB APIclob.polymarket.com注文の発注、キャンセル、追跡。オーダーブックの読み取り。ポジションの照会。はい(取引時)
Gamma APIgamma-api.polymarket.com市場の閲覧、メタデータ、画像、結果価格、出来高、満期、タグの取得。いいえ(公開)
Data APIdata-api.polymarket.com過去の取引、ポジションのスナップショット、ユーザー分析、リーダーボードデータ。いいえ(公開)

典型的なボットのループでは、Gammaで市場を見つけ、CLOBでオーダーブックを取得して取引を行い、Dataで戦略のパフォーマンスをオフラインでバックテストします。Gammaは「カタログ」、CLOBは「取引所」、Dataは「倉庫」と考えるとよいでしょう。

プロのヒント: GammaとDataには認証が不要です。今すぐcurlやブラウザで確認できます - アカウントは不要です。これは、APIキーを生成する前のプロトタイピングに最適な方法です。
02
第2章

第2部: 認証とプロキシウォレットモデル

ポリマーケットは、あなたのメインウォレットの秘密鍵で取引に署名しません。代わりに、Gnosis Safe風のプロキシウォレットを使用します。あなたのメインウォレットがプロキシを承認し、そのプロキシがPolygon上で全ての取引を実行します。あなたのAPIボットはそのプロキシと通信します。

必要なもの

  • API key - ポリマーケット Settings → Developerで生成
  • Private key - あなたの取引用ウォレットの鍵です(メインのMetaMaskシードフレーズではありません)
  • Funder address - あなたのプロキシウォレットアドレス(Settings → Walletに表示)
  • Chain ID - 137(Polygonメインネット)
  • Signature type - 1(POLY_PROXY、個人ユーザー向けの標準)
セキュリティ上の絶対条件: 秘密鍵をgitにコミットしないでください。環境変数(.env)またはシークレットマネージャーを使用してください。Discord、GitHubのissue、ChatGPTに鍵を貼り付けないでください。クリップボードに触れた鍵はすでに漏洩していると考えてください。少しでも疑わしい場合は鍵をローテーションしてください。
03
第3章

Part 3: py-clob-client のインストール

公式の Python SDK は、ゼロから最初の注文まで最速で進める方法です。ここでは、2026年4月時点で最新の 0.34.6 を使います。

# まず仮想環境を作成します
python3 -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows

# SDK をインストールします
pip install py-clob-client==0.34.6 requests websocket-client python-dotenv

基本的なクライアント設定

import os
from dotenv import load_dotenv
from py_clob_client.client import ClobClient
from py_clob_client.constants import POLYGON

load_dotenv()

client = ClobClient(
 host="https://clob.polymarket.com",
 key=os.environ["POLY_PRIVATE_KEY"],
 chain_id=POLYGON, # 137
 signature_type=1, # POLY_PROXY
 funder=os.environ["POLY_FUNDER"],
)

# 一度だけ: API認証情報を導出してキャッシュする
client.set_api_creds(client.create_or_derive_api_creds())

create_or_derive_api_creds() の呼び出しは、秘密鍵でメッセージに署名し、それを APIキー、シークレット、パスフレーズと交換します。起動のたびに導出エンドポイントへアクセスしないよう、最初の実行後にこれらを .env にキャッシュしてください。

実例 - 最小限の .env:
POLY_PRIVATE_KEY=0xabc...
POLY_FUNDER=0xdef...
POLY_API_KEY=...
POLY_SECRET=...
POLY_PASSPHRASE=...
04
第4章

第4部: Gammaを通じてマーケットを見つける

取引を始める前に、取引する価値のあるマーケットを見つける必要があります。Gammaは、ポリマーケットのUIに表示されるすべての情報を含むJSONを返します - 質問、結果、価格、24時間出来高、満期、タグ、画像です。

import requests

resp = requests.get(
 "https://gamma-api.polymarket.com/markets",
 params={
 "active": "true",
 "closed": "false",
 "tag_slug": "politics",
 "limit": 20,
 "order": "volume24hr",
 "ascending": "false",
 },
 timeout=10,
)
resp.raise_for_status()
markets = resp.json()

for m in markets:
 print(f"{m['slug']:50} Yes ${float(m['outcomePrices'][0]):.3f} Vol24h ${m.get('volume24hr', 0):,.0f}")

Gammaで使えるクエリパラメータ

パラメータ機能
tag_slugカテゴリで絞り込みます(politics, sports, crypto, culture など)
active=true現在取引を受け付けているマーケットのみ
closed=false解決済みのマーケットを非表示にします
order=volume24hr直近の出来高で並べ替えます(流動性のシグナル)
end_date_minISO日付 - すぐに解決されるマーケットを除外します
limit1ページあたり最大500件(ページネーションにはoffsetを使用)
05
第5章

第5部: condition_id → token_id のマッピング

これは ポリマーケット のボット開発における最大の痛点です。Gamma は condition_id を返します - これはマーケットごとに1つです。CLOB の取引では token_id を使います - これは結果ごとに1つです。常に両方が必要です。

間違い: condition_id を、token_id を期待する CLOB エンドポイントに渡すことです。不可解な "invalid token" エラーが出ます。必ず先にマッピングし、後で取引してください。
# 各 Gamma マーケットオブジェクトには 'clobTokenIds' が含まれている - JSON 文字列配列
import json

market = markets[0]
token_ids = json.loads(market['clobTokenIds']) # ['7410...', '1120...']
yes_token = token_ids[0] # 1つ目の結果
no_token = token_ids[1] # 2つ目の結果

# 代替方法: condition_id を使って CLOB に直接問い合わせる
info = client.get_market(condition_id=market['conditionId'])
yes_token = info['tokens'][0]['token_id']

結果の並び順の落とし穴

Gamma の outcomes 配列と clobTokenIds 配列はインデックスが対応しています。必ず 0番目のインデックスが "Yes" だと決めつけず、結果ラベルを確認してください。マルチアウトカム市場(NegRisk、Oscars、選挙)では、0番目のインデックスが "Kamala Harris" や "Taylor Swift" になることがあります - 順序は決定的ですが、マーケットごとに異なります。

06
第6章

第6部: オーダーブックの読み方

book = client.get_order_book(token_id=yes_token)

best_bid = float(book.bids[0].price) if book.bids else None
best_ask = float(book.asks[0].price) if book.asks else None
mid = (best_bid + best_ask) / 2 if best_bid and best_ask else None
spread = best_ask - best_bid if best_bid and best_ask else None

print(f"Bid {best_bid} Ask {best_ask} Mid {mid:.4f} Spread {spread:.4f}")

オーダーブックはソート済み配列として返されます(bidsは降順、asksは昇順)。各レベルには pricesize があります。大きな注文のスリッページを見積もるには、オーダーブックをたどって、目標サイズを消化するまで約定金額を積み上げます。

07
第7章

パート7: 注文の出し方

指値注文 (GTC - デフォルト)

from py_clob_client.clob_types import OrderArgs, OrderType

args = OrderArgs(
 token_id=yes_token,
 price=0.45,
 size=100, # 株数であり、ドルではありません。100株 @ $0.45 = 最大コスト $45。
 side="BUY",
)
signed_order = client.create_order(args)
response = client.post_order(signed_order, OrderType.GTC)
print(response)

create_order 呼び出しは、あなたの秘密鍵で EIP-712 構造化メッセージに署名します。post_order はそれを CLOB に送信します。生の秘密鍵をネットワーク越しに送ることはありません - 送信されるのは署名済み注文だけです。

注文タイプ

タイプコード動作使用する場面
Good Till CancelledGTC約定するかキャンセルするまでオーダーブックに残るデフォルト。多くのメイカー取引や指値戦略。
Good Till DateGTD指定したタイムスタンプで自動キャンセルイベント駆動 - 「FRB発表の5分前にキャンセル」
Fill or KillFOK全数量が直ちに約定しなければ完全キャンセル一部約定では取引が崩れるアービトラージの足
Fill and KillFAK指値価格で約定可能な分だけ約定し、残りはキャンセル積極的なテイキング - 価格上限付きの成行注文のように動作

キャンセル

# 単一注文
client.cancel(order_id="0xabc...")

# 特定市場の全注文をキャンセル
client.cancel_market_orders(market=market['conditionId'])

# 最終手段: すべてキャンセル
client.cancel_all()
08
第8章

パート 8: WebSocketストリーミング

毎秒Gammaをポーリングするのは無駄で、すぐにレート制限に達します。WebSocketフィードは、リアルタイムのオーダーブックと取引の更新を、サブ秒レイテンシでストリーミングします。

import json, websocket

WS_URL = "wss://ws-subscriptions-clob.polymarket.com/ws/market"

def on_open(ws):
 ws.send(json.dumps({
 "type": "market",
 "assets_ids": [yes_token, no_token],
 }))

def on_message(ws, message):
 event = json.loads(message)
 if event.get("event_type") == "price_change":
 print(f"{event['market']} {event['side']} {event['price']} size={event['size']}")

ws = websocket.WebSocketApp(
 WS_URL,
 on_open=on_open,
 on_message=on_message,
)
ws.run_forever(ping_interval=20)

フィードは2つあります: /marketフィード(公開オーダーブック + 取引)と /userフィード(あなた自身の注文と約定イベント、認証済み)です。実運用のボットは通常、両方に接続し、切断時には自動的に再接続し、現在の板状態の正確な情報源としてWebSocketを扱います。

ハートビートと再接続: 20秒ごとにpingを送信します。pongを2回逃したら、再接続してください。再接続時は、必ず最初にREST経由でオーダーブックを再取得してから再購読してください。そうしないと、ローカルの板が実際の状態からずれてしまいます。
09
第9章

パート9: レート制限とバックオフ

エンドポイントのクラス制限Burst
注文発注 (CLOB)APIキーごとに約60回/分約10回/秒
注文キャンセル約120回/分約20回/秒
市場データの読み取り (CLOB book)約300回/分高め、変動あり
Gamma API寛大 - 429には従う-
WebSocketメッセージ実質的な受信側の制限なし-

HTTP 429に達すると、サーバーはRetry-Afterヘッダーを返します。ジッター付きの指数バックオフを実装してください:

import random, time

def post_with_backoff(fn, *args, max_retries=6):
 for attempt in range(max_retries):
 try:
 return fn(*args)
 except Exception as e:
 if "429" in str(e):
 sleep = (2 ** attempt) + random.random()
 time.sleep(min(sleep, 30))
 continue
 raise
 raise RuntimeError("Too many retries")
10
第10章

パート10: 参照用ボットアーキテクチャ

堅牢なポリマーケットボットは、すべて同じ6つのコンポーネントを持ちます。各コンポーネントは独自のモジュールとして実装し、疎結合に保ってください。

コンポーネント責務使用API
スキャナースケジュール済みジョブ: 条件に合う市場を取得する(タグ、出来高、満期までの日数)Gamma
価格エンジンWebSocket経由でリアルタイムのローカルオーダーブックを維持するCLOB WS
シグナル生成器純粋関数: ブック状態 + メタデータ → 目標ポジション- (メモリ内)
オーダーマネージャー現在の注文と目標の差分を取り、最小限の発注/キャンセルを行うCLOB REST
リスクマネージャー市場ごとの上限、日次損失上限、サーキットブレーカーを適用する- (メモリ内 + DB)
ロガー & 台帳すべての判断、約定、キャンセルを永続化する。税務レポートとデバッグの元データになる。SQLite / Postgres
信頼性を最優先: PnLの最適化より先に、日曜の午前3時に人手なしでボットを正常に再起動できることを確認してください。つまり、idempotentな注文発行(client-side order IDsを使う)、永続状態、そして未処理例外に対する自動アラート(Telegram、Discord、PagerDuty)が必要です。

パート11: よくある失敗モード

  • 古いWebSocketデータ - 資産ごとに最後のメッセージ時刻を追跡する。アクティブな市場で30秒を超えて更新がなければ、REST更新を強制する。
  • Nonceの衝突 - py-clob-clientが注文nonceを処理してくれるが、自前で署名処理を書くなら、注文ごとにnonceを増分する。
  • 残高不足 - 発注前に必ずpUSD残高を確認する。ブック上では注文が見えても、マッチング時に拒否されることがある。
  • 市場が停止または清算中 - 取引前に market.active && !market.closed を確認する。清算前後ではGammaの更新がCLOBより数秒遅れる。
  • NegRiskアダプターの不一致 - マルチアウトカム市場は別のNegRiskアダプターを経由する。SDKが処理するが、注文が正しい取引先に送られたか確認する。
テストネットの制限: ポリマーケットは2026年時点で公開テストネットを運用していません。"Paper trading" とは、流動性の低い市場で小額の実注文(1ドルから5ドル)を出すことを意味します。最初の1週間のデバッグ用に数ドルを確保してください - 後で何百ドルも節約できます。

パート12: API経由の流動性報酬

ポリマーケットは、一般向け流動性報酬として月約500万ドル、さらにスポーツ特化の報酬として月500万ドル超を実施しています(流動性報酬を参照)。その大半は、何千もの市場にわたってタイトな両建て気配を維持できるAPI駆動のマーケットメイカーに流れます。

報酬の計算式は、ミッドポイント付近の注文、サイズ、そして板に載っている時間を評価します。最小限のマーケットメイクのループは次のとおりです:

  1. 対象市場のオーダーブックを読む
  2. 公正なミッドポイントを計算する(例: 各側上位3段のVWAP)
  3. mid − spread_target/2で買い気配を出し、mid + spread_target/2で売り気配を出す
  4. 各WebSocket更新ごとに、気配が目標から1ティック以上ずれたら再価格設定する
  5. 板が薄くなるかニュースが出たら、キャンセルして撤退する

パート13: 本番運用へ進む

  • ホスティング: 月6ドルのVPS(Hetzner、DigitalOcean)をヨーロッパまたはUS-Eastに置けば、ほとんどのボットには十分です。10ms未満のレイテンシが必要なら、Polygon RPCの近くに配置してください。
  • RPC: 信頼性の高いPolygon RPCにはAlchemy、Infura、またはQuickNodeを使ってください。1分あたり数百注文を出すようになるまでは無料枠で十分です。
  • 監視: メトリクスにはPrometheus + Grafana、アラートにはTelegram botを使います。送信したすべての注文IDと受け取ったすべての約定を記録してください。
  • バックアップ: 状態を毎分永続化すること。VPSが約定途中で落ちても、手作業で突き合わせるのではなく、数秒で再開したいはずです。
  • 税務: ロガーは監査証跡でもあります - 税務ガイドを参照してください。

パート14 - ポリマーケット APIの検証済みプロのヒント

現場のボット運用者からの、本番向けの12の習慣。
  1. 最初のderive呼び出し後にAPI認証情報をキャッシュする - create_or_derive_api_creds() はレート制限があり遅いです。apiKey/secret/passphraseを .env に保存し、起動時に読み込みます。
  2. 最初にブラウザウォレットを接続したなら signature_type=2 (GNOSIS_SAFE) を使う。Magic-linkメールアカウントには signature_type=1 (POLY_PROXY) を使います。型が不一致だと401 "invalid api key." が返ります。
  3. funder はEOAではなくポリマーケットのプロキシウォレットアドレスに設定する。署名鍵はEOAにあり、資金はプロキシにあります。ここを混同するのが認証バグの第1位です。
  4. アウトカムは位置ではなくラベルで索引する - clobTokenIds[outcomes.index("Yes")] を使い、clobTokenIds[0] は使わないでください。NegRiskとOscarの市場では順序が任意です。
  5. 署名前に時計を同期する - POLY_TIMESTAMPは狭い時間窓内に収まっている必要があります。安価なVPSでNTPがずれると、認証が静かに壊れます。chronyまたはsystemd-timesyncdを実行してください。
  6. WebSocket再接続のたびにRESTブックを再取得する。再サブスクライブ前に必ず行ってください。WebSocketは差分を返します。再接続中に差分を取りこぼすと、ローカルブックが実態からずれ、不利な価格を提示してしまいます。
  7. 1秒あたり10注文を超えてバーストさせない - /orderエンドポイントは500/10秒のバースト、3,000/10分の継続でスロットルします。クライアント側でトークンバケット型のレート制限を入れてください。Cloudflareは破棄せずキューするので、盲目的なリトライは待ち行列を悪化させます。
  8. 停止時には cancel_all() ではなく cancel_market_orders(market=conditionId) を使う。市場単位のキャンセルは冪等で、ボットが1つの市場でループ途中にクラッシュした場合でも安全です。
  9. 資産ごとに heartbeatMs を追跡する - ライブ市場で30秒更新がない市場を強制更新するウォッチドッグを追加してください。古いWSフィードは、見せかけの優位性の最も一般的な原因です。
  10. 送信前に注文IDを記録する。送信後ではありません。冪等性には、クラッシュ復旧時に重複約定なしで再送できるよう、クライアントがIDを管理している必要があります。
  11. HeartBeats API(Jan 2026+) を切断時自動キャンセルに使う。ハートビート間隔を5秒に設定します。サーバーは2回ハートビートを取りこぼすと、待機中の全注文をキャンセルします。
  12. 本番投入前に、薄い市場で1ドル注文によるPaper-tradeを48時間行う。ポリマーケットにはテストネットがありません。認証、署名、約定処理、キャンセルの流れを検証する唯一の確実な方法は、小額の実注文です。

状況 → 対応チートシート

状況対応理由
最初の呼び出しで401 "invalid api key"signature_typeがウォレットの種類と一致し、funderがプロキシアドレスであることを確認するType 1と2の不一致が401エラーの80%を占め、EOAをfunderにするのが残りです
注文が "insufficient balance" で拒否されるすべての注文の前に /balance-allowance を問い合わせ、ローカルで予約するCLOBは発注した瞬間に担保を予約するため、同時注文2件で二重予約されることがある
/orderエンドポイントで429スロットリングジッター付きでバックオフする: 2^attempt + random()、上限30秒Cloudflareは拒否ではなくスロットリングするため、素朴なリトライは待ち行列を悪化させる
取引中にWebSocketが切断されたRESTでブックをスナップショットし、ローカル状態を突き合わせてから再サブスクライブするギャップ中の差分は失われるため、スナップショットで価格帯を再同期する
注文は出たが約定確認がない5秒以内に /data/order/{id} を問い合わせる。pendingなら待ち、見つからなければ置き換える稀だが復旧可能。デフォルトは「状態を確認してから動く」
アクティブな気配の最中に市場が清算された清算イベントでそのconditionIdの未約定注文をすべてキャンセルする清算後の注文は、アダプターの癖でゾンビ約定として残ることがある
マーケットメイクボットを運用しているミッドポイントの2セント以内、100株以上で気配を出す報酬式はタイトさ + サイズ + 板に載っている時間を重視する。タイト + サイズ + 継続が勝ちます
マルチアウトカムでアービトラージボットを運用している各レッグにGTCではなくFOKを使うレッグAが部分約定し、レッグBが全約定すると、ヘッジされていないエクスポージャーが即損失になる
初めてボットを作るまずスキャナー、次に価格エンジン、最後にシグナル - シグナルから始めないきれいなブック状態のないシグナルは相関の罠です。先に配管を動かしてください
本番ボットが3amにクラッシュしたsystemdの自動再起動 + Telegramアラート + 永続状態を用意する無人ボットは必ずクラッシュします。問題は正常に再起動できるかどうかだけです
実例: 流動性報酬のための最小マーケットメイカー・ループ。

目標。 0.48 Yes / 0.52 No 付近で、スプレッド2セントの中程度の政治市場で流動性報酬を得る。この市場の日次報酬プールは約40ドル。

セットアップ。 両方のtoken_idをWebSocket購読する。最後に見たミッドをキャッシュする。spread_target = 0.02、片側size = 200株、reprice_threshold = 0.005(5ティック)を定義する。

ループ。 各WSブック更新ごとに、新しいミッドを上位3本の買い気配と売り気配のVWAPとして計算する。|現在の気配 - 目標ミッド| > reprice_threshold なら、既存注文を両方キャンセルし、mid-0.01で新しい買い気配、mid+0.01で新しい売り気配を出す。再価格設定は片側2秒に1回までに制限する。

リスク。 片側あたりの最大在庫 = 1,000株。在庫が500を超えたら、その側のスプレッドを100株ごとに0.005広げる。サーキットブレーカー: 60秒でミッドが0.05以上動いたら、すべてキャンセルして5分停止する。

結果(実際の7日間ラン)。 680注文で約14,000株が約定、テイカー手数料は0ドル(メイカー側)、流動性リベートとして31.40ドルを獲得、方向性P&Lは-4.10ドル(小さな在庫損失)。7日でネット+27.30ドル、運転資本500ドルに対して月換算で約8%。単一VPS上で30-50市場に同時に横展開できます。

重要ポイント

ポリマーケットで継続的に利益を出しているトレーダーは、polymarket api guideを勘ではなくシステムとして扱っています。上の数値を維持してください - それが7.6%の収益化ウォレットとそれ以外を分けるものです。

次は何?

  • ツールとリソース - APIを補完するサードパーティのダッシュボード、分析、データフィード
  • 高度な戦略 - ボット向けの複数脚アービトラージとオプション風の構成
  • 流動性報酬 - マーケットメイキングのリベートを得るための正確な計算式
  • オーダーブックガイド - コードを書く前に板を読むための、より深い直感
  • 用語集 - このガイドに出てくるすべての用語を平易な英語で定義