Туторіал ботів Полімаркет · Розділ 24 з 32

Полімаркет Perps має повноцінний публічний API з офіційними SDK для TypeScript і Python. У цьому розділі ми будуємо бота на реальному інтерфейсі. Він охоплює автентифікацію через проксі-ключ для торгівлі, ринкові дані через REST і WebSocket та ордери з тейк-профітом і стоп-лосом. Також ми додаємо контроль ризиків, щоб бот із кредитним плечем не спустошив рахунок.

Build your own theme park, free in your browserРеклама Реклама тут
Перш ніж почати. Розміщувати ордери Perps заборонено зі США, Канади, Куби, Ірану, Північної Кореї, Сирії, Криму, Донецька та Луганська, а polymarket.com блокує й інші країни. Бот або закордонний сервер цього не змінюють. З кредитним плечем помилка в коді швидко коштує грошей, тому тестуйте на мінімальному розмірі. Ще не знайомі з Perps? Почніть з посібника з Полімаркет Perps.

Що охоплює цей розділ

  • Ключові цифри для розробників ботів
  • Як влаштований API Perps
  • Крок 1: встановіть SDK і відкрийте сесію
  • Крок 2: отримуйте ринкові дані через REST і WebSocket
  • Крок 3: розміщуйте ордери з тейк-профітом і стоп-лосом
  • Крок 4: каркас бота з контролем ризиків у коді
  • Помилки, автоматичне скасування на випадок збою, правила для ботів і хостинг

Кожен метод SDK і кожен ендпоінт тут узято з документації Perps від Полімаркет (docs.polymarket.com/perps, переглянуто 6 листопада 2026 р.). Нашу власну логіку позначено в коментарях, а функція стратегії є позначеною заглушкою.

Ключові цифри для розробників ботів (станом на листопад 2026 р.)

