Учебник по ботам Полимаркет · Глава 3 из 32
Выберите свой стек для бота Полимаркет: Python (py-clob-client 0.34.6), Node.js (@polymarket/clob-client-v2 v1.0.6) или Rust (официального SDK нет, сборка на ethers-rs). Плюсы, минусы, задержка, примеры кода.
Что рассматривается в этой главе
Выбор языка куда менее важен, чем это обычно представляют многие разработчики. Полимаркет предоставляет одни и те же REST и WebSocket-эндпоинты для любого языка; выбор SDK в основном определяет, сколько связующего кода вы напишете сами. У Python и Node есть официально поддерживаемые SDK; у Rust его нет, но для горячего пути это вполне реализуемо. В этой главе мы разберём компромиссы, покажем одну и ту же задачу «получить стакан заявок» на каждом языке, чтобы разница была наглядной, и закончим паттерном смешанного стека, к которому на практике приходит большинство продакшен-ботов.
- Схема принятия решения
- Python (выбор по умолчанию)
- Node.js (fullstack-разработчики)
- Rust (горячий путь, критичный к задержке)
- Команды установки для каждого стека
- Каркас кода: получение стакана заявок на 3 языках
- Когда смешивать стеки (управляющий слой на Python + горячий путь на Rust)
Схема принятия решения
Три вопроса закрывают 90% выбора стека.
- Есть ли у вас сильный уже имеющийся навык? Если вы каждый день пишете на Python, пишите бота на Python. Если вы каждый день пишете на TypeScript, пишите бота на Node. Различия в качестве SDK ниже — реальные, но они меньше, чем цена борьбы с незнакомым языком.
- Является ли стратегия критичной к задержке? Если ваше преимущество зависит от реакции быстрее 50ms (крипторынки на 5 минут, маркет-мейкинг во время новостей), горячий путь выигрывает от Rust или Go. Большинству стратегий это не нужно.
- Будете ли вы запускать больше одной стратегии? Один процесс Python может комфортно управлять 10-20 рынками. Выше этого асинхронный Node или Python с разделением процессов масштабируется лучше.
Честный выбор по умолчанию для первого бота — Python. Переходите на другой стек только если измеримое ограничение заставляет это сделать.
Python (выбор по умолчанию)
Python — выбор по умолчанию, потому что SDK самый полный, а цикл итераций самый быстрый. py-clob-client версии 0.34.6 (май 2026) покрывает все важные эндпоинты CLOB v2: рыночные и лимитные ордера, варианты FOK/FAK/GTC, чтение стакана заявок, чтение баланса и разрешений (allowance), а также прямые операции с блокчейном через web3.py.
Плюсы: зрелый SDK, удобный анализ данных с pandas, большое сообщество, web3.py для чтения данных из блокчейна. Минусы: эргономика асинхронного кода хуже, чем в JavaScript, GIL ограничивает ускорение на нескольких ядрах (для бота, ограниченного вводом-выводом, это обычно неважно), время запуска в холодных контейнерах медленное.
Рекомендуется для: 80% разработчиков. Особенно для тех, чья стратегия включает бэктестинг, статистический анализ или любую работу с данными вместе с исполнением.
Node.js (fullstack-разработчики)
Node.js — второй по качеству поддержки стек. @polymarket/clob-client-v2 версии 1.0.6 покрывает те же эндпоинты, что и SDK для Python, с типами TypeScript повсюду. Асинхронность нативная и быстрая; обработка WebSocket отличная.
Плюсы: лучшая работа с асинхронностью, нативные типы TypeScript, большая экосистема для HTTP + WS, легко развёртывать в той же среде выполнения Node, что и веб-дашборд. Минусы: для больших идентификаторов токенов требуется точность чисел через BigInt или обработка строк (идентификаторы ERC-1155 — 256-битные), инструменты работы с данными уровня pandas слабее.
Рекомендуется для: разработчиков, которые уже поддерживают стек на JavaScript и хотят одну среду выполнения. Также для тех, кто строит дашборд вместе с ботом — общее использование типов между основным ботом и дашбордом на Next.js убирает целый класс багов.
Rust (горячий путь, критичный к задержке)
У Rust нет официального SDK для Полимаркет. Вы строите решения напрямую поверх V2 REST и WebSocket API, используя reqwest (HTTP), tokio-tungstenite (WebSocket) и ethers-rs или alloy для подписи. Это примерно два дня настройки вместо 30 минут в Python.
Плюсы: нативная подпись EIP-712 без JS-подпроцесса, субмиллисекундное построение ордеров, детерминированный профиль памяти под нагрузкой, без пауз на сборку мусора. Минусы: без SDK вам приходится заново реализовывать то, что пользователи Python получают бесплатно (разбор clobToken ID, валидация схемы ответа, управление salt/nonce). Выигрыш в задержке — 20-100ms по сравнению с хорошо настроенным Python, и он важен только для субсекундных стратегий.
Рекомендуется для: горячего пути маркет-мейкинг-бота или части, отправляющей сделки, в боте новостного арбитража. Почти никогда — для всего бота целиком.
Команды установки для каждого стека
Минимальные команды для рабочего подписанного ордера в mainnet (один эндпоинт CLOB v2).
Python:
python -m venv venv && source venv/bin/activate
pip install py-clob-client==0.34.6 web3 python-dotenv
# Set POLYGON_RPC, PRIVATE_KEY, POLY_FUNDER in .env
Node:
npm init -y
npm install @polymarket/clob-client-v2@1.0.6 ethers dotenv
# Set POLYGON_RPC, PRIVATE_KEY, POLY_FUNDER in .env
Rust:
cargo new --bin pmt
cd pmt
cargo add tokio reqwest serde serde_json ethers alloy tungstenite tokio-tungstenite
# Hand-write signer + endpoint client; no SDK shortcut.
Время до первого ордера: ~10 мин Python, ~15 мин Node, ~4-8 часов Rust.
Каркас кода: получение стакана заявок на 3 языках
Одна и та же задача — получить стакан заявок для токена Полимаркет — в каждом стеке. Все три варианта обращаются к одному и тому же REST-эндпоинту CLOB v2.
Python (py-clob-client):
from py_clob_client.client import ClobClient
client = ClobClient(host="https://clob.polymarket.com", chain_id=137)
book = client.get_order_book("<token_id>")
print(book.bids[:3], book.asks[:3])
Node (@polymarket/clob-client-v2):
import { ClobClient } from "@polymarket/clob-client-v2";
const c = new ClobClient({ host: "https://clob.polymarket.com", chain: 137 });
const book = await c.getOrderBook("<token_id>");
console.log(book.bids.slice(0,3), book.asks.slice(0,3));
Rust (прямой HTTP):
let url = format!("https://clob.polymarket.com/book?token_id={}", token);
let book: serde_json::Value = reqwest::get(&url).await?.json().await?;
println!("{:?} {:?}", &book["bids"][..3], &book["asks"][..3]);
Одинаковая форма ответа во всех трёх. Цена Rust — в остальном: подпись, построение ордеров, обработка ошибок — а не в пути чтения.
Когда смешивать стеки (управляющий слой на Python + горячий путь на Rust)
Паттерн, к которому приходят многие продакшен-боты: Python для всего, что связано с решениями, Rust — для миллисекундной части исполнения.
Архитектура: процесс Python читает состояние рынка, запускает логику стратегии и записывает небольшой командный файл (например, {"action":"buy","token":"...","size":10,"price":0.45}) в Unix-сокет. Демон на Rust слушает этот сокет, подписывает ордер и отправляет его в CLOB. Процесс Python может быть медленным и удобным; демон на Rust — быстрым и минимальным.
Передача управления — ключевой момент: изолируя шаг подписи ордера, мы возвращаем себе запас Python на сбои без потери задержки. Мы используем именно этот паттерн в наших продакшен-ботах — Python выдаёт намерения, а демон на Node на /tmp/clob.sock занимается подписью. Версия демона на Node подходит для sub-100ms; Rust начинает действительно оправдывать себя только ниже 50ms.



