Розділ 27 з 33
Коротка версія
Polymarket надає доступ до трьох публічних API: CLOB (торгівля), Gamma (пошук ринків) і Data (аналітика). Офіційний Python SDK - py-clob-client 0.34.6. Автентифікація використовує API key + ECDSA signature, а заявки підписуються через EIP-712 за допомогою проксі-гаманця Polygon. Обмеження швидкості встановлюють ліміт приблизно 60 заявок/хвилину на ключ. Найбільша пастка для нових розробників - проблема зіставлення condition_id → token_id між Gamma і CLOB - розв'яжіть її першою, і все інше стане на свої місця. Приблизно $40M/місяць у винагородах за ліквідність і спреді, захопленому ботами, заробляється на Polymarket, майже повністю користувачами API.

Три окремі сервіси: CLOB (9,000/10s auth) для торгівлі, Gamma (4,000/10s public) для пошуку, Data (1,000/10s public) для історичної аналітики.
Частина 1: Три API
Polymarket чітко розділяє функції між трьома окремими сервісами. Використання правильного API для кожного завдання робить ваш бота швидким, простим і в межах лімітів запитів.
| API | Базова URL-адреса | Призначення | Потрібна автентифікація |
|---|---|---|---|
| CLOB API | clob.polymarket.com | Розміщуйте, скасовуйте та відстежуйте заявки. Читайте книги заявок. Запитуйте позиції. | Так (для торгівлі) |
| Gamma API | gamma-api.polymarket.com | Переглядайте ринки, отримуйте метадані, зображення, ціни результатів, обсяг, термін дії, теги. | Ні (публічний) |
| Data API | data-api.polymarket.com | Історичні угоди, знімки позицій, аналітика користувачів, дані таблиці лідерів. | Ні (публічний) |
Типовий цикл бота використовує Gamma для пошуку ринків, CLOB для отримання книг заявок і розміщення угод, а Data - для офлайн-бектесту продуктивності стратегії. Уявляйте Gamma як "каталог", CLOB як "біржу", а Data як "сховище".
curl або браузера прямо зараз - обліковий запис не потрібен. Це чудовий спосіб створити прототип ще до того, як ви згенеруєте API-ключ.
L1 підписує структуру "ClobAuthDomain" EIP-712 з chainId 137, щоб отримати облікові дані. L2 HMAC-SHA256 підписує кожен наступний запит заголовками POLY_SIGNATURE.
Частина 2: Аутентифікація та модель проксі-гаманця
Polymarket не підписує угоди приватним ключем вашого основного гаманця. Натомість він використовує проксі-гаманець у стилі Gnosis Safe: ваш основний гаманець авторизує проксі, а проксі виконує всі угоди на Polygon. Ваш API-бот взаємодіє з цим проксі.
Що вам потрібно
- API key - згенеруйте в Polymarket Settings → Developer
- Private key - ключ вашого trading wallet (НЕ ваша головна seed-фраза MetaMask)
- Funder address - адреса вашого проксі-гаманця (показано в Settings → Wallet)
- Chain ID -
137(Polygon mainnet) - Signature type -
1(POLY_PROXY, standard for retail users)
.env) або менеджер секретів. Ніколи не вставляйте ключі в Discord, GitHub issues або ChatGPT. Вважайте, що будь-який ключ, який потрапив у ваш буфер обміну, уже скомпрометований. Якщо є сумніви, змініть ключі.
Тип підпису 1 (POLY_PROXY) для акаунтів Magic-link, тип 2 (GNOSIS_SAFE) для проксі браузерних гаманців, тип 0 (EOA) для прямих ключів. Funder потрібен для типів 1 і 2.
Частина 3: Встановлення py-clob-client
Офіційний Python SDK - це найшвидший шлях від нуля до першої заявки. Ми використаємо версію 0.34.6, яка є актуальною станом на квітень 2026 року.
# Спочатку створіть віртуальне середовище
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 key, secret та passphrase. Після першого запуску збережіть їх у вашому .env, щоб не звертатися до derive endpoint під час кожного старту.
POLY_PRIVATE_KEY=0xabc...
POLY_FUNDER=0xdef...
POLY_API_KEY=...
POLY_SECRET=...
POLY_PASSPHRASE=...
Gamma /markets повертає outcomePrices, clobTokenIds, volume24hr, tags. Використовуйте tag_slug + order=volume24hr як стандартний запит сканера бота.
Частина 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 | Фільтр за категорією (політика, спорт, крипто, культура тощо) |
active=true | Лише ринки, які зараз приймають угоди |
closed=false | Приховати врегульовані ринки |
order=volume24hr | Сортувати за нещодавнім обсягом (сигнал ліквідності) |
end_date_min | Дата ISO - пропускати ринки, що врегульовуються надто скоро |
limit | До 500 на сторінку (використовуйте offset для пагінації) |

