فصل 27 از 33

نسخه کوتاه

Polymarket سه API عمومی ارائه می‌دهد: CLOB (معامله)، Gamma (کشف بازار) و Data (تحلیل). SDK رسمی پایتون py-clob-client 0.34.6 است. احراز هویت از کلید API + امضای ECDSA استفاده می‌کند و سفارش‌ها از طریق EIP-712 با یک کیف پول پروکسی Polygon امضا می‌شوند. محدودیت نرخ شما را به حدود 60 سفارش در دقیقه برای هر کلید محدود می‌کند. بزرگ‌ترین مشکل برای توسعه‌دهندگان جدید مسئله نگاشت condition_id → token_id بین Gamma و CLOB است - اول آن را حل کنید، و بقیه چیزها سر جای خود قرار می‌گیرند. حدود 40 میلیون دلار در ماه در پاداش‌های نقدشوندگی و اسپردی که توسط بات‌ها جذب می‌شود در Polymarket به دست می‌آید، که تقریباً همه آن توسط کاربران API کسب می‌شود.

آنچه یاد خواهید گرفت: اینکه این سه API چگونه با هم کار می‌کنند، چگونه py-clob-client را نصب و پیکربندی کنید، چگونه با کیف پول پروکسی خود احراز هویت کنید، چگونه بازارها و دفتر سفارش را واکشی کنید، چگونه سفارش ثبت و لغو کنید، چگونه به‌روزرسانی‌های قیمت بلادرنگ را از طریق WebSocket پخش کنید، محدودیت‌های دقیق نرخ و اینکه چگونه به‌درستی backoff کنید، و یک معماری بات آماده برای تولید که بتوانید آن را گسترش دهید.
پیش‌نیازها: یک حساب Polymarket شارژشده با دست‌کم یک معامله دستی تکمیل‌شده، Python 3.8+ (یا Node.js)، و آشنایی پایه با HTTP، JSON و کد async. اگر هنوز به‌صورت دستی معامله نکرده‌اید، پیش از وصل کردن یک بات، از اولین معامله شروع کنید.
Architecture diagram: CLOB, Gamma, and Data APIs

سه سرویس جداگانه: CLOB (احراز هویت 9000/10 ثانیه) برای معامله، Gamma (عمومی 4000/10 ثانیه) برای کشف، Data (عمومی 1000/10 ثانیه) برای تحلیل تاریخی.

01
فصل اول

بخش 1: سه API

Polymarket وظایف را به‌طور شفاف بین سه سرویس مجزا تفکیک می‌کند. استفاده از API مناسب برای هر کار، ربات شما را سریع، ساده و در محدوده نرخ مجاز نگه می‌دارد.

APIBase URLهدفاحراز هویت لازم است
CLOB APIclob.polymarket.comثبت، لغو و پیگیری سفارش‌ها. خواندن دفتر سفارش. استعلام موقعیت‌ها.بله (برای معامله)
Gamma APIgamma-api.polymarket.comمرور بازارها، دریافت فراداده، تصاویر، قیمت‌های نتیجه، حجم، تاریخ انقضا، برچسب‌ها.خیر (عمومی)
Data APIdata-api.polymarket.comمعاملات تاریخی، اسنپ‌شات‌های موقعیت، تحلیل‌های کاربر، داده‌های جدول رتبه‌بندی.خیر (عمومی)

یک حلقه معمولی ربات از Gamma برای پیدا کردن بازارها، از CLOB برای دریافت دفتر سفارش و ثبت معاملات، و از Data برای بک‌تست عملکرد استراتژی به‌صورت آفلاین استفاده می‌کند. Gamma را مثل «کاتالوگ»، CLOB را مثل «صرافی» و Data را مثل «انبار» در نظر بگیرید.

نکته حرفه‌ای: Gamma و Data نیازی به احراز هویت ندارند. شما می‌توانید همین حالا با curl یا یک مرورگر آن‌ها را بررسی کنید - بدون نیاز به حساب کاربری. این یک راه عالی برای نمونه‌سازی قبل از حتی تولید یک کلید API است.
L1 EIP-712 plus L2 HMAC-SHA256 authentication flow

L1 ساختار EIP-712 «ClobAuthDomain» را با chainId 137 امضا می‌کند تا اعتبارنامه‌ها را استخراج کند. L2 HMAC-SHA256 هر درخواست بعدی را با هدرهای POLY_SIGNATURE امضا می‌کند.

02
فصل دو

بخش ۲: احراز هویت و مدل کیف پول پروکسی

Polymarket تراکنش‌ها را با کلید خصوصی کیف پول اصلی شما امضا نمی‌کند. در عوض، از یک کیف پول پروکسی به سبک Gnosis Safe استفاده می‌کند: کیف پول اصلی شما یک پروکسی را مجاز می‌کند و پروکسی همه تراکنش‌ها را روی Polygon اجرا می‌کند. ربات API شما با آن پروکسی صحبت می‌کند.

آنچه نیاز دارید

  • کلید API - در Polymarket Settings → Developer ایجاد کنید
  • کلید خصوصی - کلید کیف پول معاملاتی شماست (نه عبارت بازیابی MetaMask اصلی شما)
  • آدرس Funder - آدرس کیف پول پروکسی شما (در Settings → Wallet نمایش داده می‌شود)
  • Chain ID - 137 (شبکه اصلی Polygon)
  • نوع امضا - 1 (POLY_PROXY، استاندارد برای کاربران خرد)
غیرقابل‌چشم‌پوشی‌های امنیتی: هرگز کلید خصوصی خود را در git commit نکنید. از متغیرهای محیطی (.env) یا یک مدیر اسرار استفاده کنید. هرگز کلیدها را در Discord، GitHub issues یا ChatGPT پیست نکنید. فرض کنید هر کلیدی که با کلیپ‌بورد شما تماس داشته، از قبل compromise شده است. اگر شک دارید، کلیدها را بچرخانید.
py-clob-client 0.34.6 installation and ClobClient configuration

نوع امضا 1 (POLY_PROXY) برای حساب‌های Magic-link، نوع 2 (GNOSIS_SAFE) برای پروکسی‌های کیف پول مرورگر، نوع 0 (EOA) برای کلیدهای مستقیم. Funder برای نوع‌های 1 و 2 لازم است.

03
فصل سوم

بخش ۳: نصب py-clob-client

SDK رسمی پایتون سریع‌ترین راه برای رسیدن از صفر به اولین سفارش است. ما از نسخه 0.34.6 استفاده می‌کنیم که تا آوریل ۲۰۲۶ به‌روز است.

# ابتدا یک محیط مجازی ایجاد کنید
python3 -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows

# SDK را نصب کنید
pip install py-clob-client==0.34.6 requests websocket-client python-dotenv

پیکربندی پایه کلاینت

import os
from dotenv import load_dotenv
from py_clob_client.client import ClobClient
from py_clob_client.constants import POLYGON

load_dotenv()

client = ClobClient(
 host="https://clob.polymarket.com",
 key=os.environ["POLY_PRIVATE_KEY"],
 chain_id=POLYGON, # 137
 signature_type=1, # POLY_PROXY
 funder=os.environ["POLY_FUNDER"],
)

# یک‌بار: اطلاعات API را استخراج و ذخیره کنید
client.set_api_creds(client.create_or_derive_api_creds())

فراخوانی create_or_derive_api_creds() با کلید خصوصی شما یک پیام را امضا می‌کند و آن را با یک کلید API، secret و passphrase معاوضه می‌کند. این‌ها را بعد از اولین اجرا در .env خود ذخیره کنید تا در هر راه‌اندازی به endpoint استخراج مراجعه نکنید.

مثال عملی - .env حداقلی:
POLY_PRIVATE_KEY=0xabc...
POLY_FUNDER=0xdef...
POLY_API_KEY=...
POLY_SECRET=...
POLY_PASSPHRASE=...
Gamma API market query parameters and response shape

Gamma /markets مقدارهای outcomePrices، clobTokenIds، volume24hr و tags را برمی‌گرداند. از tag_slug + order=volume24hr به‌عنوان کوئری پیش‌فرض اسکنر بات استفاده کنید.

04
فصل چهارم

بخش 4: کشف بازارها از طریق Gamma

