Polymarket Bot Tutorial · অধ্যায় 8 of 32

বটের জন্য Polymarket CLOB API: order book snapshot-এর জন্য REST endpoints, real-time আপডেটের জন্য WebSocket subscriptions, bids/asks parsing, mid-price এবং depth computing, code samples.

এই অধ্যায়ে কী আছে

CLOB API-ই হলো সেই জায়গা যেখানে orders sign করা হয়, পাঠানো হয়, match করা হয়, এবং order book থাকে। Polymarket-এর দুইটি SDK generation আছে - deprecated v1 এবং বর্তমান v2। এই অধ্যায়ে শুধু v2 cover করা হয়েছে; 2026-এ আপনি যে bot ship করবেন তাতে v1 থাকা উচিত নয়। আমরা REST snapshot path, WebSocket update channel, নতুন builder-দের আটকে দেওয়া parsing details, এবং reconnect logic নিয়ে আলোচনা করব - এগুলো ছাড়া একটি long-running bot কয়েক ঘণ্টার মধ্যেই out of sync হয়ে যায়।

  • 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 দুইটি SDK generation maintain করে। v1 (@polymarket/clob-client on npm, py-clob-client <0.30) deprecated এবং 2024-এ যোগ হওয়া বেশ কিছু order type নেই। v2 (@polymarket/clob-client-v2 Node-এ v1.0.6, Python-এ py-clob-client 0.34.6+) হলো current standard।

তিনটি concrete difference। v2 multi-outcome market-এর জন্য negRisk flag support করে - NegRisk exchange late 2024-এ চালু হওয়ার পর থেকে এটি required। v2 WebSocket message shape-এর জন্য TypeScript types ship করে; v1 any return করে। v2 August 2025-এর Gnosis Safe signature flow natively handle করে; v1-এ custom signing glue লাগে।

এই অধ্যায়ের বাকি অংশ জুড়ে আমরা v2 ধরে লিখছি। আপনি যদি কোনো পুরনো tutorial-এ v1 code দেখেন, প্রমাণ না হওয়া পর্যন্ত সেটিকে broken ধরে নিন - বিশেষ করে NegRisk market-এ order placement v1-এ silently ভুল exchange contract-এ route হতে পারে।

Order book REST snapshot

REST snapshot endpoint নির্দিষ্ট একটি token-এর পূর্ণ book একটি নির্দিষ্ট সময়ে return করে।

GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>

Response shape:

{
  "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"}, ...]
}

Price string আকারে 2-3 decimal place-এ আসে; size হলো share count-এর string (dollar নয়)। Bids high-to-low sorted, asks low-to-high sorted। hash হলো deduplication marker - unchanged book-এর repeated poll একই hash return করে এবং আপনার bot processing skip করতে পারে।

একবারের lookup-এর জন্য REST snapshot-ই সঠিক পছন্দ (entry decision-এ price check)। Continuous monitoring-এর জন্য নিচের WebSocket channel ব্যবহার করুন।

WebSocket subscriptions: market and user channels

দুটি WebSocket channel গুরুত্বপূর্ণ।

Market channel: wss://ws-subscriptions-clob.polymarket.com/ws/market. এক বা একাধিক token subscribe করুন; order-book update যতক্ষণ ঘটছে ততক্ষণ তা receive করবেন।

{"type":"Market","markets":["0xCondId1","0xCondId2"]}

প্রতি change-এ message আসে। Type-এর মধ্যে আছে book (full snapshot), price_change (delta), tick_size_change (rare), এবং last_trade_price (সর্বশেষ fill)।

User channel: wss://ws-subscriptions-clob.polymarket.com/ws/user. Authenticated; আপনার own order event - fills, partial fills, cancellations - receive করবেন।

{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}

Fill detect করার জন্য user channel সবচেয়ে clean way। orders REST endpoint poll করা বেশি expensive এবং poll-এর মধ্যে state change miss করতে পারে; WebSocket matcher সেটা acknowledge করার মুহূর্তেই event push করে।

Parsing bids/asks/depth

Order book হলো aggregated size-সহ price level-এর একটি list। ঠিকভাবে ধরার জন্য দুটি parsing convention গুরুত্বপূর্ণ।

Order direction: bids হলো buy order (এই price-এ কেউ BUY করতে চায়)। যখন আপনার bot sell করে, তখন আপনি একটি bid hit করেন। যখন আপনার bot buy করে, তখন আপনি ask lift করেন। Polymarket UI একই direction দেখায়; অন্য কিছু exchange উল্টোভাবে দেখায়।

Sorting: bids descending order-এ আসে (best bid প্রথমে)। asks ascending order-এ আসে (best ask প্রথমে)। Best bid হলো bids[0]; best ask হলো asks[0]। সতর্ক থাকুন: public WebSocket কখনও কখনও partial book update পাঠায় যা pre-sorted নয় - কোনো merge-এর পরে সবসময় defensively re-sort করুন।

কোনো level-এ depth মানে হলো transactable dollar value: price * size। Top-5-level depth একটি common liquidity metric: sum(b.price * b.size for b in bids[:5])। যদি top-5 depth $100-এর নিচে হয়, book illiquid এবং বেশিরভাগ strategy assumption ভেঙে যায়।