ПараметрЗначення
Базовий URL RESThttps://api.perpetuals.polymarket.com
WebSocketwss://ws.perpetuals.polymarket.com/v1/ws
TypeScript SDK@polymarket/client (з viem для підпису)
Python SDKpolymarket-client (асинхронний)
Публічні дані/v1/info/*, без автентифікації
Приватні запити на читання/v1/account/* із заголовками polymarket-proxy і polymarket-secret
Підписані запити на запис/v1/trade/*, підпис EIP-712 проксі-ключем, дійсний 5 хвилин
Облікові дані сесіїЗа замовчуванням спливають через тиждень
Мінімальний ордер$10 номіналу; мінімальний депозит 10 pUSD
Найбільший ринковий ордер$1 млн на ринках 50x і 20x, $500 тис. на більшості інших, $50 тис. на монетах 3x і 5x
Формат ціни та розміруДесяткові рядки, не більше знаків після крапки, ніж дозволяє ринок, і не більше 5 значущих цифр
Максимальне кредитне плече50x (BTC, ETH, USA500, US100), в інших випадках 20x, 10x, 5x або 3x залежно від ринку, менше для великих позицій
Комісії (базовий рівень)Тейкер 0.040%, мейкер 0.0125%; для ANT удвічі дешевше
ФінансуванняЩогодини, не більше +/-4% на годину
Тригери TP/SLМаркувальна ціна, а не ціна останньої угоди
Підтримка зʼєднання WebSocketPing приблизно кожні 25 секунд; вважайте зʼєднання неактивним після приблизно 65 секунд тиші
Актуальність тікераДані до 10 секунд давності

Як влаштований API Perps

Perps є гібридною біржею: зіставлення ордерів відбувається offchain, а зберігання коштів і розрахунки виконуються на Polygon. Onchain проходять лише депозити й виведення, тому за ордери не потрібно платити газ. API має три рівні:

  • Публічні дані (/v1/info/): інструменти, тікери, стакан, свічки, угоди, фінансування, комісії. Ключ не потрібен, географічного блокування немає.
  • Приватні запити на читання (/v1/account/): портфель, баланси, ордери, виконання, налаштування.
  • Підписані запити на запис (/v1/trade/): ордери, скасування, кредитне плече, ізольована маржа, автоматичне скасування. Кожен запис кодується в MessagePack, хешується через keccak256 і підписується проксі-ключем як типізовані дані EIP-712.

SDK підписують запити за вас. Також є специфікація OpenAPI (/api-spec/perps-openapi.json на сайті документації) і специфікація AsyncAPI для WebSocket.

Символи відрізняються від прикладів у документації. У документації наведено BTC-PERP. Робочий API повертає BTC-USD, SP500-USD (USA500), NAS100-USD (US100), ANT-USD тощо. Завантажте список інструментів, знайдіть актуальний symbol і збережіть числовий id. Не копіюйте ID з прикладів: у робочому API BTC має 6, а SP500 має 1.

Крок 1: встановіть SDK і відкрийте сесію

Встановіть пакет командою pip install polymarket-client або npm install @polymarket/client@latest viem. Боту потрібні адреса вашого гаманця на Полімаркет і приватний ключ підписувача, якому належить рахунок Perps (рахунок привʼязаний до EOA підписувача, а не до Safe). Під час відкриття сесії ви ставите один підпис, щоб авторизувати новий проксі-ключ для торгівлі. Далі він підписує кожен ордер, тож ваш ключ із коштами ніколи не торгує. Зберігайте session.credentials у зашифрованому вигляді, щоб відновити сесію пізніше.

import asyncio
import os
from datetime import timedelta

from polymarket import AsyncSecureClient


async def main():
    client = await AsyncSecureClient.create(
        private_key=os.environ["PRIVATE_KEY"],
        wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
    )
    # One signature creates a proxy trading key. Orders are signed by the proxy,
    # not by your wallet key. Credentials expire after one week by default.
    session = await client.open_perps_session(
        expires_in=timedelta(days=1),
        label="perps-bot",
    )
    stored = session.credentials.model_dump(mode="json")  # keep it encrypted

    instruments = await client.fetch_perps_instruments()
    btc = next(i for i in instruments if i.symbol == "BTC-USD")
    print(btc.id, btc.max_leverage, btc.min_notional, btc.price_decimals)


asyncio.run(main())
import { createSecureClient } from "@polymarket/client";
import { privateKey } from "@polymarket/client/viem";

const client = await createSecureClient({
  wallet: process.env.POLYMARKET_WALLET_ADDRESS!,
  signer: privateKey(process.env.PRIVATE_KEY!),
});

// One signature creates a proxy trading key. Orders are signed by the proxy,
// not by your wallet key. Credentials expire after one week by default.
const session = await client.openPerpsSession({
  expiresIn: 24 * 60 * 60 * 1000,
  label: "perps-bot",
});
const stored = session.credentials; // keep it encrypted

const instruments = await client.fetchPerpsInstruments();
const btc = instruments.find((i) => i.symbol === "BTC-USD");
if (!btc) throw new Error("BTC-USD not listed");
console.log(btc.id, btc.maxLeverage, btc.minNotional, btc.priceDecimals);

Для депозиту з коду (deposit_to_perps / depositToPerps) також потрібен ключ Relayer API з розділу Settings, API Keys на polymarket.com. Простіше й безпечніше поповнювати рахунок у вебзастосунку і не давати боту доступу до переказів коштів. З 5 листопада 2026 р. рахунки, що мають адресну книгу для виведення, можуть виводити кошти лише на збережені адреси. Для дашбордів використовуйте ключ лише для читання (проксі з міткою read-only:, який відхиляє підписані запити на запис), і ніколи не використовуйте для цього торговий ключ. Зберігання ключів описано в нашому розділі про гаманці та автентифікацію.

Крок 2: отримуйте ринкові дані через REST і WebSocket

Тікер містить три ціни: індексну (справедлива вартість із фідів, таких як Pyth, Chainlink Data Streams і Hyperliquid), маркувальну (для PnL, маржі, ліквідації та TP/SL) і останню (лише для виконання), а також ставку фінансування і час наступного нарахування фінансування. Будуйте сигнали на маркувальній або індексній ціні.

# Inside your async main(), after Step 1 (btc is the BTC-USD instrument)
from polymarket import AsyncPublicClient
from polymarket.streams import PerpsBboSpec

client = AsyncPublicClient()

ticker = await client.fetch_perps_ticker(instrument_id=btc.id)
print(ticker.mark_price, ticker.index_price, ticker.funding_rate)

stream = await client.subscribe(PerpsBboSpec(instrument_id=btc.id))
async for event in stream:
    print(event.payload.bid_price, event.payload.ask_price)
// After Step 1 (btc is the BTC-USD instrument)
import { createPublicClient } from "@polymarket/client";

const client = createPublicClient();

const ticker = await client.fetchPerpsTicker({ instrumentId: btc.id });
console.log(ticker.markPrice, ticker.indexPrice, ticker.fundingRate);

const stream = await client.subscribe([{ topic: "perps.bbo", instrumentId: btc.id }]);
for await (const event of stream) {
  console.log(event.payload.bidPrice, event.payload.askPrice);
}

Без SDK підпишіться через «сирий» WebSocket повідомленням {"id": 1, "req": "sub", "chs": ["bbo::6"]}. Серед каналів є bbo::<id>, book::<id>, trades::<id>, tickers::<id> і klines::<id>::1m. Кожне оновлення має порядковий номер sq: після пропуску або перепідключення заново зчитайте стан через REST. Для бектестів list_perps_candles / listPerpsCandles посторінково завантажує історію (ендпоінт REST повертає до 1 000 свічок за один запит).

Крок 3: розміщуйте ордери з тейк-профітом і стоп-лосом

Ордер має side (BUY або SELL), quantity в одиницях базового активу, необовʼязкову price у pUSD і строк дії (gtc, ioc або fok). Post-only потребує GTC; reduce-only може лише зменшити позицію. Окремого прапорця long чи short немає: коли позиції немає, BUY відкриває long, а SELL відкриває short.

Брекет-ордер прикріплює до входу один тейк-профіт і один стоп-лос. Вони неактивні, доки вхідний ордер не виконається повністю, і скасовуються, якщо вхід скасовано або виконано лише частково. Ціни нижче умовні.

# Inside your async main(), after Step 1 (btc is the BTC-USD instrument)
from polymarket import PerpsTpSlTrigger

result = await session.place_order(
    instrument_id=btc.id,
    side="BUY",
    price="100000",
    quantity="0.01",
    time_in_force="gtc",
    take_profit=PerpsTpSlTrigger(trigger_price="104000"),
    stop_loss=PerpsTpSlTrigger(trigger_price="98000"),
)
print(result.order.id, result.order.status)
// After Step 1 (btc is the BTC-USD instrument)
import { OrderSide, PerpsTimeInForce } from "@polymarket/client";

const result = await session.placeOrder({
  instrumentId: btc.id,
  side: OrderSide.BUY,
  price: "100000",
  quantity: "0.01",
  timeInForce: PerpsTimeInForce.GTC,
  takeProfit: { triggerPrice: "104000" },
  stopLoss: { triggerPrice: "98000" },
});
console.log(result.order.id, result.tpSl.stopLoss?.orderId);

Для відкритої позиції place_position_tp_sl / placePositionTpSl додає тригери, які закривають усю позицію. Правила:

  • Тригери відстежують маркувальну ціну і надсилають ордер reduce-only. TP/SL позиції виходить за ринком, тож у тонкому стакані очікуйте прослизання.
  • На кожному ринку можна мати один тейк-профіт і один стоп-лос позиції. Щоб пересунути стоп, його треба скасувати й створити заново, і ця операція не атомарна.
  • Тригер, який маркувальна ціна вже перетнула, відхиляється, як і лімітні ціни, що надто далекі від маркувальної.

Щоб спробувати процес розміщення ордерів вручну перед автоматизацією, відкрийте ринок BTC на Полімаркет Perps і розмістіть найменший дозволений ордер. Коли ви побачите виконання, комісії та панель позиції, відповіді API буде легше зрозуміти.

Крок 4: каркас бота з контролем ризиків у коді

Каркас на Python нижче використовує лише задокументовані виклики SDK; логіка ризиків наша. Три рівні захисту:

  1. Обмеження кредитного плеча. Кредитне плече встановлюється на 3x або на максимум ринку, залежно від того, що менше, з ізольованою маржею. Розміри, що потрапляють у рівень ризику з нижчим лімітом, відхиляються.
  2. Аварійні вимикачі. Файл HALT, денний ліміт збитку 5% і вихід у разі ліквідації. Вимикач закриває позиції ордерами reduce-only IOC, скасовує решту ордерів, а потім перевіряє, що не лишилося ні позицій, ні ордерів.
  3. Стоп на кожній позиції. Входи fill-or-kill гарантують, що не буде незахищених часткових виконань. Після кожного виконання встановлюються стоп і тейк-профіт позиції; якщо їх відхилено, позиція одразу закривається.
import asyncio
import logging
import os
from datetime import timedelta
from decimal import Decimal, ROUND_DOWN

from polymarket import AsyncSecureClient, PerpsPositionTpSlTrigger

SYMBOL = "BTC-USD"                   # live API symbol; docs examples say "BTC-PERP"
LEVERAGE_CAP = 3                     # our cap, far below the 50x BTC allows
RISK_PER_TRADE = Decimal("20")       # pUSD we accept losing if the stop fills
STOP_PCT = Decimal("0.02")           # stop 2% from entry
TAKE_PCT = Decimal("0.04")           # take profit 4% from entry
MAX_NOTIONAL = Decimal("2000")       # hard cap per position, in pUSD
MAX_SLIPPAGE = Decimal("0.002")      # worst entry price: ask + 0.2%
MAX_FUNDING = Decimal("0.0005")      # skip longs if funding > 0.05% per hour
DAILY_LOSS_LIMIT = Decimal("0.05")   # kill switch at -5% of start equity
HALT_FILE = "/opt/perps-bot/HALT"    # touch this file to stop the bot


def fit(value: Decimal, decimals: int, sig: int = 5) -> str:
    """Round down to the market's decimals and to 5 significant figures."""
    v = value.quantize(Decimal(1).scaleb(-decimals), rounding=ROUND_DOWN)
    if v != 0:
        step = Decimal(1).scaleb(v.adjusted() - sig + 1)
        if step > Decimal(1).scaleb(-decimals):
            v = v.quantize(step, rounding=ROUND_DOWN)
    return format(v, "f")


def tier_cap(inst, notional: Decimal) -> int:
    """Max leverage allowed for this notional by the market's risk tiers."""
    cap = inst.max_leverage
    for tier in inst.risk_tiers:
        if notional >= Decimal(tier.lower_bound):
            cap = tier.max_leverage
    return cap


async def close_all(session):
    """Close every position with reduce-only IOC orders, then cancel the rest."""
    portfolio = await session.fetch_portfolio()
    for pos in portfolio.positions:
        if pos.size != 0:
            await session.place_order(
                instrument_id=pos.instrument_id,
                side="SELL" if pos.size > 0 else "BUY",
                quantity=abs(pos.size),
                time_in_force="ioc",
                reduce_only=True,
            )
    await session.cancel_all_orders()


async def kill_switch(session, reason: str):
    logging.error("KILL SWITCH: %s", reason)
    for attempt in range(3):
        await close_all(session)
        portfolio = await session.fetch_portfolio()
        open_orders = await session.fetch_open_orders()
        if not open_orders and all(p.size == 0 for p in portfolio.positions):
            return
        await asyncio.sleep(2)
    logging.critical("Positions still open after kill switch: act manually")


async def open_long(client, session, inst):
    ticker = await client.fetch_perps_ticker(instrument_id=inst.id)
    if Decimal(ticker.funding_rate) > MAX_FUNDING:
        return                                     # longs would pay too much
    book = await client.fetch_perps_book(instrument_id=inst.id, depth=10)
    if not book.asks:
        return
    ask = Decimal(book.asks[0].price)
    stop = ask * (1 - STOP_PCT)
    qty = RISK_PER_TRADE / (ask - stop)            # size from the stop, not leverage
    qty = min(qty, MAX_NOTIONAL / ask)
    notional = qty * ask
    if notional < Decimal(inst.min_notional):
        return
    if tier_cap(inst, notional) < LEVERAGE_CAP:
        return                                     # size would break our cap

    entry = await session.place_order(
        instrument_id=inst.id,
        side="BUY",
        price=fit(ask * (1 + MAX_SLIPPAGE), inst.price_decimals),
        quantity=fit(qty, inst.quantity_decimals),
        time_in_force="fok",                       # all or nothing
    )
    if entry.order.status != "filled":
        return

    try:                                           # stop on the whole position
        await session.place_position_tp_sl(
            instrument_id=inst.id,
            take_profit=PerpsPositionTpSlTrigger(
                trigger_price=fit(ask * (1 + TAKE_PCT), inst.price_decimals)),
            stop_loss=PerpsPositionTpSlTrigger(
                trigger_price=fit(stop, inst.price_decimals)),
        )
    except Exception:
        logging.exception("TP/SL rejected: closing the unprotected position")
        await close_all(session)


async def my_signal(client, inst) -> bool:
    """PLACEHOLDER: your strategy goes here. Not part of the SDK."""
    return False


async def main():
    logging.basicConfig(level=logging.INFO)
    client = await AsyncSecureClient.create(
        private_key=os.environ["PRIVATE_KEY"],
        wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
    )
    session = await client.open_perps_session(
        expires_in=timedelta(days=1), label="perps-bot")
    inst = next(i for i in await client.fetch_perps_instruments()
                if i.symbol == SYMBOL)

    # Control 1: leverage cap and isolated margin, set before any order
    await session.update_leverage(
        instrument_id=inst.id,
        leverage=min(LEVERAGE_CAP, inst.max_leverage),
        cross_margin=False,
    )

    # Field names below follow the documented portfolio JSON
    # (margin.total_account_value, in_liquidation). Check them in your SDK.
    start_equity = Decimal((await session.fetch_portfolio()).margin.total_account_value)

    while True:
        portfolio = await session.fetch_portfolio()
        equity = Decimal(portfolio.margin.total_account_value)

        # Control 2: kill switches
        if os.path.exists(HALT_FILE):
            await kill_switch(session, "HALT file found")
            break
        if equity < start_equity * (1 - DAILY_LOSS_LIMIT):
            await kill_switch(session, f"daily loss limit hit: {equity}")
            break
        if portfolio.in_liquidation:
            await kill_switch(session, "account in liquidation")
            break

        in_position = any(p.instrument_id == inst.id and p.size != 0
                          for p in portfolio.positions)
        if not in_position and await my_signal(client, inst):
            await open_long(client, session, inst)   # Control 3 lives here

        await asyncio.sleep(5)


asyncio.run(main())

Розрахунок розміру. Розмір визначається відстанню до стопу, а не кредитним плечем. Візьмімо умовну ціну продажу BTC 100 000 pUSD і стоп 2%: стоп стоїть на 98 000. Ризик на одиницю становить 2 000, тож кількість дорівнює 20 / 2 000 = 0.01 BTC, тобто номінал 1 000 pUSD. З плечем 3x для цього потрібно близько 333 pUSD маржі. Ставка підтримувальної маржі для BTC становить 1% (0.5 / 50x), тож ціна ліквідації лонга дорівнює 100 000 x (1 - 1/3) / (1 - 0.01) = приблизно 67 340, тобто падіння на 32.7%. Стоп на -2% спрацює задовго до цього. Якщо стоп виконається за ціною тригера, збиток становитиме 20 pUSD плюс комісії: 0.40 за відкриття і приблизно 0.39 за закриття за тарифом тейкера 0.040%. Разом це приблизно 20.79 pUSD без урахування прослизання. Кредитне плече визначає лише те, скільки маржі заблоковано. Воно не змінює збиток на стопі.

Перед запуском на реальних коштах додайте денний ліміт угод, сповіщення про виконання та спрацювання аварійних вимикачів, а також звірку стану під час старту (fetch_portfolio, fetch_open_orders, fetch_orders, list_fills). Дивіться наші розділи про код для керування ризиками і паперову торгівлю, посібник з кредитного плеча та ліквідації в Perps і посібник зі ставок фінансування в Perps.

Помилки, повторні спроби та автоматичне скасування на випадок збою

  • 503 service_unavailable не означає, що запит точно не пройшов. Повторюйте запити на читання і зміни кредитного плеча зі збільшенням інтервалу та враховуйте Retry-After. Для підписаних змін балансу (маржа, виведення) повторно надсилайте лише точно той самий підписаний запит; новий підпис означатиме другу зміну.
  • signature expired: підпис старший за 5 хвилин. Синхронізуйте годинник.
  • insufficient_margin / invalid_leverage: перевірки враховують вашу позицію плюс усі активні ордери.
  • message_rate_limited: ліміт повідомлень WebSocket вичерпано. Ключі лише для читання мають 1 000 повідомлень на хвилину з однієї IP-адреси (пікове навантаження 50) і чотири зʼєднання на рахунок на шлюз; інші ліміти дивіться на сторінці Rate Limits у документації.
  • Помилки формату: забагато знаків після крапки або понад 5 значущих цифр. Саме для цього потрібна fit().

Автоматичне скасування скасовує всі відкриті ордери, якщо ваш бот перестає його поновлювати. Дедлайн має бути щонайменше на 5 секунд у майбутньому, а кількість спрацювань за добу UTC обмежена, тому вимикайте його під час коректного завершення роботи.

// For quoting bots: cancel all resting orders if this process dies
await session.armAutoCancel({ cancelAt: Date.now() + 60_000 });
const rearm = setInterval(() => {
  // A missed re-arm is fail-safe: the armed switch still fires.
  session.armAutoCancel({ cancelAt: Date.now() + 60_000 }).catch(console.error);
}, 20_000);

// On a clean shutdown
clearInterval(rearm);
await session.disarmAutoCancel();
Автоматичне скасування та стопи. У документації автоматичне скасування вказано як одну з причин, через які ордер TP/SL може бути скасовано, тож збій може прибрати стоп з відкритої позиції. Автоматичне скасування підходить для ботів, що виставляють котирування, наприклад маркетмейкерів. Наш каркас не має активних вхідних ордерів, тому автоматичне скасування в ньому вимкнене, щоб стопи лишалися на місці. У будь-якому разі від ліквідації бота після збою захищає саме низьке кредитне плече.

Змагання, коди білдерів і правила для ботів

У документації серед сценаріїв використання API названо «торгових ботів, що реагують на ринкові сигнали» та маркетмейкерів. Діють два набори правил.

  • Змагання. Заборонено фіктивну торгівлю (wash trading), торгівлю із самим собою, кілька рахунків, торгівлю переважно заради обсягу та «ботів, скрипти або автоматизовані засоби, призначені для маніпулювання Програмою». Бот, що справді торгує, дозволений; бот, що накручує обсяг, можуть дискваліфікувати.
  • Коди білдерів. Застосунок, що торгує для інших користувачів, може додавати комісію до 10 базисних пунктів за згодою кожного трейдера. Він має перевіряти місцезнаходження кожного користувача й блокувати ордери з юрисдикцій з обмеженнями, а не лише попереджати.

Винагороди мейкерам за ліквідність і змагання описано в посібнику з Полімаркет Perps.

Хостинг бота

Бот із кредитним плечем не варто запускати на ноутбуці. Він має підтримувати WebSocket-зʼєднання, реагувати на виконання за секунди й переживати перебої домашнього інтернету. Запускайте його на VPS під systemd з автоматичним перезапуском, тримайте ключ у файлі змінних середовища, який може читати лише користувач бота, і синхронізуйте годинник. Розміщувати ордери з регіонів з обмеженнями заборонено, тому не хостьте бота у США чи Канаді й ніколи не використовуйте VPS, щоб обійти блокування, яке стосується вас. Наші власні боти працюють на TradingVPS (партнерське посилання: ми отримуємо невелику комісію, а ціна для вас не змінюється). У нашому розділі про VPS-хостинг його порівняно з іншими провайдерами за затримкою, ціною та регіонами.

Після паперової торгівлі поповніть рахунок невеликою сумою на сторінці Полімаркет Perps і тиждень працюйте з мінімальним розміром, перш ніж масштабуватися.

Головне

  • Використовуйте офіційні SDK, @polymarket/client або polymarket-client. Ваш гаманець підписує один раз; ордери підписує проксі-ключ.
  • Шукайте ринки за актуальним символом (BTC-USD, а не BTC-PERP) і зберігайте числовий ID.
  • Визначайте розмір від відстані до стопу, обмежуйте кредитне плече в коді, використовуйте ізольовану маржу і ставте стоп на кожну позицію одразу після виконання.
  • TP/SL спрацьовує за маркувальною ціною і виходить за ринком. Автоматичне скасування може прибрати стопи.
  • Боти дозволені, маніпулювання змаганнями заборонене. Ніколи не торгуйте з країни з обмеженнями.

Часті запитання

Чи має Полімаркет Perps API для торгових ботів?
Так. Є REST API за адресою api.perpetuals.polymarket.com, WebSocket за адресою ws.perpetuals.polymarket.com та офіційні SDK: @polymarket/client для TypeScript і polymarket-client для Python. У документації Полімаркет торгові боти та системи маркетмейкінгу вказані як підтримувані сценарії використання.
Який SDK обрати: TypeScript чи Python?
Будь-який. Обидва охоплюють той самий процес: створити захищений клієнт, відкрити сесію Perps, завантажити інструменти, розмістити ордери з TP/SL і отримувати потік подій. TypeScript SDK використовує viem для підпису. Python SDK асинхронний. Обирайте мову, якою вже написано вашого бота.
Чи потрібен боту приватний ключ мого основного гаманця?
Лише для відкриття сесії. Цей один підпис авторизує проксі-ключ для торгівлі, і надалі ордери підписує проксі. Облікові дані сесії за замовчуванням спливають через тиждень. Зберігайте їх у зашифрованому вигляді й використовуйте ключі лише для читання для дашбордів.
Як встановити стоп-лос через API Perps?
Прикріпіть тригери takeProfit і stopLoss до вхідного ордера як брекет або викличте placePositionTpSl (place_position_tp_sl у Python) для відкритої позиції. Тригери відстежують маркувальну ціну і виходять ордером reduce-only. TP/SL позиції закриває всю позицію за ринком.
Який мінімальний розмір ордера на Полімаркет Perps?
$10 номіналу на ордер, а мінімальний депозит становить 10 pUSD (станом на листопад 2026 р.). Ціни й розміри також мають відповідати кількості знаків після крапки на кожному ринку і містити не більше 5 значущих цифр, інакше ордер буде відхилено.
Чи є аварійний вимикач або автоматичне скасування на випадок збою?
Так. Автоматичне скасування скасовує всі відкриті ордери, якщо ваш бот перестає його поновлювати, а cancelAllOrders прибирає ордери на вимогу. У документації автоматичне скасування вказано як одну з причин, через які ордер TP/SL може бути скасовано, тож збій може прибрати й ваші стопи. Напишіть також власний аварійний вимикач.
Чи можна запускати бота для Полімаркет Perps зі США чи Канади?
Ні. Розміщувати ордери Perps заборонено зі США, Канади, Куби, Ірану, Північної Кореї, Сирії, Криму, Донецька та Луганська. Не хостьте там бота й не використовуйте VPS чи VPN, щоб обійти блокування, яке стосується вас.
Чи дозволені боти в торгових змаганнях Полімаркет Perps?
Торгувати за допомогою бота дозволено. Правила змагань забороняють фіктивну торгівлю (wash trading), торгівлю із самим собою, кілька рахунків, торгівлю переважно заради обсягу, а також ботів чи скрипти, призначені для маніпулювання програмою. Порушення може призвести до дискваліфікації.