آموزش ربات پلی‌مارکت · فصل 8 از 32

پلی‌مارکت CLOB API برای botها: REST endpointها برای order book snapshotها، WebSocket subscriptionها برای real-time updateها، parsing of bids/asks، محاسبه mid-price و depth، نمونه‌کدها.

این فصل چه چیزهایی را پوشش می‌دهد

CLOB API جایی است که orderها امضا می‌شوند، ارسال می‌شوند، match می‌شوند، و order book آنجا قرار دارد. پلی‌مارکت دو نسل SDK دارد - نسخه deprecated v1 و نسخه current v2. این فصل فقط v2 را پوشش می‌دهد؛ v1 نباید در هیچ botی که در 2026 منتشر می‌کنید ظاهر شود. ما مسیر REST snapshot، کانال به‌روزرسانی WebSocket، جزئیات parsing که برای builderهای تازه‌کار دردسرساز می‌شوند، و منطق reconnect را بررسی می‌کنیم؛ منطقی که بدون آن یک bot طولانی‌مدت ظرف چند ساعت از sync خارج می‌شود.

  • CLOB v1 در برابر v2 (از v2 استفاده کنید)
  • Order book REST snapshot
  • WebSocket subscriptionها: market و user channelها
  • Parsing bids/asks/depth
  • محاسبه mid-price و best-bid/ask
  • Maker fee، taker fee، rebate
  • Code: اتصال WS و پردازش price-change eventها
  • Reconnect و gap-handling

CLOB v1 در برابر v2 (از v2 استفاده کنید)

پلی‌مارکت دو نسل SDK را نگه می‌دارد. v1 (@polymarket/clob-client در npm، py-clob-client <0.30) deprecated شده و چندین order type اضافه‌شده در 2024 را ندارد. v2 (@polymarket/clob-client-v2 نسخه 1.0.2 در Node، py-clob-client نسخه 0.34.6+ در Python) استاندارد فعلی است.

سه تفاوت مشخص. v2 از flagِ negRisk برای marketهای multi-outcome پشتیبانی می‌کند - که از زمان launch شدن NegRisk exchange در اواخر 2024 لازم است. v2 typeهای TypeScript را برای شکل پیام‌های WebSocket همراه دارد؛ v1 مقدار any برمی‌گرداند. v2 جریان امضای Gnosis Safe مربوط به August 2025 را به‌صورت native مدیریت می‌کند؛ v1 به glue code سفارشی برای signing نیاز دارد.

بقیه این فصل با فرض استفاده از v2 نوشته شده است. اگر در یک tutorial قدیمی کد v1 دیدید، آن را تا زمانی که خلافش ثابت نشده خراب فرض کنید - به‌ویژه order placement در marketهای NegRisk تحت v1 به‌صورت silent به contract exchange اشتباه route می‌شود.

Order book REST snapshot

REST snapshot endpoint کل book را برای یک token در یک لحظه برمی‌گرداند.

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

شکل 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"}, ...]
}

قیمت‌ها رشته‌هایی با 2 تا 3 رقم اعشار هستند؛ sizeها رشته‌هایی هستند که تعداد share را نشان می‌دهند (نه دلار). bids از بالا به پایین مرتب شده‌اند، asks از پایین به بالا. hash یک نشانگر deduplication است - polling تکراریِ book بدون تغییر همان hash را برمی‌گرداند و bot شما می‌تواند پردازش را رد کند.

REST snapshot انتخاب درست برای lookupهای یک‌باره است (مثلاً بررسی قیمت هنگام تصمیم ورود). برای monitoring پیوسته، از WebSocket channel زیر استفاده کنید.

WebSocket subscriptionها: market و user channelها

دو WebSocket channel مهم‌اند.

Market channel: wss://ws-subscriptions-clob.polymarket.com/ws/market. به یک یا چند token subscribe کنید؛ order-book updateها را به‌محض وقوع دریافت می‌کنید.

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

پیام‌ها با هر تغییر می‌رسند. typeها شامل book (full snapshot)، price_change (delta)، tick_size_change (نادر)، و last_trade_price (آخرین fill) هستند.

User channel: wss://ws-subscriptions-clob.polymarket.com/ws/user. احراز هویت‌شده است؛ eventهای مربوط به orderهای خودتان را دریافت می‌کنید - fillها، partial fillها، cancellationها.

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

