Polymarket Bot Tutorial · Rozdział 8 z 32
Polymarket CLOB API dla botów: REST endpoints do snapshotów order book, subskrypcje WebSocket do aktualizacji w czasie rzeczywistym, parsowanie bids/asks, obliczanie mid-price i depth, przykłady kodu.
Co obejmuje ten rozdział
CLOB API to miejsce, gdzie ordery są podpisywane, wysyłane, matchowane i gdzie żyje order book. Polymarket ma dwa pokolenia SDK — przestarzałe v1 i aktualne v2. Ten rozdział obejmuje wyłącznie v2; v1 nie powinno pojawiać się w żadnym bocie, który wypuszczasz w 2026 roku. Omawiamy ścieżkę REST snapshot, kanał aktualizacji WebSocket, szczegóły parsowania, które potrafią wyłożyć nowych builderów, oraz logikę reconnectu, bez której długodziałający bot w ciągu kilku godzin wypada z synchronizacji.
To jest rozdział 8 naszej 32-częściowej serii o budowie Polymarket trading bota. Temat omawiamy szczegółowo w sekcjach poniżej. Treść dla każdej sekcji jest pisana i publikowana rozdział po rozdziale; odpowiedzi FAQ i reference są już kompletne i odzwierciedlają production experience z działania naszego własnego tradera.
- CLOB v1 vs v2 (use v2]
- Order book REST snapshot
- WebSocket subscriptions: market and user channels
- Parsing bids/asks/depth
- Computing mid-price and best-bid/ask
- Maker fees, taker fees, rebates
- Code: connect WS and process price-change events
- Reconnect and gap-handling
CLOB v1 vs v2 (use v2]
Polymarket utrzymuje dwa pokolenia SDK. v1 (@polymarket/clob-client na npm, py-clob-client <0.30) jest przestarzałe i nie ma kilku typów orderów dodanych w 2024 roku. v2 (@polymarket/clob-client-v2 v1.0.2 w Node, py-clob-client 0.34.6+ w Pythonie) to obecny standard.
Trzy konkretne różnice. v2 wspiera flagę negRisk dla rynków multi-outcome — wymaganą od momentu uruchomienia NegRisk exchange pod koniec 2024 roku. v2 dostarcza typy TypeScript dla kształtów wiadomości WebSocket; v1 zwraca any. v2 natywnie obsługuje flow podpisywania Gnosis Safe z sierpnia 2025; v1 wymaga niestandardowego glue do signing.
Reszta tego rozdziału jest napisana z założeniem, że wszędzie używasz v2. Jeśli w starszym tutorialu widzisz kod v1, traktuj go jako błędny, dopóki nie zostanie udowodnione inaczej — zwłaszcza składanie orderów na rynkach NegRisk pod v1 może po cichu kierować do niewłaściwego kontraktu exchange.
Order book REST snapshot
REST snapshot endpoint zwraca pełny book dla pojedynczego tokena w danym momencie.
GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>
Kształt odpowiedzi:
{
"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"}, ...]
}
Ceny są stringami z 2-3 miejscami po przecinku; sizes są stringami reprezentującymi liczbę share'ów (nie dolarów). Bids są sortowane od najwyższej do najniższej, asks od najniższej do najwyższej. hash to marker deduplikacji — powtarzane odczyty niezmienionego booka zwracają ten sam hash, więc bot może pominąć przetwarzanie.
REST snapshot to właściwy wybór dla jednorazowych lookupów (sprawdzenie ceny przy decyzji wejścia). Do ciągłego monitoringu użyj kanału WebSocket poniżej.
WebSocket subscriptions: market and user channels
Liczą się dwa kanały WebSocket.
Market channel: wss://ws-subscriptions-clob.polymarket.com/ws/market. Subskrybuj jeden lub wiele tokenów; otrzymasz aktualizacje order book w momencie, gdy się pojawiają.
{"type":"Market","markets":["0xCondId1","0xCondId2"]}
Wiadomości przychodzą przy każdej zmianie. Typy obejmują book (pełny snapshot), price_change (delta), tick_size_change (rzadko) oraz last_trade_price (najnowszy fill).
User channel: wss://ws-subscriptions-clob.polymarket.com/ws/user. Uwierzytelniony; otrzymujesz własne zdarzenia orderów — fills, partial fills, cancellations.
{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}
User channel to najczystszy sposób wykrywania filla. Polling orders REST endpoint kosztuje więcej i może przegapić zmiany stanu między odpytywaniem; WebSocket wypycha zdarzenie w momencie, gdy matcher je potwierdzi.
Parsing bids/asks/depth
Order book to lista poziomów cenowych z zagregowanym size. Dwa konwencjonalne sposoby parsowania, które trzeba zrobić dobrze.
Kierunek orderu: bids to ordery kupna (ktoś chce KUPIĆ po tej cenie). Gdy TWÓJ bot sprzedaje, uderza w bid. Gdy bot kupuje, podnosi ask. UI Polymarket pokazuje ten sam kierunek; niektóre inne exchange odwracają to.
Sortowanie: bids przychodzą posortowane malejąco (najlepszy bid pierwszy). asks przychodzą posortowane rosnąco (najlepszy ask pierwszy). Best bid to bids[0]; best ask to asks[0]. Uwaga: publiczny WebSocket czasem wysyła częściowe aktualizacje booka, które nie są wstępnie posortowane — zawsze defensywnie sortuj ponownie po każdym merge.
Depth na danym poziomie to wartość w dolarach możliwa do transakcji: price * size. Depth top-5 poziomów to popularna miara płynności: sum(b.price * b.size for b in bids[:5]). Jeśli depth top-5 jest poniżej $100, book jest illiquid i większość założeń strategii przestaje działać.
Computing mid-price and best-bid/ask
Trzy pochodne punkty cenowe, których potrzebuje bot.
- Best bid / best ask:
bids[0].priceiasks[0].price. Ceny, po których faktycznie możesz handlować, na jedną share. - Mid-price:
(best_bid + best_ask) / 2. Matematyczny środek spreadu. Przydatny do wyceny; nigdy nie handlujesz po mid. - Cena VWAP dla size N: przechodzisz przez book, aż skumulowany size osiągnie N, po czym zwracasz średnią cenę ważoną size. Faktyczny koszt KUPNA N share'ów teraz, z uwzględnieniem sweepu w głębsze poziomy.
Przypadek brzegowy: pusta strona bid lub ask (nikt nie sprzedaje albo nikt nie kupuje) oznacza, że book jest jednostronny. W strukturze rynku Polymarket dzieje się to na marketach resolved lub blisko resolved, gdzie jedna strona jest na 0.999 i nikt nie oferuje płynności po stronie przegranej. Traktuj best-bid = 0 lub best-ask = 1 jako sygnały „nie handluj”.
Maker fees, taker fees, rebates
Polymarket działa w modelu maker-taker fee. Liczby na maj 2026:
- Taker fee: 0 (zero) — ordery, które podnoszą istniejącą płynność booka, nie płacą prowizji. Pamiętaj, że koszty gas / network nadal obowiązują przy operacjach proxy.
- Maker rebate: niewielki dodatni, programowy, wypłacany za każdy wypełniony rested order w kwalifikujących się marketach programu rewardów. Nie wszystkie markety mają rewards.
- NegRisk markets: ta sama struktura opłat, ale na osobnym kontrakcie exchange; rewards naliczają się oddzielnie.
Zerowy taker fee sprawia, że Polymarket znacząco różni się od tradycyjnych venue CFD — większość „kosztu” tradingu to sam bid-ask spread, a nie jawna prowizja. Dla strategii przecinającej spread przy każdej transakcji spread tax to realny koszt; zakładaj 1-3 centy round-trip na typowych bookach, więcej na illiquid.
Maker rebates warto gonić tylko wtedy, gdy markety kwalifikujące się do liquidity-rewards pokrywają się z pomysłami na strategię. Rozdział 19 omawia liquidity-rewards farming jako osobne podejście.
Code: connect WS and process price-change events
Minimalny przykład w Node: połącz się, zasubskrybuj, loguj każde zdarzenie price-change dla jednego tokena.
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));
W jednej connection WebSocket komfortowo subskrybuj do około 30 tokenów. Powyżej tej liczby rozdziel ruch na kilka connections — serwer czasem porzuca duże subskrypcje bez błędu, co powoduje ciche odczyty przestarzałego booka.
Reconnect and gap-handling
Długo działające połączenie WebSocket prędzej czy później się rozłączy. Cloudflare cyklicznie resetuje connections co kilka godzin; sieci migną; Polymarket czasem wdraża zmiany. Zaplanuj to.
Strategia reconnectu: przy close lub error poczekaj min(2^attempt, 30) sekund z jitterem, a potem ponownie się zasubskrybuj. Zresetuj licznik attempt przy pierwszej udanej wiadomości po reconnect.
Gap-handling jest ważniejszy niż szybkość reconnectu. W czasie gdy WebSocket był rozłączony, book się zmienił. Przy każdym reconnectcie ponownie pobierz REST snapshot każdego zasubskrybowanego tokena i wykonaj reconciliation: wszystkie otwarte pozycje, których book zmienił się istotnie, wymagają ponownego sprawdzenia stanu, exits mogą wymagać odpalenia, alerty mogą być nieaktualne. Przypadek „przegapiłem 30 sekund aktualizacji booka” to cichy zabójca długodziałających botów — dalej działają na starej state i składają ordery po cenach, które już nie istnieją.
Defensive pattern: snapshotuj każdy zasubskrybowany book raz na minutę niezależnie od stanu WebSocket i traktuj WS jako fast-path optimization nad pollingiem snapshotów.