Computing mid-price and best-bid/ask

আপনার bot-এর দরকার তিনটি derived price point।

  • Best bid / best ask: bids[0].price এবং asks[0].price. আপনি বাস্তবে যেটাতে trade করতে পারবেন, এক share-এর জন্য।
  • Mid-price: (best_bid + best_ask) / 2. Spread-এর mathematical center। valuation-এর জন্য useful; আপনি mid-এ trade করেন না।
  • VWAP price for size N: cumulative size N-এ পৌঁছানো পর্যন্ত book walk করুন, তারপর size-weighted average price return করুন। এখনই N share BUY করার আসল cost, deeper level sweep ধরেই।

Edge case: bid বা ask side empty থাকা (কেউ sell করছে না, বা কেউ buy করছে না) মানে book one-sided। Polymarket-এর market structure-এ এটা resolved বা near-resolved market-এ ঘটে, যেখানে এক side 0.999-এ এবং loser side-এ কেউ liquidity offer করে না। best-bid = 0 বা best-ask = 1-কে "do not trade" signal হিসেবে নিন।

Maker fees, taker fees, rebates

নিজের ইতিহাসের বেশিরভাগ সময় Polymarket কোনো trading fee নেয়নি। 2026-এ এটি বদলে যায়: fee বছরের শুরুতে 15-মিনিটের crypto market-এ চালু হয়, 30 মার্চ 2026-এ Sports-এ সম্প্রসারিত হয়, এবং তারপর থেকে বেশিরভাগ category-তে প্রয়োগ হয়। যে কোনো tutorial যা এখনও দাবি করে Polymarket fee-মুক্ত, তা পুরনো - আর high-frequency strategy-তে কেউ এটি উপেক্ষা করলে নীরবে খেয়ে ফেলা হবে। 2026-এর মাঝামাঝি অনুযায়ী model আসলে যেভাবে কাজ করে তা এখানে।

প্রথমে প্রতিটি trade-এর দুটি দিক। maker হলো সেই যে book-এ একটি অপেক্ষমাণ limit order রাখে যা সেখানে অপেক্ষা করে; taker হলো সেই যে এমন order পাঠায় যা বিদ্যমান liquidity-র বিপরীতে সঙ্গে সঙ্গে execute হয়। maker এখনও শূন্য fee দেয় এবং উপরন্তু একটি rebate পায়; fee কেবল taker-রা দেয়।

taker fee কোনো স্থির শতাংশ নয়। এটি এমন একটি curve অনুসরণ করে যা order-এর আকার এবং price উভয়ের উপর নির্ভর করে:

fee = shares × feeRate × price × (1 - price)

price × (1 - price) পদটি price 0.50-তে (একটি সত্যিকারের "coin-flip" market) সর্বোচ্চ হয় এবং 0 বা 1-এর দিকে সংকুচিত হয়। অন্য কথায়, সবচেয়ে অনিশ্চিত market-এ আপনি সর্বোচ্চ fee দেন এবং প্রায়-নিষ্পন্ন market-এ প্রায় কিছুই নয়। feeRate প্রতিটি category-র জন্য নির্ধারিত:

  • Crypto: feeRate 0.07 (সর্বোচ্চ, effective peak প্রায় 1.8%), maker rebate 20%।
  • Sports: feeRate 0.03 (peak প্রায় 0.75%), maker rebate 25%।
  • Finance, Politics, Tech, Mentions: feeRate 0.04, maker rebate 25%।
  • Economics, Culture, Weather, সাধারণ: feeRate 0.05, maker rebate 25%।
  • Geopolitics এবং বড় বিশ্ব-ঘটনা: 0, এখনও fee-মুক্ত।

একটি হিসাবের উদাহরণ। ধরুন আপনার bot 0.50 price-এ একটি crypto market-এর 100 shares নেয়। fee হবে 100 × 0.07 × 0.50 × (1 - 0.50) = 100 × 0.07 × 0.25 = $1.75। আপনি যদি একই 100 shares 0.90-তে নেন, fee কমে 100 × 0.07 × 0.90 × 0.10 = $0.63 হয়, কারণ price অনিশ্চিত মাঝখান থেকে দূরে। bot-এর জন্য শিক্ষা স্পষ্ট: অস্থির, প্রায়-ভারসাম্যপূর্ণ crypto ও sports market-এ liquidity নেওয়া সবচেয়ে বেশি fee নেয় - তাই ঠিক সেখানেই fee দেওয়ার বদলে maker হিসেবে quote করে rebate তুলে নেওয়া সবচেয়ে লাভজনক।

explicit fee ছাড়াও, প্রতিবার আপনি bid-ask spread cross করলে সেই spread-ও দেন। spread হলো সেরা buy price এবং সেরা sell price-এর মধ্যকার ফাঁক, এবং taker হিসেবে ঢোকা-বেরোনো strategy-র জন্য সেই ফাঁক fee-র উপরে একটি বাস্তব cost। সাধারণ book-এ round-trip 1-3 cents এবং illiquid-এ আরও বেশি ধরে নিন। NegRisk market (multi-outcome exchange) একই fee model ব্যবহার করে কিন্তু আলাদা contract-এ settle হয়, তাই তাদের rewards আলাদাভাবে accrue করে। Chapter 19-এ liquidity-rewards farming cover করা হয়েছে, যেখানে maker rebate তুলে নেওয়াই strategy, কেবল কোনো side-effect নয়।