User channel تمیزترین راه برای تشخیص fill است. polling کردن orders REST endpoint هزینه بیشتری دارد و ممکن است state changeها را بین pollingها از دست بدهد؛ WebSocket event را همان لحظه‌ای که matcher آن را تأیید می‌کند push می‌کند.

Parsing bids/asks/depth

Order book فهرستی از price levelها با size تجمیع‌شده است. دو convention برای parsing را باید درست انجام دهید.

جهت order: bids orderهای خرید هستند (یعنی کسی می‌خواهد در این قیمت BUY کند). وقتی bot شما SELL می‌کند، به bid می‌زند. وقتی bot شما BUY می‌کند، ask را lift می‌کند. رابط کاربری پلی‌مارکت هم همین جهت را نشان می‌دهد؛ بعضی exchangeهای دیگر برعکس عمل می‌کنند.

Sorting: bids به‌صورت نزولی می‌رسند (best bid اول). asks به‌صورت صعودی می‌رسند (best ask اول). best bid برابر bids[0] است؛ best ask برابر asks[0]. مراقب باشید: WebSocket عمومی گاهی partial book updateهایی می‌فرستد که از قبل sort نشده‌اند - بعد از هر merge همیشه به‌صورت defensive دوباره sort کنید.

Depth در یک level برابر ارزش دلاری قابل معامله است: price * size. depth پنج level اول یک metric رایج برای liquidity است: sum(b.price * b.size for b in bids[:5]). اگر top-5 depth زیر 100 دلار باشد، book illiquid است و بیشتر فرض‌های strategy از کار می‌افتند.

محاسبه mid-price و best-bid/ask

سه price point مشتق‌شده که bot شما به آن‌ها نیاز دارد.

  • Best bid / best ask: bids[0].price و asks[0].price. قیمتی که واقعاً می‌توانید با آن معامله کنید، برای یک share.
  • Mid-price: (best_bid + best_ask) / 2. مرکز ریاضی spread. برای valuation مفید است؛ شما هیچ‌وقت در mid معامله نمی‌کنید.
  • VWAP price for size N: book را آن‌قدر طی کنید تا cumulative size به N برسد، سپس average price وزن‌دار با size را برگردانید. هزینه واقعی BUY کردن N سهم در همین لحظه، با در نظر گرفتن sweep شدن به levelهای عمیق‌تر.

حالت مرزی: خالی بودن سمت bid یا ask (یعنی کسی نمی‌فروشد یا کسی نمی‌خرد) به این معناست که book یک‌طرفه است. در ساختار market پلی‌مارکت این حالت برای marketهای resolved یا نزدیک به resolved رخ می‌دهد، جایی که یک سمت روی 0.999 است و کسی برای سمت بازنده liquidity ارائه نمی‌کند. best-bid = 0 یا best-ask = 1 را به‌عنوان سیگنال «معامله نکن» در نظر بگیرید.

Maker fee، taker fee، rebate

پلی‌مارکت از مدل maker-taker fee استفاده می‌کند. اعداد تا مه 2026:

  • Taker fee: 0 (صفر) - orderهایی که liquidity موجود book را برمی‌دارند هیچ feeیی نمی‌پردازند. توجه کنید که gas / network cost برای proxy operationها اعمال می‌شود.
  • Maker rebate: مقدار کوچک مثبت، برنامه‌ریزی‌شده، که برای هر rested order پرشده در marketهای واجد شرایط reward program پرداخت می‌شود. همه marketها reward ندارند.
  • NegRisk marketها: همان ساختار fee اما روی یک contract exchange جداگانه؛ rewardها به‌صورت جداگانه انباشته می‌شوند.

صفر بودن taker fee باعث می‌شود پلی‌مارکت به‌طور معناداری با venueهای سنتی CFD متفاوت باشد - بیشتر «هزینه» معامله همان bid-ask spread است، نه یک fee صریح. برای strategyیی که در هر trade spread را رد می‌کند، tax واقعی همان spread است؛ برای bookهای معمولی، round-trip را 1 تا 3 سنت فرض کنید، و برای bookهای illiquid بیشتر.

تعقیب maker rebate فقط زمانی ارزش دارد که marketهای واجد liquidity-reward با ایده‌های strategy شما هم‌راستا شوند. فصل 19 liquidity-rewards farming را به‌عنوان یک رویکرد اختصاصی پوشش می‌دهد.

Code: اتصال WS و پردازش price-change eventها

نمونه Node حداقلی: اتصال، subscribe، و log کردن هر price-change event برای یک 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));

تا حدود 30 token را می‌توانید به‌راحتی در هر WebSocket connection subscribe کنید. فراتر از آن، اتصال‌ها را بین چند connection تقسیم کنید - server گاهی subscriptionهای بزرگ را بدون error رها می‌کند که باعث stale book readهای silent می‌شود.

Reconnect و gap-handling

یک WebSocket connection طولانی‌مدت قطع خواهد شد. Cloudflare هر چند ساعت connectionها را می‌چرخاند؛ networkها flicker می‌کنند؛ پلی‌مارکت هم گاهی deploy می‌کند. برای این وضعیت برنامه داشته باشید.

استراتژی reconnect: در صورت close یا error، با jitter به‌مدت min(2^attempt, 30) ثانیه صبر کنید، سپس دوباره subscribe کنید. شمارنده attempt را پس از اولین پیام موفق بعد از reconnect reset کنید.

gap-handling از سرعت reconnect مهم‌تر است. در زمانی که WebSocket قطع بوده، book تغییر کرده است. در هر reconnect، snapshot REST هر token subscribed را دوباره بگیرید و reconcile کنید: هر position باز که book آن به‌طور معناداری حرکت کرده نیاز به state re-check دارد، exitها ممکن است باید اجرا شوند، alarmها ممکن است stale باشند. حالت «30 ثانیه update book را از دست دادم» قاتل خاموش botهای طولانی‌مدت است - آن‌ها با state قدیمی ادامه می‌دهند و orderها را در قیمت‌هایی می‌گذارند که دیگر وجود ندارند.

الگوی دفاعی: هر book subscribed را صرف‌نظر از وضعیت WebSocket، هر دقیقه یک‌بار snapshot بگیرید و WS را به‌عنوان یک optimization مسیر سریع روی polling snapshot در نظر بگیرید.

پرسش‌های متداول

پلی‌مارکت 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 (snapshotها و WebSocket subscriptionها) عمومی است و هیچ authenticationی نمی‌خواهد. فقط برای ثبت/لغو order و خواندن داده‌های مخصوص account (positionها، fillها) به API key نیاز دارید.
CLOB WebSocket با چه سرعتی price update را push می‌کند؟
به همان سرعتی که orderها match می‌شوند. marketهای فعال هر چند صد میلی‌ثانیه یک‌بار update می‌بینند؛ marketهای کم‌عمق فقط هنگام order واقعی update می‌شوند. هم تغییرات depth و هم eventهای trade از همان WS channel عبور می‌کنند - برای مدیریت درست هر مورد، event type را parse کنید.
چطور mid-price یک پلی‌مارکت order book را محاسبه کنم؟
mid = (best_bid + best_ask) / 2 اگر هر دو وجود داشته باشند؛ در غیر این صورت از last_trade_price به‌عنوان fallback استفاده کنید. در bookهای کم‌عمق که best_bid بسیار پایین‌تر از best_ask است دقت کنید - mid ممکن است بی‌معنا باشد. همیشه قبل از اینکه mid را price منصفانه فرض کنید spread را هم در نظر بگیرید.
Maker fee در پلی‌مارکت در 2026 چقدر است؟
در بیشتر دسته‌ها 0% است. Makerها rebate‌ای معادل 20 تا 25% از taker feeها دریافت می‌کنند. Taker feeها بسته به دسته متفاوت‌اند: 0.75% sports، 1.00% politics، 1.25% economics، 1.80% crypto. همین نابرابری rebate و fee است که باعث می‌شود botهای فعال تقریباً همیشه با limit order quote بدهند نه market order.
چطور WebSocket disconnect را مدیریت کنم؟
با exponential backoff reconnect کنید (1s، 2s، 4s، حداکثر 30s)، دوباره به همان marketها subscribe شوید، و برای پر کردن هر gap یک REST snapshot دوباره بگیرید. هرگز به order book stale اعتماد نکنید - اگر بیش از 5 ثانیه disconnect بوده‌اید، قبل از گذاشتن order یک snapshot تازه درخواست کنید.