ポリマーケット Bot チュートリアル · 第 8 章 / 全 32 章
ボット向けの ポリマーケット CLOB API: オーダーブックスナップショット用の REST エンドポイント、リアルタイム更新用の WebSocket サブスクリプション、bid/ask の解析、ミッドプライスと深さの計算、コードサンプル。
この章で扱う内容
CLOB API は、注文が署名され、送信され、マッチングされ、そしてオーダーブックが存在する場所です。ポリマーケット には 2 世代の SDK があります。非推奨の v1 と、現在の v2 です。この章では v2 のみを扱います。2026 年にあなたが出すボットに v1 が含まれていてはいけません。ここでは、REST スナップショットの取得経路、WebSocket 更新チャネル、新規ビルダーがつまずきやすいパースの詳細、そして長時間稼働するボットが数時間で同期ズレを起こさないために必要な再接続ロジックまで解説します。
これは、ポリマーケット のトレーディングボットを作る全 32 回シリーズの第 8 章です。以下の各セクションでこのトピックを詳しく扱います。各セクションの本文は章ごとに順次執筆・公開していきます。FAQ の回答と参考情報はすでに完成しており、自前のトレーダーを運用した実戦経験を反映しています。
- CLOB v1 vs v2(v2 を使用)
- オーダーブックの REST スナップショット
- WebSocket サブスクリプション:market と user チャネル
- bid/ask/depth の解析
- ミッドプライスと best-bid/ask の計算
- maker fee、taker fee、rebate
- コード:WS 接続と price-change イベント処理
- 再接続とギャップ処理
CLOB v1 vs v2(v2 を使用)
ポリマーケット は 2 世代の SDK を提供しています。v1(npm の @polymarket/clob-client、py-clob-client 0.30 未満)は非推奨で、2024 年に追加された複数の注文タイプがありません。v2(Node では @polymarket/clob-client-v2 v1.0.2、Python では py-clob-client 0.34.6 以上)が現在の標準です。
具体的な違いは 3 つあります。v2 は複数結果市場向けの negRisk フラグをサポートしており、これは 2024 年末に NegRisk 取引所が立ち上がって以降必須です。v2 は WebSocket メッセージの型に対する TypeScript 型定義を同梱していますが、v1 は any を返します。v2 は 2025 年 8 月の Gnosis Safe 署名フローをネイティブに処理しますが、v1 ではカスタム署名処理のつなぎ込みが必要です。
この章の以降の内容は、すべて v2 を前提に書かれています。古いチュートリアルで v1 のコードを見かけても、別の証拠がない限り壊れているものとして扱ってください。特に NegRisk 市場への注文発注は、v1 では静かに誤った取引所コントラクトへルーティングされます。
オーダーブックの REST スナップショット
REST スナップショットエンドポイントは、特定時点における単一トークンの完全な板情報を返します。
GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>
レスポンス形式:
{
"market": "0x...",
"asset_id": "5413...",
"timestamp": "1715600000000",
"hash": "0x...",
"bids": [{"price":"0.45","size":"120"}, {"price":"0.44","size":"380"}, ...],
"asks": [{"price":"0.47","size":"85"}, {"price":"0.48","size":"210"}, ...]
}
価格は小数点 2〜3 桁の文字列で、サイズは株数を表す文字列です(ドルではありません)。bids は高い順、asks は低い順に並びます。hash は重複排除用のマーカーです。変化のない板を繰り返し取得すると同じ hash が返るため、ボット側で処理をスキップできます。
REST スナップショットは、一度だけ確認したい場合(例:エントリー判断時の価格チェック)に適しています。継続監視には、下記の WebSocket チャネルを使ってください。
WebSocket サブスクリプション:market と user チャネル
重要な WebSocket チャネルは 2 つあります。
Market チャネル: wss://ws-subscriptions-clob.polymarket.com/ws/market。1 つまたは複数のトークンを購読し、発生した順にオーダーブック更新を受け取ります。
{"type":"Market","markets":["0xCondId1","0xCondId2"]}
メッセージは変更があるたびに届きます。タイプには book(完全スナップショット)、price_change(差分)、tick_size_change(まれ)、last_trade_price(直近約定価格)が含まれます。
User チャネル: wss://ws-subscriptions-clob.polymarket.com/ws/user。認証が必要で、自分の注文イベント――約定、部分約定、キャンセル――を受け取ります。
{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}
User チャネルは、約定を検知する最もきれいな方法です。orders REST エンドポイントをポーリングする方法はコストが高く、ポーリング間の状態変化を見逃すことがあります。WebSocket なら、マッチャーが承認した瞬間にイベントがプッシュされます。
bid/ask/depth の解析
オーダーブックは、価格帯ごとに集約されたサイズの一覧です。正しく押さえるべき解析ルールが 2 つあります。
注文方向: bids は買い注文です(誰かがこの価格で買いたい)。あなたのボットが売る場合は bid にぶつけます。買う場合は ask を取ります。ポリマーケット の UI も同じ向きで表示しますが、他の取引所では逆の場合があります。
ソート順: bids は降順で届きます(最良 bid が先頭)。asks は昇順で届きます(最良 ask が先頭)。最良 bid は bids[0]、最良 ask は asks[0] です。注意:公開 WebSocket は、事前ソートされていない部分更新を送ることがあります。マージ後は必ず防御的に再ソートしてください。
ある価格帯の depth は、実際に取引可能なドル価値です。price * size で求めます。トップ 5 段の depth は、よく使われる流動性指標です。sum(b.price * b.size for b in bids[:5]) で計算できます。トップ 5 の depth が 100 ドル未満なら、その板は流動性が低く、ほとんどの戦略前提が崩れます。
ミッドプライスと best-bid/ask の計算
ボットに必要な 3 つの派生価格です。
- Best bid / best ask:
bids[0].priceとasks[0].price。実際に 1 株で売買できる価格です。 - Mid-price:
(best_bid + best_ask) / 2。スプレッドの数学的な中心です。評価には便利ですが、mid で実際に約定することはありません。 - サイズ N の VWAP 価格: N に達するまで板を順にたどり、出来高加重平均価格を返します。より深い価格帯まで食い込むことを織り込んだ、いま N 株を BUY したときの実コストです。
例外ケースとして、bid 側または ask 側が空(誰も売っていない、あるいは誰も買っていない)なら、その板は片側だけの状態です。ポリマーケット の市場構造では、解決済み、または解決間近の市場で起こり、片側が 0.999 で反対側に流動性提供者がいない場合があります。best-bid = 0 または best-ask = 1 は「取引しない」シグナルとして扱ってください。
maker fee、taker fee、rebate
ポリマーケット は maker-taker 料金モデルで運営されています。2026 年 5 月時点の数値は次のとおりです。
- Taker fee: 0(ゼロ)― 既存の板の流動性を取る注文に手数料はかかりません。なお、proxy 操作には gas / network コストが発生します。
- Maker rebate: 小額のプラス。対象の報酬プログラム市場で、約定した指値注文に対してプログラム的に支払われます。すべての市場に報酬があるわけではありません。
- NegRisk markets: 料金体系は同じですが、別の取引所コントラクト上で動作します。報酬は別に加算されます。
Taker fee がゼロという点は、ポリマーケット を従来の CFD 取引所と大きく異なるものにしています。取引コストの大半は明示的な手数料ではなく、bid-ask スプレッドそのものです。毎回スプレッドを跨ぐ戦略なら、真のコストはスプレッド税です。一般的な板では往復で 1〜3 セント、流動性の低い板ではそれ以上と見積もってください。
Maker rebate を狙う価値があるのは、流動性報酬対象市場が自分の戦略アイデアと噛み合う場合だけです。流動性報酬のファーミングについては、第 19 章で専用に扱います。
コード:WS 接続と price-change イベント処理
最小限の Node 例です。接続し、購読し、1 つのトークンについてすべての price-change イベントをログします。
import WebSocket from "ws";
const ws = new WebSocket("wss://ws-subscriptions-clob.polymarket.com/ws/market");
ws.on("open", () => {
ws.send(JSON.stringify({ type: "Market", markets: ["<CONDITION_ID>"] }));
});
ws.on("message", (data) => {
const msg = JSON.parse(data.toString());
if (msg.event_type === "price_change") {
console.log("price_change", msg.asset_id, msg.changes);
} else if (msg.event_type === "book") {
console.log("book snapshot", msg.bids?.[0], msg.asks?.[0]);
}
});
ws.on("close", () => console.log("closed"));
ws.on("error", (e) => console.error("err", e.message));
1 つの WebSocket 接続で、およそ 30 トークンまでなら問題なく購読できます。それを超える場合は複数接続に分けてください。サーバーは大きな購読をエラーなしで落とすことがあり、その結果、静かに stale な板を読み続けることになります。
再接続とギャップ処理
長時間稼働する WebSocket 接続は切断されます。Cloudflare は数時間ごとに接続をローテーションし、ネットワークは瞬断し、ポリマーケット 側もデプロイを行います。そこまで見越して設計してください。
再接続戦略は次のとおりです。close または error の後、ジッター付きで min(2^attempt, 30) 秒待ち、その後に再購読します。再接続後、最初に正常なメッセージを受け取った時点で attempt カウンタをリセットします。
再接続速度以上に重要なのは、ギャップ処理です。WebSocket が切れていた間に、板は動いています。再接続のたびに、購読中の各トークンについて REST スナップショットを再取得し、整合性を取ってください。板が意味のあるほど動いた未決済ポジションは状態再確認が必要で、出口注文は発火させるべきかもしれませんし、アラートは古くなっている可能性があります。「30 秒分の板更新を取り逃した」ケースは、長時間稼働ボットの静かな致命傷です。古い状態のまま動き続け、もはや存在しない価格で注文を出してしまいます。
防御的なパターンとして、WebSocket の状態に関係なく、購読中の各板を 1 分ごとにスナップショットし、WS はスナップショットポーリングの上に乗る高速経路として扱ってください。


