Hướng dẫn Bot Polymarket · Chương 8 trên 32
Polymarket CLOB API cho bots: REST endpoints để lấy order book snapshots, WebSocket subscriptions cho real-time updates, phân tích bids/asks, tính mid-price và depth, code samples.
Chương này bao gồm những gì
CLOB API là nơi orders được ký, gửi, khớp, và cũng là nơi order book tồn tại. Polymarket có hai thế hệ SDK - v1 đã bị deprecate và v2 hiện tại. Chương này chỉ đề cập đến v2; v1 không nên xuất hiện trong bất kỳ bot nào bạn triển khai vào năm 2026. Chúng ta sẽ đi qua luồng REST snapshot, WebSocket update channel, các chi tiết parsing dễ khiến builder mới mắc lỗi, và logic reconnect mà nếu thiếu thì một bot chạy lâu sẽ lệch khỏi trạng thái thực tế chỉ sau vài giờ.
- CLOB v1 so với v2 (dùng v2]
- Order book REST snapshot
- WebSocket subscriptions: market và user channels
- Phân tích bids/asks/depth
- Tính mid-price và best-bid/ask
- Maker fees, taker fees, rebates
- Code: kết nối WS và xử lý price-change events
- Reconnect và xử lý gap
CLOB v1 so với v2 (dùng v2]
Polymarket duy trì hai thế hệ SDK. v1 (@polymarket/clob-client trên npm, py-clob-client <0.30) đã bị deprecate và thiếu một số order types được thêm vào năm 2024. v2 (@polymarket/clob-client-v2 v1.0.2 trong Node, py-clob-client 0.34.6+ trong Python) là standard hiện tại.
Có ba khác biệt cụ thể. v2 hỗ trợ cờ negRisk cho multi-outcome markets - yêu cầu bắt buộc kể từ khi NegRisk exchange ra mắt vào cuối năm 2024. v2 cung cấp TypeScript types cho cấu trúc WebSocket message; v1 trả về any. v2 xử lý native luồng ký Gnosis Safe từ tháng 8 năm 2025; v1 cần custom signing glue.
Phần còn lại của chương này được viết với giả định luôn dùng v2. Nếu bạn thấy code v1 trong một tutorial cũ, hãy xem nó là lỗi cho đến khi được chứng minh ngược lại - đặc biệt là việc đặt lệnh vào NegRisk markets dưới v1 có thể âm thầm route tới sai exchange contract.
Order book REST snapshot
REST snapshot endpoint trả về toàn bộ book cho một token duy nhất tại một thời điểm.
GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>
Cấu trúc response:
{
"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"}, ...]
}
Prices là strings với 2-3 chữ số thập phân; sizes là strings biểu thị số lượng shares (không phải dollars). Bids được sắp xếp từ cao xuống thấp, asks từ thấp lên cao. hash là một marker để chống trùng lặp - các lần poll lặp lại trên một book không thay đổi sẽ trả về cùng hash và bot của bạn có thể bỏ qua việc xử lý.
REST snapshot là lựa chọn đúng cho các truy vấn một lần (kiểm tra giá khi ra quyết định vào lệnh). Với giám sát liên tục, hãy dùng WebSocket channel bên dưới.
WebSocket subscriptions: market và user channels
Có hai WebSocket channels quan trọng.
Market channel: wss://ws-subscriptions-clob.polymarket.com/ws/market. Subscribe một hoặc nhiều tokens; nhận các order-book updates khi chúng xảy ra.
{"type":"Market","markets":["0xCondId1","0xCondId2"]}
Messages đến mỗi khi có thay đổi. Các loại bao gồm book (full snapshot), price_change (delta), tick_size_change (hiếm), và last_trade_price (lần khớp gần nhất).
User channel: wss://ws-subscriptions-clob.polymarket.com/ws/user. Đã xác thực; nhận các sự kiện order của chính bạn - fills, partial fills, cancellations.
{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}
User channel là cách sạch nhất để phát hiện một fill. Poll REST endpoint của orders tốn nhiều chi phí hơn và có thể bỏ lỡ thay đổi trạng thái giữa các lần poll; WebSocket đẩy sự kiện ngay khi matcher xác nhận nó.
Phân tích bids/asks/depth
Order book là danh sách các price levels với size được cộng gộp. Có hai quy ước parsing cần làm đúng.
Order direction: bids là buy orders (ai đó muốn MUA ở mức giá này). Khi bot của BẠN bán, bạn khớp vào một bid. Khi bot của bạn mua, bạn lift một ask. Polymarket UI hiển thị cùng chiều; một số exchange khác thì đảo ngược.
Sorting: bids đi theo thứ tự giảm dần (best bid trước). asks đi theo thứ tự tăng dần (best ask trước). Best bid là bids[0]; best ask là asks[0]. Lưu ý: public WebSocket đôi khi gửi partial book updates chưa được pre-sort - hãy luôn re-sort một cách phòng thủ sau mỗi lần merge.
Depth tại một level là giá trị dollar có thể giao dịch: price * size. Top-5-level depth là một chỉ số thanh khoản phổ biến: sum(b.price * b.size for b in bids[:5]). Nếu top-5 depth dưới $100, book này kém thanh khoản và hầu hết giả định chiến lược sẽ không còn đúng.
Tính mid-price và best-bid/ask
Có ba price points dẫn xuất mà bot của bạn cần.
- Best bid / best ask:
bids[0].pricevàasks[0].price. Đây là mức giá bạn thực sự có thể giao dịch, cho một share. - Mid-price:
(best_bid + best_ask) / 2. Tâm toán học của spread. Hữu ích cho định giá; bạn không bao giờ giao dịch tại mid. - VWAP price cho size N: đi qua book cho đến khi cumulative size đạt N, rồi trả về giá trung bình gia quyền theo size. Đây là chi phí thực tế để MUA N shares ngay lúc này, có tính đến việc sweep sang các level sâu hơn.
Edge case: một bên bid hoặc ask trống (không ai bán, hoặc không ai mua) nghĩa là book chỉ có một phía. Trong cấu trúc market của Polymarket, điều này xảy ra ở các markets đã được resolve hoặc gần resolve, nơi một phía ở mức 0.999 và không ai cung cấp thanh khoản ở phía thua. Hãy xem best-bid = 0 hoặc best-ask = 1 là tín hiệu "không giao dịch".
Maker fees, taker fees, rebates
Polymarket vận hành mô hình phí maker-taker. Các con số tính đến tháng 5 năm 2026:
- Taker fee: 0 (zero) - các orders hút thanh khoản sẵn có trong book không phải trả phí. Lưu ý rằng gas / network costs vẫn áp dụng cho proxy operations.
- Maker rebate: nhỏ, dương, được trả theo chương trình cho mỗi rested order được fill trong các markets đủ điều kiện của reward program. Không phải thị trường nào cũng có rewards.
- NegRisk markets: cùng cấu trúc phí nhưng trên một exchange contract riêng; rewards được tích lũy riêng.
Zero taker fee khiến Polymarket khác biệt đáng kể so với các CFD venue truyền thống - phần lớn "chi phí" giao dịch thực ra là bid-ask spread, không phải fee tường minh. Với chiến lược vượt spread ở mọi giao dịch, spread tax mới là chi phí thực; hãy giả định 1-3 cents cho một round-trip trên các book điển hình, và cao hơn ở các book kém thanh khoản.
Maker rebates chỉ đáng theo đuổi khi các markets đủ điều kiện liquidity rewards khớp với ý tưởng chiến lược. Chương 19 sẽ đề cập chi tiết liquidity-rewards farming như một phương pháp riêng.
Code: kết nối WS và xử lý price-change events
Ví dụ Node tối giản: kết nối, subscribe, log mọi price-change event cho một token.
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));
Hãy subscribe khoảng tối đa ~30 tokens cho mỗi WebSocket connection một cách thoải mái. Vượt quá mức đó, hãy tách ra nhiều connections - server đôi khi sẽ làm rơi các subscriptions lớn mà không báo lỗi, dẫn đến việc đọc book bị stale một cách âm thầm.
Reconnect và xử lý gap
Một WebSocket connection chạy lâu sẽ bị rớt. Cloudflare luân chuyển connections mỗi vài giờ; network chập chờn; Polymarket đôi khi deploy. Hãy lên kế hoạch cho điều đó.
Chiến lược reconnect: khi close hoặc error, chờ min(2^attempt, 30) giây có thêm jitter, rồi subscribe lại. Reset attempt counter sau message thành công đầu tiên sau khi reconnect.
Xử lý gap quan trọng hơn tốc độ reconnect. Trong lúc WebSocket bị ngắt, book đã di chuyển. Mỗi khi reconnect, hãy fetch lại REST snapshot của mọi token đã subscribe và đối soát: bất kỳ open positions nào có book thay đổi đáng kể đều cần re-check state, các exits có thể cần kích hoạt, alarms có thể đã stale. Trường hợp "tôi đã bỏ lỡ 30 giây cập nhật book" là kẻ giết thầm lặng của các bot chạy dài - chúng tiếp tục hoạt động trên state cũ và đặt orders ở những mức giá không còn tồn tại.
Mẫu phòng thủ: snapshot mọi subscribed book một lần mỗi phút bất kể trạng thái WebSocket, và coi WS là một optimization fast-path nằm trên lớp poll snapshot.