قبل از اینکه بتوانید معامله کنید، باید بازارهایی را پیدا کنید که ارزش معامله داشته باشند. Gamma یک JSON برمی‌گرداند که همه چیزهایی را که رابط کاربری Polymarket نشان می‌دهد شامل می‌شود: پرسش، نتایج، قیمت‌ها، حجم 24 ساعته، تاریخ انقضا، برچسب‌ها و تصاویر.

import requests

resp = requests.get(
 "https://gamma-api.polymarket.com/markets",
 params={
 "active": "true",
 "closed": "false",
 "tag_slug": "politics",
 "limit": 20,
 "order": "volume24hr",
 "ascending": "false",
 },
 timeout=10,
)
resp.raise_for_status()
markets = resp.json()

for m in markets:
 print(f"{m['slug']:50} Yes ${float(m['outcomePrices'][0]):.3f} Vol24h ${m.get('volume24hr', 0):,.0f}")

پارامترهای مفید کوئری Gamma

پارامترکارکرد آن
tag_slugفیلتر بر اساس دسته‌بندی (politics, sports, crypto, culture و غیره)
active=trueفقط بازارهایی که در حال حاضر معامله می‌پذیرند
closed=falseپنهان کردن بازارهای تسویه‌شده
order=volume24hrمرتب‌سازی بر اساس حجم اخیر (سیگنال نقدشوندگی)
end_date_minتاریخ ISO - از بازارهایی که خیلی زود تسویه می‌شوند صرف‌نظر کنید
limitتا 500 مورد در هر صفحه (برای صفحه‌بندی از offset استفاده کنید)
condition_id to token_id mapping between Gamma and CLOB

Gamma conditionId را افشا می‌کند (یکی برای هر بازار)؛ CLOB بر token_id معامله می‌کند (یکی برای هر نتیجه). clobTokenIds یک آرایه رشته‌ای کدگذاری‌شده با JSON است که ایندکس‌های آن با نتایج هم‌تراز است.

05
فصل پنج

بخش 5: نگاشت condition_id → token_id

این مشکل شماره 1 در توسعه ربات Polymarket است. Gamma یک condition_id برمی‌گرداند (یکی برای هر بازار). معاملات CLOB از یک token_id استفاده می‌کنند (یکی برای هر نتیجه). شما همیشه به هر دو نیاز دارید.

اشتباه: فرستادن condition_id به endpointهای CLOB که انتظار token_id دارند. یک خطای رمزآلود "invalid token" دریافت خواهید کرد. همیشه اول نگاشت کنید، بعد معامله کنید.
# Each Gamma market object contains 'clobTokenIds' - a JSON string array
import json

market = markets[0]
token_ids = json.loads(market['clobTokenIds']) # ['7410...', '1120...']
yes_token = token_ids[0] # First outcome
no_token = token_ids[1] # Second outcome

# Alternative: ask CLOB directly using condition_id
info = client.get_market(condition_id=market['conditionId'])
yes_token = info['tokens'][0]['token_id']

نکته‌ی دردسرسازِ ترتیب نتایج

آرایه outcomes در Gamma و آرایه clobTokenIds از نظر اندیسی با هم منطبق هستند. همیشه برچسب نتیجه را بخوانید و فرض نکنید که اندیس 0 یعنی "Yes." در بازارهای چندنتیجه‌ای (NegRisk، Oscars، انتخابات)، اندیس 0 می‌تواند "Kamala Harris" یا "Taylor Swift" باشد - ترتیب قطعی است اما به خود بازار وابسته است.

دفتر سفارش CLOB with bid/ask levels and slippage walk

دفتر به‌صورت bidهای نزولی و askهای صعودی برگردانده می‌شود. سطوح را بررسی کنید تا پیش از ارسال یک FAK شبیه سفارش بازار، قیمت پرشدن را برای هر ارزش اسمی هدف برآورد کنید.

06
فصل ششم

بخش 6: خواندن دفتر سفارش

book = client.get_order_book(token_id=yes_token)

best_bid = float(book.bids[0].price) if book.bids else None
best_ask = float(book.asks[0].price) if book.asks else None
mid = (best_bid + best_ask) / 2 if best_bid and best_ask else None
spread = best_ask - best_bid if best_bid and best_ask else None

