Οδηγός bot για την Polymarket · Κεφάλαιο 24 από 32
Η Polymarket Perps διαθέτει πλήρες δημόσιο API με επίσημα SDK για TypeScript και Python. Σε αυτό το κεφάλαιο φτιάχνουμε ένα bot πάνω στο πραγματικό interface: έλεγχος ταυτότητας με proxy κλειδί συναλλαγών, δεδομένα αγοράς μέσω REST και WebSocket, εντολές με take-profit και stop-loss, και οι έλεγχοι κινδύνου που εμποδίζουν ένα bot με μόχλευση να αδειάσει τον λογαριασμό.
Τι καλύπτει αυτό το κεφάλαιο
- Βασικά νούμερα για όσους φτιάχνουν 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 του REST | https://api.perpetuals.polymarket.com |
| WebSocket | wss://ws.perpetuals.polymarket.com/v1/ws |
| TypeScript SDK | @polymarket/client (με viem για υπογραφή) |
| Python SDK | polymarket-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 του WebSocket | Ping περίπου κάθε 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. Η λογική κινδύνου είναι δική μας. Τρία επίπεδα προστασίας:
- Όριο μόχλευσης. Η μόχλευση ορίζεται στο 3x ή στο μέγιστο της αγοράς, όποιο είναι χαμηλότερο, με απομονωμένο περιθώριο, και μεγέθη που πέφτουν σε βαθμίδα κινδύνου με χαμηλότερο όριο απορρίπτονται.
- Διακόπτες έκτακτης διακοπής (kill switches). Ένα αρχείο HALT, ένα ημερήσιο όριο ζημίας 5% και έξοδος σε περίπτωση ρευστοποίησης. Ο διακόπτης κλείνει τις θέσεις με εντολές IOC reduce-only, ακυρώνει τις υπόλοιπες εντολές και μετά ελέγχει ότι δεν έχει μείνει τίποτα από τα δύο.
- 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();
Διαγωνισμοί, 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 επιτρέπονται, η χειραγώγηση διαγωνισμών όχι. Μην κάνετε ποτέ συναλλαγές από χώρα με περιορισμούς.