Code: connect WS and process price-change events

Minimal Node example: connect করুন, subscribe করুন, একটি token-এর জন্য প্রতিটি price-change event log করুন।

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));

একটি WebSocket connection-এ প্রায় 30 token পর্যন্ত subscribe করা আরামদায়ক। এর বেশি হলে multiple connection-এ split করুন - server মাঝে মাঝে error না দিয়েই বড় subscription drop করে দেয়, ফলে silent stale book read তৈরি হয়।

Reconnect and gap-handling

একটি long-running WebSocket connection drop করবে। Cloudflare কয়েক ঘণ্টা পরপর connection cycle করে; network blink করে; Polymarket কখনও কখনও deploy করে। সে অনুযায়ী পরিকল্পনা করুন।

Reconnect strategy: close বা error-এ min(2^attempt, 30) seconds jitter-সহ wait করুন, তারপর re-subscribe করুন। Reconnect-এর পরে প্রথম successful message-এ attempt counter reset করুন।

Gap handling reconnect speed-এর চেয়ে বেশি গুরুত্বপূর্ণ। WebSocket disconnected থাকার সময় book নড়েছে। প্রতিটি reconnect-এ subscribed token-এর REST snapshot আবার fetch করুন এবং reconcile করুন: যেকোনো open position whose book meaningfully moved, state re-check দরকার; exits fire করতে হতে পারে; alarm stale হতে পারে। "আমি 30 seconds-এর book update miss করেছি" - এটা long-running bot-এর silent killer; bot stale state-এ চালতে থাকে এবং এমন price-এ order দেয় যা আর নেই।

Defensive pattern: WebSocket state যাই হোক না কেন, প্রতি মিনিটে সব subscribed book-এর snapshot নিন, এবং WS-কে snapshot poll-এর উপর built একটি fast-path optimization হিসেবে ধরুন।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

Polymarket CLOB API endpoint কী?
Base CLOB endpoint হলো https://clob.polymarket.com (REST) এবং wss://ws-subscriptions-clob.polymarket.com/ws/market (WebSocket)। এগুলোই V2 endpoint, যা @polymarket/clob-client-v2 এবং py-clob-client ব্যবহার করে।
Order book পড়তে কি API key লাগে?
না। Order book read (snapshot এবং WebSocket subscription) public এবং কোনো authentication লাগে না। শুধু order place/cancel করা এবং account-specific data (positions, fills) পড়ার জন্য API key লাগে।
CLOB WebSocket কত দ্রুত price update push করে?
Order match হওয়ার গতিতে। Active market-এ প্রতি কয়েকশো millisecond-এ update দেখা যায়; thin market-এ শুধু actual order-এ update হয়। Depth change এবং trade event উভয়ই একই WS channel দিয়ে যায় - প্রতিটিকে সঠিকভাবে handle করতে event type parse করুন।
আমি কীভাবে Polymarket order book-এর mid-price compute করব?
mid = (best_bid + best_ask) / 2 যদি দুটোই থাকে; না থাকলে fallback হিসেবে last_trade_price ব্যবহার করুন। Thin book-এ সতর্ক থাকুন যেখানে best_bid best_ask-এর অনেক নিচে - তখন mid অর্থহীন হতে পারে। Mid-কে fair price হিসেবে ধরার আগে সবসময় spread-ও বিবেচনা করুন।
2026-এ Polymarket-এর maker fee কত?
maker-রা 0% দেয় এবং একটি rebate পায় (crypto-তে 20%, বেশিরভাগ অন্য category-তে 25%)। fee কেবল taker-রা দেয়, এবং এটি স্থির নয়: এটি fee = shares × feeRate × price × (1 - price) অনুসরণ করে, তাই 0.50-এর কাছে "coin-flip" market-এ সর্বোচ্চ হয় এবং প্রান্তের দিকে সংকুচিত হয়। category অনুযায়ী feeRate 0.03 (Sports, effective peak প্রায় 0.75%) থেকে 0.07 (Crypto, effective peak প্রায় 1.8%) পর্যন্ত যায়, আর Geopolitics এখনও fee-মুক্ত। এই maker-taker asymmetry-ই কারণ যে active bot প্রায় সবসময় market order দিয়ে spread cross করার বদলে অপেক্ষমাণ limit order দিয়ে quote করে।
WebSocket disconnect হলে কীভাবে handle করব?
Exponential backoff (1s, 2s, 4s, max 30s) দিয়ে reconnect করুন, একই market-এ re-subscribe করুন, এবং gap পূরণ করতে একটি REST snapshot আবার fetch করুন। Stale order book-এ কখনও ভরসা করবেন না - যদি 5 seconds-এর বেশি disconnected থাকেন, order place করার আগে fresh snapshot request করুন।