Οδηγός bot για την Polymarket · Κεφάλαιο 24 από 32

Η Polymarket Perps διαθέτει πλήρες δημόσιο API με επίσημα SDK για TypeScript και Python. Σε αυτό το κεφάλαιο φτιάχνουμε ένα bot πάνω στο πραγματικό interface: έλεγχος ταυτότητας με proxy κλειδί συναλλαγών, δεδομένα αγοράς μέσω REST και WebSocket, εντολές με take-profit και stop-loss, και οι έλεγχοι κινδύνου που εμποδίζουν ένα bot με μόχλευση να αδειάσει τον λογαριασμό.

Build your own theme park, free in your browserAd Advertise here
Πριν ξεκινήσετε. Η υποβολή εντολών στα Perps δεν επιτρέπεται από τις Ηνωμένες Πολιτείες, τον Καναδά, την Κούβα, το Ιράν, τη Βόρεια Κορέα, τη Συρία, την Κριμαία, το Ντονέτσκ ή το Λουχάνσκ, και το polymarket.com μπλοκάρει και άλλες χώρες. Ένα bot ή ένας server στο εξωτερικό δεν αλλάζει κάτι σε αυτό. Με μόχλευση, ένα σφάλμα στον κώδικα χάνει χρήματα γρήγορα, γι' αυτό κάντε δοκιμές με το ελάχιστο μέγεθος. Πρώτη φορά στα Perps; Ξεκινήστε από τον οδηγό για την Polymarket Perps.