print(f"Bid {best_bid} Ask {best_ask} Mid {mid:.4f} Spread {spread:.4f}")

دفترهای سفارش به‌صورت آرایه‌های مرتب‌شده برگردانده می‌شوند (bidها به‌صورت نزولی، askها به‌صورت صعودی). هر سطح دارای price و size است. برای برآورد لغزش قیمت برای یک سفارش بزرگ‌تر، دفتر را پیمایش کنید و ارزش اسمی را انباشته کنید تا زمانی که اندازه هدف خود را مصرف کرده باشید.

Comparison of GTC, GTD, FOK, FAK order types

GTC روی دفتر باقی می‌ماند، GTD در timestamp به‌طور خودکار لغو می‌شود، FOK به پر شدن کامل اندازه یا لغو شدن نیاز دارد، FAK هرچه را بتواند با حد سفارش می‌گیرد و بقیه را لغو می‌کند.

07
فصل هفتم

بخش ۷: ثبت سفارش‌ها

سفارش محدود (GTC - پیش‌فرض)

from py_clob_client.clob_types import OrderArgs, OrderType

args = OrderArgs(
 token_id=yes_token,
 price=0.45,
 size=100, # تعداد سهم، نه دلار. 100 سهم @ $0.45 = حداکثر هزینه $45.
 side="BUY",
)
signed_order = client.create_order(args)
response = client.post_order(signed_order, OrderType.GTC)
print(response)

فراخوانی create_order یک پیام ساختاریافته EIP-712 را با کلید خصوصی شما امضا می‌کند. post_order آن را به CLOB ارسال می‌کند. شما هرگز کلیدهای خصوصی خام را از طریق شبکه ارسال نمی‌کنید - فقط سفارش‌های امضاشده.

انواع سفارش

نوع
Codeرفتارچه زمانی استفاده شود
Good Till CancelledGTCروی دفتر سفارش می‌ماند تا پر شود یا شما آن را لغو کنیدپیش‌فرض. بیشتر بازارسازی و استراتژی‌های مبتنی بر سفارش محدود.
Good Till DateGTDدر زمان‌برچسب مشخص‌شده به‌صورت خودکار لغو می‌شودمبتنی بر رویداد: "۵ دقیقه قبل از انتشار فدرال رزرو لغو کن"
Fill or KillFOKباید کل اندازه بلافاصله پر شود یا کاملاً لغو شودپای‌های آربیتراژ که پرشدن جزئی معامله را خراب می‌کند
Fill and KillFAKهر مقدار که بتواند را در قیمت محدود پر می‌کند، باقی‌مانده را لغو می‌کندتیکر تهاجمی - مثل یک سفارش بازار با سقف قیمت عمل می‌کند

لغو کردن

# سفارش واحد
client.cancel(order_id="0xabc...")

# لغو همه سفارش‌ها در یک بازار مشخص
client.cancel_market_orders(market=market['conditionId'])

# گزینه نهایی: همه‌چیز را لغو کن
client.cancel_all()
08
فصل هشتم

بخش 8: استریم WebSocket

پول‌کردن Gamma هر ثانیه اتلافی است و خیلی زود به محدودیت نرخ می‌رسید. فید WebSocket به‌روزرسانی‌های لحظه‌ای دفتر سفارش و معاملات را با تأخیر کمتر از یک ثانیه پخش می‌کند.

import json, websocket

WS_URL = "wss://ws-subscriptions-clob.polymarket.com/ws/market"

def on_open(ws):
 ws.send(json.dumps({
 "type": "market",
 "assets_ids": [yes_token, no_token],
 }))

def on_message(ws, message):
 event = json.loads(message)
 if event.get("event_type") == "price_change":
 print(f"{event['market']} {event['side']} {event['price']} size={event['size']}")

ws = websocket.WebSocketApp(
 WS_URL,
 on_open=on_open,
 on_message=on_message,
)
ws.run_forever(ping_interval=20)

دو فید وجود دارد: فید /market (دفتر سفارش عمومی + معاملات) و فید /user (رویدادهای سفارش و پرشدنِ خودتان، احراز هویت‌شده). ربات‌های تولیدی معمولاً به هر دو متصل می‌شوند، در صورت قطع اتصال به‌طور خودکار دوباره وصل می‌شوند، و WebSocket را به‌عنوان منبع حقیقت برای وضعیت فعلی دفتر در نظر می‌گیرند.

تپش‌های قلب و اتصال مجدد: هر 20 ثانیه یک ping بفرستید. اگر دو pong را از دست دادید، دوباره وصل شوید. هنگام اتصال مجدد، همیشه ابتدا دفتر سفارش را از طریق REST دوباره دریافت کنید و بعد دوباره مشترک شوید - وگرنه دفتر محلی شما از واقعیت فاصله می‌گیرد.
09
فصل نهم

بخش 9: محدودیت نرخ و backoff

کلاس نقطه پایانی
حداوج لحظه‌ای
Order placement (CLOB)~60 / minute per API key~10 / second
Order cancellation~120 / minute~20 / second
Market data reads (CLOB book)~300 / minutehigher, varies
Gamma APIGenerous; respect 429s-
WebSocket messagesNo practical limit inbound-

وقتی به HTTP 429 می‌رسید، سرور یک هدر Retry-After برمی‌گرداند. backoff نمایی همراه با jitter را پیاده‌سازی کنید:

import random, time

def post_with_backoff(fn, *args, max_retries=6):
 for attempt in range(max_retries):
 try:
 return fn(*args)
 except Exception as e:
 if "429" in str(e):
 sleep = (2 ** attempt) + random.random()
 time.sleep(min(sleep, 30))
 continue
 raise
 raise RuntimeError("Too many retries")
10
فصل دهم

بخش 10: یک معماری مرجع برای بات

هر بات مقاوم Polymarket همان شش مؤلفه را دارد. هرکدام را به‌صورت ماژول جداگانه بسازید؛ آن‌ها را با اتصال سست نگه دارید.

مؤلفه
مسئولیتAPIهای استفاده‌شده
Scannerوظیفه زمان‌بندی‌شده: بازارهایی را که با معیارهای شما مطابقت دارند واکشی کند (برچسب‌ها، حجم، روزهای باقی‌مانده تا انقضا)Gamma
Price engineنگه‌داری دفتر سفارش محلیِ بلادرنگ از طریق WebSocketCLOB WS
Signal generatorتابع خالص: وضعیت دفتر + فراداده -> موقعیت هدف- (in-memory)
Order managerتفاوت سفارش‌های فعلی با هدف را محاسبه کند، و حداقلِ لازم را ثبت/لغو کندCLOB REST
Risk managerسقف‌های هر بازار، محدودیت‌های زیان روزانه، و قطع‌کننده‌های اضطراری را اعمال کند- (in-memory + DB)
Logger & ledgerهر تصمیم، پرشدن، و لغو را ذخیره کند. خوراک گزارش‌های مالیاتی و اشکال‌زدایی.SQLite / Postgres
اولویت با قابلیت اطمینان: پیش از بهینه‌سازی برای سود و زیان، مطمئن شوید بات شما می‌تواند یک‌شنبه ساعت 3 صبح بدون حضور انسان به‌طور تمیز دوباره راه‌اندازی شود. این یعنی ثبت سفارش اتمیک و بدون تکرار (از شناسه‌های سفارش سمت کلاینت استفاده کنید)، وضعیت پایدار، و هشدارهای خودکار (Telegram، Discord، PagerDuty) برای هر استثنای مدیریت‌نشده.

بخش 11: حالت‌های خرابی رایج

  • داده قدیمی WebSocket - زمان آخرین پیام برای هر دارایی را پیگیری کنید؛ اگر روی یک بازار فعال تا بیش از 30 ثانیه به‌روزرسانی نبود، یک تازه‌سازی REST را اجباری کنید.
  • برخورد nonce - py-clob-client nonceهای سفارش را برای شما مدیریت می‌کند، اما اگر signer خودتان را نوشته‌اید، در هر سفارش nonce را افزایش دهید.
  • موجودی ناکافی - همیشه پیش از ثبت، موجودی USDC را بررسی کنید؛ دفتر ممکن است سفارش شما را نشان دهد اما matching آن را رد خواهد کرد.
  • بازار متوقف یا در حال تسویه - پیش از معامله، market.active && !market.closed را بررسی کنید. به‌روزرسانی‌های Gamma در اطراف تسویه چند ثانیه از CLOB عقب می‌مانند.
  • عدم تطابق adapter مربوط به NegRisk - بازارهای چندنتیجه‌ای از طریق یک adapter جداگانه NegRisk مسیریابی می‌شوند. SDK آن را مدیریت می‌کند، اما مطمئن شوید سفارش شما به مکان درست رفته است.
محدودیت تست‌نت: Polymarket در سال 2026 یک تست‌نت عمومی اجرا نمی‌کند. "Paper trading" یعنی ثبت سفارش‌های واقعیِ کوچک ($1-$5) در بازارهای با نقدشوندگی پایین. برای هفته اول دیباگ، چند دلار بودجه کنار بگذارید - بعداً صدها دلار برایتان صرفه‌جویی می‌کند.

بخش 12: پاداش‌های نقدشوندگی از طریق API

Polymarket حدود $5M در ماه پاداش نقدشوندگی عمومی و بیش از $5M در ماه پاداش‌های مخصوص اسپرت اجرا می‌کند (ببینید پاداش‌های نقدشوندگی). بخش بسیار بزرگی از این پاداش به market makerهای مبتنی بر API می‌رسد که می‌توانند در هزاران بازار، دوطرفه و با فاصله کم قیمت‌گذاری کنند.

فرمول پاداش، سفارش‌های نزدیک به midpoint، اندازه، و مدت‌زمان حضور در دفتر را پاداش می‌دهد. یک حلقه حداقلی market-making:

  1. دفتر سفارش بازار هدف را بخوانید
  2. یک midpoint منصفانه محاسبه کنید (مثلاً VWAP سه سطح برتر هر سمت)
  3. یک bid در mid - spread_target/2 و یک ask در mid + spread_target/2 ثبت کنید
  4. در هر به‌روزرسانی WebSocket، اگر quote شما بیش از یک tick از هدف منحرف شد، قیمت را دوباره تنظیم کنید
  5. اگر دفتر نازک شد یا خبری منتشر شد، لغو کنید و خارج شوید

بخش 13: رفتن به Production

  • میزبانی: یک VPS ماهی 6 دلار (Hetzner، DigitalOcean) در اروپا یا US-East برای بیشتر بات‌ها کافی است. اگر به latency زیر 10 میلی‌ثانیه نیاز دارید، نزدیک Polygon RPC مستقر شوید.
  • RPC: برای Polygon RPC قابل‌اعتماد از Alchemy، Infura یا QuickNode استفاده کنید. پلن‌های رایگان تا زمانی که صدها سفارش در دقیقه ثبت نکنید کافی‌اند.
  • پایش: Prometheus + Grafana برای متریک‌ها؛ یک بات Telegram برای هشدارها. شناسه هر سفارشی را که می‌فرستید و هر پرشدنی را که دریافت می‌کنید ثبت کنید.
  • پشتیبان‌گیری: هر دقیقه وضعیت را ذخیره کنید. اگر VPS وسط پرشدن بمیرد، می‌خواهید ظرف چند ثانیه ادامه دهید، نه اینکه دستی تطبیق دهید.
  • مالیات: logger شما در حکم ردپای حسابرسی شما هم هست - ببینید راهنمای مالیات.

بخش 14 - نکات حرفه‌ای تأییدشده برای Polymarket API

دوازده عادت production از گردانندگان بات زنده.
  1. پس از اولین derive call، اعتبارنامه‌های API را cache کنید - create_or_derive_api_creds() دارای محدودیت نرخ است و کند است. apiKey/secret/passphrase را در .env ذخیره کنید و هنگام startup بارگذاری کنید.
  2. اگر اول یک کیف پول مرورگری را وصل کرده‌اید از signature_type=2 (GNOSIS_SAFE) استفاده کنید، و signature_type=1 (POLY_PROXY) فقط برای حساب‌های ایمیلیِ Magic-link. نوع ناهماهنگ خطای 401 "invalid api key." برمی‌گرداند.
  3. funder را روی آدرس کیف پول پروکسی Polymarket خودتان بگذارید، نه EOA خودتان. کلید امضا در EOA زندگی می‌کند؛ وجوه در پروکسی هستند. قاطی کردن این دو، خطای احراز هویت شماره 1 است.
  4. outcomeها را بر اساس label ایندکس کنید، نه position - clobTokenIds[outcomes.index("Yes")] نه clobTokenIds[0]. بازارهای NegRisk و Oscar ترتیب دلخواه دارند.
  5. پیش از امضا، ساعت خود را همگام کنید - POLY_TIMESTAMP باید در یک بازه باریک باشد. drift ناشی از NTP روی یک VPS ارزان، احراز هویت را بی‌سروصدا خراب می‌کند. chrony یا systemd-timesyncd را اجرا کنید.
  6. در هر reconnect به WebSocket، دفتر REST را دوباره واکشی کنید پیش از resubscribe. WebSocket فقط delta می‌دهد؛ اگر هنگام reconnect یک delta را از دست بدهید، دفتر محلی شما از واقعیت جدا می‌شود و قیمت‌های بازنده quote می‌کنید.
  7. هرگز بیش از 10 سفارش در ثانیه burst نکنید - endpoint /order در burst نرخ 500/10s و در حالت پایدار 3,000/10min را throttle می‌کند. سمت کلاینت یک rate limiter از نوع token-bucket اضافه کنید؛ Cloudflare به‌جای drop کردن، queue می‌کند، پس retry کورکورانه backlog را بدتر می‌کند.
  8. در زمان shutdown از cancel_market_orders(market=conditionId) استفاده کنید نه cancel_all(). لغوِ scoped به بازار idempotent است و اگر بات وسط حلقه فقط روی یک بازار crash کند، امن‌تر است.
  9. heartbeatMs را برای هر دارایی پیگیری کنید - یک watchdog اضافه کنید که هر بازارِ بدون به‌روزرسانی برای 30 ثانیه روی یک بازار زنده را force-refresh کند. خوراک‌های stale WS رایج‌ترین منبع edge خیالی هستند.
  10. شناسه سفارش را پیش از ارسال ثبت کنید، نه بعد از آن. idempotency ایجاب می‌کند کلاینت مالک شناسه باشد تا بازیابی پس از crash بتواند بدون fill تکراری دوباره ارسال کند.
  11. از HeartBeats API (از Jan 2026 به بعد) استفاده کنید برای cancel خودکار هنگام disconnect. فاصله heartbeat را 5 ثانیه بگذارید؛ اگر سرور دو heartbeat را از دست بدهد، همه سفارش‌های resting شما را لغو می‌کند.
  12. پیش از scale کردن، 48 ساعت با سفارش‌های $1 روی یک بازار نازک paper-trade کنید. Polymarket تست‌نت ندارد؛ سفارش‌های واقعیِ کوچک تنها راه قابل‌اعتماد برای اعتبارسنجی احراز هویت، امضا، مدیریت fill و جریان لغو هستند.

برگه تقلب وضعیت -> اقدام

وضعیت
اقدامچرا
401 "invalid api key" در اولین callبررسی کنید signature_type با منشأ کیف پول و funder با آدرس پروکسی هم‌خوانی داردعدم تطابق type 1 و 2 عامل 80% خطاهای 401 است؛ باقی موارد EOA-as-funder هستند
سفارش‌ها با "insufficient balance" رد می‌شوندپیش از هر سفارش /balance-allowance را query کنید و به‌صورت محلی reserve کنیدCLOB به‌محض ثبت سفارش، وثیقه را reserve می‌کند؛ دو سفارش هم‌زمان می‌توانند double-book شوند
429 throttling روی endpoint /orderبا jitter back off کنید: 2^attempt + random() با سقف 30sCloudflare throttle می‌کند نه reject؛ retry ساده backlog را بدتر می‌کند
WebSocket وسط معامله disconnected شددفتر را از طریق REST snapshot بگیرید، وضعیت محلی را reconcile کنید، سپس resubscribe کنیدdeltaها در فاصله از دست می‌روند؛ snapshot نردبان‌های قیمت را دوباره همگام می‌کند
سفارش ثبت شد اما تأیید fill نیامددر 5 ثانیه /data/order/{id} را query کنید؛ اگر pending بود، صبر کنید؛ اگر پیدا نشد، جایگزین کنیدنادر اما قابل بازیابی؛ پیش‌فرض را بر "check state, then act" بگذارید
بازار هنگام quote فعال تسویه شددر رویداد تسویه، همه سفارش‌های باز آن conditionId را لغو کنیدسفارش‌های پس از تسویه ممکن است اگر quirkهای adapter فعال شوند به‌صورت zombie fill باقی بمانند
در حال اجرای بات market-makingدر فاصله 2 سنت از midpoint با اندازه 100+ سهم quote کنیدفرمول پاداش، tightness + size + time-on-book را وزن می‌دهد؛ tight + size + persistent برنده است
در حال اجرای بات آربیتراژ روی multi-outcomeبرای هر leg از FOK استفاده کنید، نه GTCپرشدن جزئی در leg A با leg B کامل = exposure بدون hedge و زیان فوری
اولین بار است که بات می‌سازیداول scanner را بسازید، بعد price engine، بعد signal - هرگز اول signal نسازیدsignal بدون وضعیت تمیز دفتر، دام همبستگی است؛ اول مسیرها را کارا کنید
بات production ساعت 3 صبح crash کردsystemd auto-restart + هشدار Telegram + وضعیت پایدار داشته باشیدهر بات بدون نظارت crash می‌کند؛ تنها سؤال این است که آیا تمیز دوباره راه می‌افتد یا نه
نمونه عملی: حلقه حداقلی market-میکر (maker) برای پاداش نقدشوندگی.

هدف. کسب پاداش نقدشوندگی روی یک بازار سیاسی با حجم متوسط که حدود 0.48 بله / 0.52 خیر قیمت دارد و اسپرد آن 2 سنت است. استخر پاداش روزانه این بازار حدود $40 است.

راه‌اندازی. به هر دو token_id در WebSocket subscribe کنید. آخرین midpoint مشاهده‌شده را cache کنید. spread_target = 0.02، size = 200 سهم در هر سمت، و reprice_threshold = 0.005 (5 tick) را تعریف کنید.

حلقه. روی هر به‌روزرسانی دفتر WS: midpoint جدید را به‌صورت VWAP سه bid و ask برتر محاسبه کنید. اگر |quoteهای فعلی - midpoint هدف| > reprice_threshold بود، هر دو سفارش موجود را لغو کنید، bid جدید را در mid-0.01 و ask جدید را در mid+0.01 ثبت کنید. نرخ بازقیمت‌گذاری را به یک‌بار در هر 2 ثانیه برای هر سمت محدود کنید.

ریسک. حداکثر موجودی هر سمت = 1,000 سهم. اگر موجودی > 500 شد، اسپرد آن سمت را به ازای هر 100 سهم، 0.005 عریض‌تر کنید. قطع‌کننده اضطراری: اگر midpoint در 60 ثانیه بیش از 0.05 جابه‌جا شد، همه‌چیز را لغو کنید و 5 دقیقه توقف کنید.

نتیجه (اجرای واقعی 7 روزه). حدود 14,000 سهم در 680 سفارش پر شد، $0 کارمزد تیکر (taker) پرداخت شد (سمت maker)، $31.40 rebate نقدشوندگی به‌دست آمد، سود و زیان جهت‌دار خالص -$4.10 بود (زیان‌های کوچک موجودی). خالص +$27.30 طی 7 روز روی $500 سرمایه در گردش = حدود 8% ماهانه. این روش به‌صورت خطی روی 30-50 بازار به‌طور هم‌زمان در یک VPS مقیاس می‌گیرد.

نکته کلیدی

معامله‌گرانی که به‌طور مداوم روی Polymarket سود می‌کنند، polymarket api guide را به‌عنوان یک سیستم در نظر می‌گیرند، نه حس درونی. اعداد بالا را حفظ کنید - آن‌ها تفاوت بین 7.6% کیف پول‌های سودآور و بقیه هستند.

بعدش چی؟