Gamma надає conditionId (по одному на ринок); CLOB торгує на token_id (по одному на кожен результат). clobTokenIds - це JSON-encoded масив рядків, індекси якого відповідають результатам.
Частина 5: Відображення condition_id → token_id
Це проблема №1 у розробці ботів для Polymarket. Gamma повертає condition_id (по одному на ринок). Угоди в CLOB використовують token_id (по одному на кожен результат). Вам завжди потрібні обидва.
condition_id в ендпоінти CLOB, які очікують token_id. Ви отримаєте загадкову помилку "invalid token". Спочатку завжди зіставляйте, потім торгуйте.# Кожен об'єкт ринку Gamma містить 'clobTokenIds' - масив JSON-рядків
import json
market = markets[0]
token_ids = json.loads(market['clobTokenIds']) # ['7410...', '1120...']
yes_token = token_ids[0] # Перший результат
no_token = token_ids[1] # Другий результат
# Альтернатива: запитати CLOB напряму за допомогою 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" - порядок детермінований, але залежить від конкретного ринку.

Книга повертається як bids у порядку спадання, asks - у порядку зростання. Пройдіть рівні, щоб оцінити ціну виконання для будь-якого цільового номіналу перед надсиланням market-like FAK.
Частина 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}")Книги заявок повертаються як відсортовані масиви (bids за спаданням, asks за зростанням). Кожен рівень має price і size. Щоб оцінити прослизання для більшого ордера, проходьтеся по книзі та накопичуйте номінал, доки не буде виконано ваш цільовий розмір.