Τι καλύπτει αυτό το κεφάλαιο

  • Βασικά νούμερα για όσους φτιάχνουν bots
  • Πώς είναι δομημένο το API των Perps
  • Βήμα 1: εγκατάσταση του SDK και άνοιγμα session
  • Βήμα 2: ανάγνωση δεδομένων αγοράς μέσω REST και WebSocket
  • Βήμα 3: υποβολή εντολών με take-profit και stop-loss
  • Βήμα 4: σκελετός bot με ελέγχους κινδύνου σε κώδικα
  • Σφάλματα, ο διακόπτης ασφαλείας (dead man's switch), κανόνες για bots και φιλοξενία

Κάθε μέθοδος SDK και κάθε endpoint εδώ προέρχεται από την τεκμηρίωση της Polymarket για τα Perps (docs.polymarket.com/perps, ανάγνωση στις 6 Νοεμβρίου 2026). Η δική μας λογική σημειώνεται στα σχόλια, και η συνάρτηση στρατηγικής είναι ένα σημειωμένο placeholder.

Βασικά νούμερα για όσους φτιάχνουν bots (Νοέμβριος 2026)

ΣτοιχείοΤιμή
Βασικό URL του RESThttps://api.perpetuals.polymarket.com
WebSocketwss://ws.perpetuals.polymarket.com/v1/ws
TypeScript SDK@polymarket/client (με viem για υπογραφή)
Python SDKpolymarket-client (async)
Δημόσια δεδομένα/v1/info/*, χωρίς έλεγχο ταυτότητας
Ιδιωτικές αναγνώσεις/v1/account/* με τα headers polymarket-proxy και polymarket-secret
Υπογεγραμμένες εγγραφές/v1/trade/*, υπογραφή EIP-712 από το proxy κλειδί, έγκυρη για 5 λεπτά
Διαπιστευτήρια sessionΛήγουν από προεπιλογή μετά από μία εβδομάδα
Ελάχιστη εντολή$10 ονομαστική αξία. Ελάχιστη κατάθεση 10 pUSD
Μέγιστη εντολή market$1M στις αγορές 50x και 20x, $500K στις περισσότερες άλλες, $50K στα νομίσματα 3x και 5x
Μορφή τιμής και μεγέθουςΔεκαδικά strings, όχι περισσότερα από τα δεκαδικά της αγοράς και 5 σημαντικά ψηφία
Μέγιστη μόχλευση50x (BTC, ETH, USA500, US100), αλλιώς 20x, 10x, 5x ή 3x ανά αγορά, χαμηλότερη για μεγάλες θέσεις
Προμήθειες (βασική βαθμίδα)Taker 0,040%, maker 0,0125%. ANT στη μισή τιμή
Χρηματοδότηση (funding)Ανά ώρα, με ανώτατο όριο +/-4% ανά ώρα
Ενεργοποίηση TP/SLΤιμή σήμανσης (mark), όχι η τελευταία συναλλαγή
Keepalive του WebSocketPing περίπου κάθε 25 δευτερόλεπτα. Θεωρήστε τη σύνδεση νεκρή μετά από περίπου 65 δευτερόλεπτα σιωπής
Φρεσκάδα tickerΈως 10 δευτερόλεπτα παλιό

Πώς είναι δομημένο το API των Perps

Τα Perps είναι υβριδικό ανταλλακτήριο: η αντιστοίχιση εντολών γίνεται offchain, ενώ η φύλαξη και ο διακανονισμός γίνονται στο Polygon. Μόνο οι καταθέσεις και οι αναλήψεις είναι onchain, άρα δεν υπάρχει gas ανά εντολή. Το API έχει τρία επίπεδα:

  • Δημόσια δεδομένα (/v1/info/): instruments, tickers, βιβλίο εντολών, κεριά, συναλλαγές, χρηματοδότηση, προμήθειες. Δεν χρειάζεται κλειδί και δεν υπάρχει γεωγραφικός αποκλεισμός.
  • Ιδιωτικές αναγνώσεις (/v1/account/): χαρτοφυλάκιο, υπόλοιπα, εντολές, εκτελέσεις, ρυθμίσεις.
  • Υπογεγραμμένες εγγραφές (/v1/trade/): εντολές, ακυρώσεις, μόχλευση, απομονωμένο περιθώριο, αυτόματη ακύρωση. Κάθε εγγραφή κωδικοποιείται σε MessagePack, κατακερματίζεται με keccak256 και υπογράφεται ως EIP-712 typed data από το proxy κλειδί.

Τα SDK κάνουν την υπογραφή για εσάς. Υπάρχει επίσης ένα OpenAPI spec (/api-spec/perps-openapi.json στον ιστότοπο της τεκμηρίωσης) και ένα AsyncAPI spec για το WebSocket.

Τα σύμβολα διαφέρουν από τα παραδείγματα της τεκμηρίωσης. Η τεκμηρίωση δείχνει BTC-PERP. Το ζωντανό API επιστρέφει BTC-USD, SP500-USD (USA500), NAS100-USD (US100), ANT-USD και ούτω καθεξής. Ανακτήστε τη λίστα instruments, αντιστοιχίστε το ζωντανό symbol και αποθηκεύστε το αριθμητικό id. Μην αντιγράφετε IDs από τα παραδείγματα: στο ζωντανό σύστημα, το BTC είναι 6 και το SP500 είναι 1.

Βήμα 1: εγκατάσταση του SDK και άνοιγμα session

Εγκαταστήστε με pip install polymarket-client ή npm install @polymarket/client@latest viem. Το bot χρειάζεται τη διεύθυνση του πορτοφολιού σας στην Polymarket και το ιδιωτικό κλειδί του signer στον οποίο ανήκει ο λογαριασμός Perps (ο λογαριασμός συνδέεται με το EOA του signer, όχι με το Safe). Το άνοιγμα session απαιτεί μία υπογραφή για να εξουσιοδοτήσει ένα νέο proxy κλειδί συναλλαγών, το οποίο στη συνέχεια υπογράφει κάθε εντολή, έτσι το κλειδί με τα κεφάλαιά σας δεν κάνει ποτέ συναλλαγές. Αποθηκεύστε το 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 key από το polymarket.com, Settings, API Keys. Πιο απλό και πιο ασφαλές: χρηματοδοτήστε τον λογαριασμό από την εφαρμογή web και κρατήστε το bot μακριά από τη μετακίνηση χρημάτων. Από τις 5 Νοεμβρίου 2026, οι λογαριασμοί με βιβλίο διευθύνσεων ανάληψης μπορούν να κάνουν ανάληψη μόνο σε αποθηκευμένες διευθύνσεις. Για dashboards, χρησιμοποιήστε ένα κλειδί μόνο ανάγνωσης (ένα proxy με ετικέτα read-only:, που αρνείται τις υπογεγραμμένες εγγραφές), ποτέ το κλειδί συναλλαγών. Η αποθήκευση κλειδιών καλύπτεται στο κεφάλαιό μας για πορτοφόλια και έλεγχο ταυτότητας.

Βήμα 2: ανάγνωση δεδομένων αγοράς μέσω REST και WebSocket

Το ticker έχει τρεις τιμές: index (δίκαιη αξία από πηγές όπως Pyth, Chainlink Data Streams και Hyperliquid), mark (τιμή σήμανσης, χρησιμοποιείται για PnL, περιθώριο, ρευστοποίηση και TP/SL) και last (μόνο για εκτέλεση), καθώς και το επιτόκιο χρηματοδότησης και την επόμενη ώρα χρηματοδότησης. Βασίστε τα σήματά σας στην τιμή σήμανσης ή στο index.

# 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. Για backtests, το list_perps_candles / listPerpsCandles φέρνει το ιστορικό σε σελίδες (το endpoint REST επιστρέφει έως 1.000 κεριά ανά κλήση).

Βήμα 3: υποβολή εντολών με take-profit και stop-loss

Μια εντολή έχει side (BUY ή SELL), quantity σε μονάδες του βασικού στοιχείου, προαιρετικό price σε pUSD και διάρκεια ισχύος (gtc, ioc ή fok). Το post-only απαιτεί GTC. Το reduce-only μπορεί μόνο να μικρύνει μια θέση. Δεν υπάρχει σημαία long ή short: χωρίς ανοιχτή θέση, το BUY ανοίγει long και το SELL ανοίγει short.

Μια εντολή bracket συνδέει ένα take-profit και ένα stop-loss με την εντολή εισόδου. Μένουν ανενεργά μέχρι να εκτελεστεί πλήρως η είσοδος, και ακυρώνονται αν η είσοδος ακυρωθεί ή εκτελεστεί μόνο μερικώς. Οι τιμές παρακάτω είναι υποθετικές.

# 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 προσθέτει triggers που κλείνουν ολόκληρη τη θέση. Κανόνες:

  • Τα triggers παρακολουθούν την τιμή σήμανσης και στέλνουν εντολή reduce-only. Το TP/SL θέσης κλείνει στην τρέχουσα τιμή (market), οπότε περιμένετε slippage σε βιβλία εντολών με χαμηλή ρευστότητα.
  • Ένα take-profit και ένα stop-loss θέσης ανά αγορά. Η μετακίνηση ενός stop σημαίνει ακύρωση και μετά δημιουργία, κάτι που δεν είναι ατομική λειτουργία.
  • Ένα trigger που η τιμή σήμανσης έχει ήδη ξεπεράσει απορρίπτεται, και οι τιμές limit πολύ μακριά από την τιμή σήμανσης δεν γίνονται δεκτές.

Για να δοκιμάσετε τη ροή εντολών χειροκίνητα πριν την αυτοματοποιήσετε, ανοίξτε την αγορά BTC στην Polymarket Perps και υποβάλετε τη μικρότερη επιτρεπόμενη εντολή. Όταν βλέπετε εκτελέσεις, προμήθειες και τον πίνακα θέσεων, οι απαντήσεις του API διαβάζονται πιο εύκολα.

Βήμα 4: σκελετός bot με ελέγχους κινδύνου σε κώδικα

Ο σκελετός σε Python παρακάτω χρησιμοποιεί μόνο τεκμηριωμένες κλήσεις του SDK. Η λογική κινδύνου είναι δική μας. Τρία επίπεδα προστασίας:

  1. Όριο μόχλευσης. Η μόχλευση ορίζεται στο 3x ή στο μέγιστο της αγοράς, όποιο είναι χαμηλότερο, με απομονωμένο περιθώριο, και μεγέθη που πέφτουν σε βαθμίδα κινδύνου με χαμηλότερο όριο απορρίπτονται.
  2. Διακόπτες έκτακτης διακοπής (kill switches). Ένα αρχείο HALT, ένα ημερήσιο όριο ζημίας 5% και έξοδος σε περίπτωση ρευστοποίησης. Ο διακόπτης κλείνει τις θέσεις με εντολές IOC reduce-only, ακυρώνει τις υπόλοιπες εντολές και μετά ελέγχει ότι δεν έχει μείνει τίποτα από τα δύο.
  3. Stop σε κάθε θέση. Οι είσοδοι fill-or-kill σημαίνουν ότι δεν υπάρχουν απροστάτευτες μερικές εκτελέσεις. Μετά από κάθε εκτέλεση ακολουθούν stop και take-profit θέσης. Αν απορριφθούν, η θέση κλείνει αμέσως.
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())

Οι υπολογισμοί μεγέθους. Το μέγεθος προκύπτει από την απόσταση του stop, όχι από τη μόχλευση. Με υποθετική τιμή ask για το BTC στα 100.000 pUSD και stop 2%, το stop βρίσκεται στα 98.000. Ο κίνδυνος ανά μονάδα είναι 2.000, άρα η ποσότητα είναι 20 / 2.000 = 0,01 BTC, ονομαστική αξία 1.000 pUSD. Στο 3x αυτό απαιτεί περίπου 333 pUSD περιθωρίου. Το ποσοστό περιθωρίου διατήρησης του BTC είναι 1% (0,5 / 50x), άρα η τιμή ρευστοποίησης της θέσης long είναι 100.000 x (1 - 1/3) / (1 - 0,01) = περίπου 67.340, πτώση 32,7%. Το stop στο -2% ενεργοποιείται πολύ πριν από αυτό. Αν το stop εκτελεστεί στην τιμή ενεργοποίησης, η ζημία είναι 20 pUSD συν προμήθειες: 0,40 για το άνοιγμα και περίπου 0,39 για το κλείσιμο με την προμήθεια taker 0,040%, δηλαδή περίπου 20,79 pUSD πριν από το slippage. Η μόχλευση καθορίζει μόνο πόσο περιθώριο δεσμεύεται. Δεν αλλάζει τη ζημία στο stop.

Πριν περάσετε σε πραγματική λειτουργία, προσθέστε ημερήσιο όριο συναλλαγών, ειδοποιήσεις για εκτελέσεις και διακόπτες έκτακτης διακοπής, καθώς και συμφωνία κατάστασης κατά την εκκίνηση (fetch_portfolio, fetch_open_orders, fetch_orders, list_fills). Δείτε τα κεφάλαιά μας για τον κώδικα διαχείρισης κινδύνου και την εξάσκηση στις συναλλαγές, τον οδηγό για μόχλευση και ρευστοποίηση στα Perps και τον οδηγό για τα επιτόκια χρηματοδότησης στα Perps.

Σφάλματα, επαναλήψεις και ο διακόπτης ασφαλείας (dead man's switch)

  • 503 service_unavailable: δεν αποδεικνύει ότι το αίτημα απέτυχε. Επαναλάβετε τις αναγνώσεις και τις αλλαγές μόχλευσης με backoff και σεβαστείτε το Retry-After. Για υπογεγραμμένες αλλαγές υπολοίπου (περιθώριο, αναλήψεις), ξαναστείλτε μόνο το ακριβές αρχικό υπογεγραμμένο αίτημα. Μια νέα υπογραφή σημαίνει δεύτερη προσαρμογή.
  • signature expired: παλαιότερη από 5 λεπτά. Κρατήστε το ρολόι συγχρονισμένο.
  • insufficient_margin / invalid_leverage: οι έλεγχοι λαμβάνουν υπόψη τη θέση σας και όλες τις εκκρεμείς εντολές.
  • message_rate_limited: εξαντλήθηκε το όριο μηνυμάτων του WebSocket. Τα κλειδιά μόνο ανάγνωσης έχουν 1.000 μηνύματα ανά λεπτό ανά IP (burst 50) και τέσσερις συνδέσεις ανά λογαριασμό ανά gateway. Για τα υπόλοιπα, δείτε τη σελίδα Rate Limits της τεκμηρίωσης.
  • Σφάλματα μορφής: πάρα πολλά δεκαδικά ή περισσότερα από 5 σημαντικά ψηφία. Γι' αυτό υπάρχει η fit().

Η αυτόματη ακύρωση (auto-cancel) ακυρώνει κάθε ανοιχτή εντολή αν το bot σας σταματήσει να την ανανεώνει. Η προθεσμία πρέπει να είναι τουλάχιστον 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();
Αυτόματη ακύρωση και stops. Η τεκμηρίωση αναφέρει την αυτόματη ακύρωση ως έναν από τους τρόπους με τους οποίους ακυρώνεται μια εντολή TP/SL, άρα ένα crash μπορεί να αφαιρέσει το stop από μια ανοιχτή θέση. Η αυτόματη ακύρωση ταιριάζει σε bots που δίνουν τιμές, όπως οι market makers. Ο σκελετός μας δεν έχει εκκρεμείς εντολές εισόδου, οπότε αφήνει την αυτόματη ακύρωση απενεργοποιημένη για να διατηρεί τα stops. Σε κάθε περίπτωση, η χαμηλή μόχλευση είναι αυτό που προστατεύει ένα bot που κατέρρευσε από τη ρευστοποίηση.

Διαγωνισμοί, builder codes και οι κανόνες για τα bots

Η τεκμηρίωση αναφέρει τα «trading bots που αντιδρούν σε σήματα της αγοράς» και τους market makers ως χρήσεις του API. Ισχύουν δύο σύνολα κανόνων.

  • Διαγωνισμοί. Απαγορεύονται το wash trading, οι συναλλαγές με τον εαυτό σας, οι πολλαπλοί λογαριασμοί, οι συναλλαγές κυρίως για όγκο και τα «bots, scripts ή αυτοματοποιημένα μέσα που αποσκοπούν στη χειραγώγηση του Προγράμματος». Ένα bot που κάνει πραγματικές συναλλαγές είναι αποδεκτό. Ένα bot που φουσκώνει τον όγκο μπορεί να αποκλειστεί.
  • Builder codes. Μια εφαρμογή που κάνει συναλλαγές για λογαριασμό άλλων χρηστών μπορεί να προσθέσει προμήθεια έως 10 μονάδες βάσης με την έγκριση κάθε trader. Πρέπει να επαληθεύει την τοποθεσία κάθε χρήστη και να μπλοκάρει εντολές από περιοχές με περιορισμούς, όχι απλώς να προειδοποιεί.

Οι ανταμοιβές ρευστότητας για makers και οι διαγωνισμοί καλύπτονται στον οδηγό για την Polymarket Perps.

Φιλοξενία του bot

Ένα bot με μόχλευση δεν πρέπει να τρέχει σε laptop. Πρέπει να κρατά το WebSocket του ζωντανό, να αντιδρά σε εκτελέσεις μέσα σε δευτερόλεπτα και να αντέχει μια διακοπή του οικιακού internet. Τρέξτε το σε VPS κάτω από systemd με αυτόματη επανεκκίνηση, κρατήστε το κλειδί σε αρχείο περιβάλλοντος που μπορεί να διαβάσει μόνο ο χρήστης του bot, και συγχρονίστε το ρολόι. Η υποβολή εντολών δεν επιτρέπεται από τοποθεσίες με περιορισμούς, οπότε μην φιλοξενείτε στις ΗΠΑ ή στον Καναδά, και μη χρησιμοποιείτε ποτέ VPS για να παρακάμψετε έναν αποκλεισμό που ισχύει για εσάς. Εμείς τρέχουμε τα δικά μας bots στο TradingVPS (σύνδεσμος affiliate: κερδίζουμε μια μικρή προμήθεια και η τιμή που πληρώνετε είναι ίδια). Το κεφάλαιό μας για φιλοξενία σε VPS το συγκρίνει με άλλους παρόχους ως προς την καθυστέρηση, την τιμή και τις περιοχές.

Μετά την εξάσκηση στις συναλλαγές, χρηματοδοτήστε τον λογαριασμό με ένα μικρό ποσό από τη σελίδα της Polymarket Perps και τρέξτε με το ελάχιστο μέγεθος για μία εβδομάδα πριν αυξήσετε την κλίμακα.

Βασικά συμπεράσματα

  • Χρησιμοποιήστε τα επίσημα SDK, @polymarket/client ή polymarket-client. Το πορτοφόλι σας υπογράφει μία φορά. Ένα proxy κλειδί υπογράφει τις εντολές.
  • Αντιστοιχίστε τις αγορές με βάση το ζωντανό σύμβολο (BTC-USD, όχι BTC-PERP) και αποθηκεύστε το αριθμητικό ID.
  • Υπολογίστε το μέγεθος από την απόσταση του stop, βάλτε όριο μόχλευσης στον κώδικα, χρησιμοποιήστε απομονωμένο περιθώριο και βάλτε stop σε κάθε θέση αμέσως μετά την εκτέλεση.
  • Το TP/SL ενεργοποιείται με βάση την τιμή σήμανσης και κλείνει στην τρέχουσα τιμή. Η αυτόματη ακύρωση μπορεί να αφαιρέσει stops.
  • Τα bots επιτρέπονται, η χειραγώγηση διαγωνισμών όχι. Μην κάνετε ποτέ συναλλαγές από χώρα με περιορισμούς.

Συχνές ερωτήσεις

Έχει η Polymarket Perps API για trading bots;
Ναι. Υπάρχει REST API στο api.perpetuals.polymarket.com, WebSocket στο ws.perpetuals.polymarket.com και επίσημα SDK: @polymarket/client για TypeScript και polymarket-client για Python. Η τεκμηρίωση της Polymarket αναφέρει τα trading bots και τα συστήματα market making ως υποστηριζόμενες χρήσεις.
Να χρησιμοποιήσω το SDK για TypeScript ή για Python;
Οποιοδήποτε από τα δύο. Και τα δύο καλύπτουν την ίδια ροή: δημιουργία secure client, άνοιγμα session Perps, ανάκτηση instruments, υποβολή εντολών με TP/SL και ροή συμβάντων. Το SDK για TypeScript χρησιμοποιεί το viem για υπογραφή. Το SDK για Python είναι async. Επιλέξτε τη γλώσσα στην οποία είναι ήδη γραμμένο το bot σας.
Χρειάζεται το bot μου το ιδιωτικό κλειδί του κύριου πορτοφολιού μου;
Μόνο για να ανοίξει session. Αυτή η μία υπογραφή εξουσιοδοτεί ένα proxy κλειδί συναλλαγών, και από εκεί και πέρα το proxy υπογράφει τις εντολές. Τα διαπιστευτήρια session λήγουν από προεπιλογή μετά από μία εβδομάδα. Αποθηκεύστε τα κρυπτογραφημένα και χρησιμοποιήστε κλειδιά μόνο ανάγνωσης για dashboards.
Πώς ορίζω stop loss μέσω του API των Perps;
Συνδέστε triggers takeProfit και stopLoss στην εντολή εισόδου ως bracket, ή καλέστε το placePositionTpSl (place_position_tp_sl σε Python) σε μια ανοιχτή θέση. Τα triggers παρακολουθούν την τιμή σήμανσης και κλείνουν με εντολή reduce-only. Το TP/SL θέσης κλείνει ολόκληρη τη θέση στην τρέχουσα τιμή.
Ποιο είναι το ελάχιστο μέγεθος εντολής στην Polymarket Perps;
10 δολάρια ονομαστικής αξίας ανά εντολή, και η ελάχιστη κατάθεση είναι 10 pUSD (Νοέμβριος 2026). Οι τιμές και τα μεγέθη πρέπει επίσης να ταιριάζουν με τα δεκαδικά κάθε αγοράς και να μην έχουν περισσότερα από 5 σημαντικά ψηφία, αλλιώς η εντολή απορρίπτεται.
Υπάρχει διακόπτης έκτακτης διακοπής ή dead man's switch;
Ναι. Η αυτόματη ακύρωση ακυρώνει κάθε ανοιχτή εντολή αν το bot σας σταματήσει να την ανανεώνει, και το cancelAllOrders καθαρίζει τις εντολές κατ' απαίτηση. Η τεκμηρίωση αναφέρει την αυτόματη ακύρωση ως έναν τρόπο με τον οποίο μπορεί να ακυρωθεί μια εντολή TP/SL, άρα ένα crash μπορεί επίσης να αφαιρέσει τα stops σας. Γράψτε και τον δικό σας διακόπτη έκτακτης διακοπής.
Μπορώ να τρέξω bot για την Polymarket Perps από τις ΗΠΑ ή τον Καναδά;
Όχι. Η υποβολή εντολών στα Perps δεν επιτρέπεται από τις Ηνωμένες Πολιτείες, τον Καναδά, την Κούβα, το Ιράν, τη Βόρεια Κορέα, τη Συρία, την Κριμαία, το Ντονέτσκ ή το Λουχάνσκ. Μη φιλοξενείτε bot εκεί, και μη χρησιμοποιείτε VPS ή VPN για να παρακάμψετε έναν αποκλεισμό που ισχύει για εσάς.
Επιτρέπονται τα bots στους διαγωνισμούς συναλλαγών της Polymarket Perps;
Οι συναλλαγές με bot επιτρέπονται. Οι κανόνες των διαγωνισμών απαγορεύουν το wash trading, τις συναλλαγές με τον εαυτό σας, τους πολλαπλούς λογαριασμούς, τις συναλλαγές κυρίως για τη δημιουργία όγκου και τα bots ή scripts που αποσκοπούν στη χειραγώγηση του προγράμματος. Η παραβίασή τους μπορεί να οδηγήσει σε αποκλεισμό.