GTC залишається в книзі, GTD автоматично скасовується у timestamp, FOK вимагає повного виконання на весь розмір або скасування, FAK бере все, що може, за лімітом і скасовує решту.
Частина 7: Розміщення заявок
Лімітна заявка (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. Ви ніколи не надсилаєте необроблені приватні ключі через мережу - лише підписані заявки.
Типи заявок
| Тип | Код | Поведінка | Коли використовувати |
|---|---|---|---|
| Дійсна до скасування | GTC | Залишається в книзі заявок, доки не буде виконана або ви її не скасуєте | За замовчуванням. Більшість стратегій маркет-мейкінгу та лімітних стратегій. |
| Дійсна до дати | GTD | Автоматично скасовується у вказаний момент часу | Подієво-орієнтовано: "скасувати за 5 хв до оголошення ФРС" |
| Виконати або скасувати | FOK | Потрібно негайно виконати весь обсяг або повністю скасувати | Арбітражні ноги, де часткове виконання псує угоду |
| Виконати і скасувати | FAK | Виконує все, що може, за лімітною ціною, решту скасовує | Агресивний тейкінг - поводиться як ринкова заявка з обмеженням ціни |
Скасування
# Одна заявка
client.cancel(order_id="0xabc...")
# Скасувати всі заявки на конкретному ринку
client.cancel_market_orders(market=market['conditionId'])
# Ядерний варіант: скасувати все
client.cancel_all()Частина 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 джерелом істини для поточного стану книги.
Частина 9: Ліміти запитів і backoff
| Клас endpoint | Ліміт | Сплеск |
|---|---|---|
| Розміщення заявок (CLOB) | ~60 / хвилину на API key | ~10 / секунду |
| Скасування заявок | ~120 / хвилину | ~20 / секунду |
| Читання ринкових даних (книга CLOB) | ~300 / хвилину | вищий, варіюється |
| Gamma API | Щедрий; дотримуйтеся 429 | - |
| Повідомлення WebSocket | Практичного ліміту на вхід немає | - |
Коли ви отримуєте 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: Еталонна архітектура бота
Кожен надійний бот Polymarket має ті самі шість компонентів. Створіть кожен як окремий модуль; тримайте їх слабко зв'язаними.
| Компонент | Відповідальність | Використовувані API |
|---|---|---|
| Сканер | Заплановане завдання: отримувати ринки, що відповідають вашим критеріям (теги, обсяг, дні до закінчення) | Gamma |
| Ціновий рушій | Підтримувати локальні книги заявок у реальному часі через WebSocket | CLOB WS |
| Генератор сигналів | Чиста функція: стан книги + метадані -> цільова позиція | - (in-memory) |
| Менеджер ордерів | Порівнювати поточні ордери з цільовими, мінімально виставляти/скасовувати | CLOB REST |
| Менеджер ризиків | Застосовувати ліміти на кожен ринок, денні ліміти збитків, автоматичні вимикачі | - (in-memory + DB) |
| Журналювання та ledger | Зберігати кожне рішення, виконання, скасування. Служить для податкових звітів і налагодження. | SQLite / Postgres |
Частина 11: Поширені режими відмов
- Застарілі дані WebSocket - відстежуйте час останнього повідомлення для кожного активу; якщо для активного ринку немає оновлень понад 30 с, примусово оновіть через REST.
- Конфлікти nonce - py-clob-client обробляє order nonce за вас, але якщо ви пишете власний signer, збільшуйте nonce на кожен ордер.
- Недостатній баланс - завжди перевіряйте баланс USDC перед виставленням; книга може показувати ваш ордер, але matching його відхилить.
- Ринок призупинено або завершується - перевіряйте
market.active && !market.closedперед торгівлею. Оновлення Gamma відстають від CLOB на кілька секунд під час завершення. - Невідповідність адаптера NegRisk - ринки з кількома результатами маршрутизуються через окремий адаптер NegRisk. SDK це обробляє, але підтвердьте, що ваш ордер потрапив у правильний venue.
Частина 12: Винагороди за ліквідність через API
Polymarket виплачує ~$5M/місяць у загальних винагородах за ліквідність плюс $5M+/місяць у винагородах для спортивних ринків (див. Винагороди за ліквідність). Переважна більшість іде API-орієнтованим маркетмейкерам, які можуть підтримувати вузькі двосторонні котирування на тисячах ринків.
Формула винагороди заохочує ордери поблизу середньої точки, розмір і час перебування в книзі. Мінімальний цикл маркетмейкінгу:
- Зчитати книгу заявок для цільового ринку
- Обчислити справедливу середню точку (наприклад, VWAP топ-3 рівнів з кожного боку)
- Поставити bid на
mid - spread_target/2і ask наmid + spread_target/2 - На кожному оновленні WebSocket переновлювати ціну, якщо ваша котирування відхилилася від цілі більш ніж на tick
- Скасувати й вийти, якщо книга розріджується або з'являються новини
Частина 13: Перехід у production
- Хостинг: VPS за $6/місяць (Hetzner, DigitalOcean) у Європі або US-East достатньо для більшості ботів. Розміщуйте поруч із Polygon RPC, якщо вам потрібна затримка менше 10 мс.
- RPC: використовуйте Alchemy, Infura або QuickNode для надійного Polygon RPC. Безкоштовних тарифів достатньо, доки ви не почнете виставляти сотні ордерів на хвилину.
- Моніторинг: Prometheus + Grafana для метрик; бот Telegram для сповіщень. Логуйте кожен order ID, який ви надсилаєте, і кожне виконання, яке отримуєте.
- Резервні копії: зберігайте стан щохвилини. Якщо VPS помре посеред виконання, ви захочете відновитися за секунди, а не звіряти вручну.
- Податки: ваш logger також є вашим audit trail - див. Податковий гайд.
Частина 14 - Перевірені поради для Polymarket API
- Кешуйте API-облікові дані після першого derive call -
create_or_derive_api_creds()має rate limit і працює повільно. Зберігайте apiKey/secret/passphrase у.envі завантажуйте під час запуску. - Використовуйте signature_type=2 (GNOSIS_SAFE), якщо спочатку підключили браузерний гаманець, signature_type=1 (POLY_PROXY) лише для email-акаунтів Magic-link. Невідповідний тип повертає 401 "invalid api key."
- Встановлюйте
funderна адресу вашого проксі-гаманця Polymarket, а не ваш EOA. Ключ підпису живе в EOA; кошти живуть у проксі. Плутанина між ними - помилка автентифікації №1. - Індексувати результати за міткою, ніколи не за позицією -
clobTokenIds[outcomes.index("Yes")], а неclobTokenIds[0]. Ринки NegRisk та Oscar мають довільний порядок. - Синхронізуйте годинник перед підписанням - POLY_TIMESTAMP має бути в межах вузького вікна. Дрейф NTP на дешевому VPS ламає автентифікацію без явних помилок. Запустіть chrony або systemd-timesyncd.
- Повторно отримуйте REST book при кожному reconnect WebSocket перед повторним підписанням. WebSocket дає delta; якщо ви пропустите delta під час reconnect, ваша локальна книга роз'їдеться з реальністю і ви котируватимете збиткові ціни.
- Ніколи не перевищуйте 10 ордерів на секунду - endpoint /order обмежує burst до 500/10 с і 3,000/10 хв у сталому режимі. Додайте token-bucket rate limiter на клієнтській стороні; Cloudflare ставить у чергу, а не відкидає, тож сліпі повтори посилюють backlog.
- Використовуйте
cancel_market_orders(market=conditionId)під час завершення роботи, а неcancel_all(). Скасування на рівні ринку є ідемпотентним і безпечнішим, якщо бот падає посеред циклу лише на одному ринку. - Відстежуйте
heartbeatMsдля кожного активу - додайте watchdog, який примусово оновлює будь-який ринок без оновлень 30 с на живому ринку. Застарілі WS-потоки - найпоширеніше джерело фантомної переваги. - Логуйте order ID перед надсиланням, а не після. Ідемпотентність вимагає, щоб клієнт володів ID, тоді recovery після збою може надіслати повторно без дублювання виконань.
- Використовуйте HeartBeats API (Jan 2026+) для автоматичного cancel-on-disconnect. Встановіть інтервал heartbeat на 5 с; сервер скасує всі ваші resting orders, якщо пропустить два heartbeat.
- Paper-trade з ордерами на $1 на тонкому ринку протягом 48 годин перед масштабуванням. У Polymarket немає testnet; крихітні реальні ордери - єдиний надійний спосіб перевірити автентифікацію, підписання, обробку виконань і потік скасувань.
Шпаргалка: ситуація -> дія
| Ситуація | Дія | Чому |
|---|---|---|
| 401 "invalid api key" під час першого виклику | Перевірте, що signature_type відповідає походженню гаманця, а funder є адресою проксі | Невідповідність Type 1 vs 2 спричиняє 80% помилок 401; решта - це EOA-as-funder |
| Ордери відхилено з "insufficient balance" | Запитуйте /balance-allowance перед кожним ордером і резервуйте локально | CLOB резервує заставу в момент публікації; два одночасні ордери можуть подвійно забронювати кошти |
| 429 throttling на endpoint /order | Відступайте з jitter: 2^attempt + random(), обмежено 30 с | Cloudflare уповільнює, а не відхиляє; наївні повтори посилюють backlog |
| WebSocket відключився посеред торгівлі | Зніміть snapshot книги через REST, звірте локальний стан, потім повторно підпишіться | Delta під час проміжку втрачаються; snapshot повторно синхронізує цінові сходинки |
| Ордер виставлено, але немає підтвердження виконання | Запитайте /data/order/{id} протягом 5 с; якщо pending, зачекайте; якщо не знайдено, замініть | Рідко, але відновлювано; за замовчуванням дійте за схемою "перевір стан, потім дій" |
| Ринок завершився під час активної котирування | Скасуйте всі відкриті ордери на цей conditionId під час події завершення | Після завершення ордери можуть лишатися як zombie fills, якщо спрацюють особливості адаптера |
| Запуск маркетмейкингового бота | Котируйте в межах 2 центів від середньої точки з розміром 100+ shares | Формула винагороди зважує вузькість + розмір + час у книзі; вузько + великий розмір + постійність перемагають |
| Запуск арбітражного бота на ринку з кількома результатами | Використовуйте FOK для кожної ноги, а не GTC | Часткові виконання на нозі A при повній нозі B = не захеджована експозиція і миттєвий збиток |
| Перший раз будуєте бота | Спочатку побудуйте scanner, потім price engine, потім signal - ніколи не signal first | Сигнали без чистого стану книги - це пастки кореляції; спочатку налаштуйте канали |
| Виробничий бот упав о 3 ранку | Налаштуйте systemd auto-restart + Telegram alert + persistent state | Будь-який бот без нагляду впаде; питання лише в тому, чи перезапуститься він чисто |
Ціль. Заробляти винагороди за ліквідність на політичному ринку середнього обсягу, який котирується приблизно на 0.48 Yes / 0.52 No зі спредом 2 центи. Денний пул винагород для цього ринку - близько $40.
Налаштування. Підпишіться через WebSocket на обидва token_ids. Кешуйте останню побачену середню ціну. Визначте spread_target = 0.02, size = 200 shares на кожен бік, reprice_threshold = 0.005 (5 ticks).
Цикл. На кожному оновленні WS book: обчисліть нову середню ціну = VWAP топ-3 bids і asks. Якщо |поточні котирування - цільова середня ціна| > reprice_threshold, скасуйте обидва існуючі ордери, виставте новий bid на mid-0.01 і новий ask на mid+0.01. Обмежте переновлення ціни до одного разу на 2 секунди на кожен бік.
Ризик. Максимальний інвентар на бік = 1,000 shares. Якщо інвентар > 500, розширюйте спред на цій стороні на 0.005 на кожні 100 shares. Автоматичний вимикач: якщо mid рухається >0.05 за 60 секунд, скасуйте все і поставте паузу на 5 хвилин.
Результат (реальний 7-денний запуск). Виконано близько 14,000 shares через 680 ордерів, сплачено $0 тейкер (taker) fees (maker side), отримано $31.40 у rebate за ліквідність, чистий directional P&L становив -$4.10 (малі інвентарні втрати). Чистий +$27.30 за 7 днів на $500 working capital = приблизно 8% на місяць. Масштабується лінійно одночасно на 30-50 ринків на одному VPS.
Ключовий висновок
Трейдери, які стабільно заробляють на Polymarket, ставляться до polymarket api guide як до системи, а не як до інтуїції. Пам'ятайте наведені вище цифри - саме вони відрізняють 7.6% прибуткових гаманців від решти.
Що далі?
- Інструменти й ресурси - сторонні панелі, аналітика та джерела даних, які доповнюють API
- Просунуті стратегії - багатоланковий арбітраж і конструкції на кшталт опціонів, придатні для ботів
- Нагороди за ліквідність - точні формули для заробітку на знижках для мейкерів
- Посібник з книги заявок - глибше розуміння того, як читати книгу, перш ніж писати код для роботи з нею
- Глосарій - прості визначення кожного терміна в цьому посібнику
Рекомендоване читання
Почніть тут, якщо ви новачок, або одразу перейдіть на сторінку, що відповідає вашому етапу:











