Skip to content

OKX SDK

Complete reference for ctx.okx — programmatic trading on OKX from worker code.

OKX V5 API

This SDK wraps the OKX V5 unified API for spot, perpetual swap, futures, and options. Live and demo environments supported.

Setup

  1. Add an OKX trading block to your workspace canvas.
  2. Open the inspector → API Keys → pick a key (Settings → API Keys → OKX to add new). OKX requires api_key + api_secret + passphrase.
  3. Connect the block to your Worker block via an edge.
  4. ctx.okx is now available.
python
def tick(ctx):
    t = ctx.okx.get_ticker("BTC-USDT-SWAP")
    ctx.log.info(f"BTC perp: {t['data'][0]['last']}")

If no OKX block is connected:

RuntimeError: No trading block connected. Connect an OKX block to this worker.

Instrument Naming & Modes

OKX uses inst_id strings shaped by category:

PatternExampleMeaning
{COIN}-{COIN}BTC-USDTSpot pair
{COIN}-{COIN}-SWAPBTC-USDT-SWAPPerpetual swap
{COIN}-{COIN}-{EXPIRY}BTC-USDT-251227Dated future
{COIN}-USD-{EXP}-{STRIKE}-{C|P}BTC-USD-251227-100000-COption

inst_type parameter (where applicable):

ValueMeaning
SPOTSpot
MARGINMargin
SWAPPerpetual swap
FUTURESDated futures
OPTIONOptions

Account modes (api_mode on key):

ModeEndpointNotes
livewww.okx.comReal funds
demowww.okx.com + x-simulated-trading: 1Paper-trading, real prices

There's no testnet — OKX uses a header flag for demo mode.

Market Data

get_ticker

Latest ticker.

python
ctx.okx.get_ticker(inst_id: str = "BTC-USDT") -> dict

Returns: {"code", "data": [{"instId", "last", "lastSz", "askPx", "bidPx", "open24h", "high24h", "low24h", "volCcy24h", "vol24h", …}]}

python
t = ctx.okx.get_ticker("BTC-USDT")
last = float(t["data"][0]["last"])

WebSocket cache

PRO/MAX plans return cached ticker data at 0ms latency from the live WS stream — no REST call.

get_orderbook

Order book depth.

python
ctx.okx.get_orderbook(inst_id: str = "BTC-USDT") -> dict

Returns: {"data": [{"asks": [[price, size, ...]], "bids": [[price, size, ...]], "ts"}]}

get_klines

Candlestick OHLCV.

python
ctx.okx.get_klines(inst_id: str = "BTC-USDT", bar: str = "1H", limit: int = 100) -> dict

bar values: "1m" "3m" "5m" "15m" "30m" "1H" "2H" "4H" "6H" "12H" "1D" "1W" "1M".

Returns: {"data": [[ts, open, high, low, close, volume, volCcy, volCcyQuote, confirm]]}.

get_instruments

All instruments for a category.

python
ctx.okx.get_instruments(inst_type: str = "SWAP") -> dict

get_funding_rate

Current funding rate for a perpetual.

python
ctx.okx.get_funding_rate(inst_id: str = "BTC-USDT-SWAP") -> dict

get_mark_price

Mark price for derivatives.

python
ctx.okx.get_mark_price(inst_type: str = "SWAP", inst_id: str = None) -> dict
python
mp = ctx.okx.get_mark_price(inst_id="BTC-USDT-SWAP")
mark = float(mp["data"][0]["markPx"])

get_open_interest

Open interest for derivatives.

python
ctx.okx.get_open_interest(inst_type: str = "SWAP", inst_id: str = None) -> dict

Account & Positions

get_balance

Account balance for one or all currencies.

python
ctx.okx.get_balance(ccy: str = None) -> dict

WebSocket cache

PRO/MAX: cached from private WS at 0ms.

get_positions

Open positions.

python
ctx.okx.get_positions(inst_type: str = None) -> dict

WebSocket cache

PRO/MAX: cached at 0ms.

get_position_history

Closed position history with entry / exit and realised P&L.

python
ctx.okx.get_position_history(
    inst_type: str = None,
    inst_id: str = None,
    mgn_mode: str = None,        # "isolated" | "cross"
    type: str = None,            # "1" partial close / "2" full close / "3" liquidation
                                 # "4" auto-deleveraging / "5" settlement
    limit: int = 100,
) -> dict

get_account_config

Account-level config: position mode, margin mode, account level (Lv1-Lv4).

python
ctx.okx.get_account_config() -> dict

set_position_mode

Switch derivatives mode for the whole account.

python
ctx.okx.set_position_mode(pos_mode: str = "long_short_mode") -> dict
# pos_mode: "long_short_mode" (hedge) | "net_mode" (one-way)

set_leverage

Set leverage on an instrument.

python
ctx.okx.set_leverage(inst_id: str, lever: str, mgn_mode: str = "cross") -> dict
# mgn_mode: "cross" | "isolated"

get_max_size

Max buy / sell size given current leverage + balance.

python
ctx.okx.get_max_size(
    inst_id: str,
    td_mode: str = "cross",
    ccy: str = None,
    leverage = None,
) -> dict
python
m = ctx.okx.get_max_size("BTC-USDT-SWAP", td_mode="cross")
ctx.log.info(f"Max long: {m['data'][0]['maxBuy']}, max short: {m['data'][0]['maxSell']}")

Orders

place_order

Place a single order. Auto-routes spot / margin / swap / futures by inst_id.

python
ctx.okx.place_order(
    inst_id: str,
    side: str,                # "buy" | "sell"
    sz: str,                  # contract count for derivatives, base qty for spot
    ord_type: str = "market", # "market" | "limit" | "post_only" | "fok" | "ioc"
    px: str = None,           # required for non-market types
    td_mode: str = "cross",   # "cash" (spot) | "cross" | "isolated"
    pos_side: str = None,     # "long" | "short" (hedge mode only)
    reduce_only: bool = False,
) -> dict
python
# Market buy 0.01 BTC perp at cross margin
r = ctx.okx.place_order("BTC-USDT-SWAP", "buy", "1", "market")  # 1 contract = 0.01 BTC

# Spot limit
r = ctx.okx.place_order("BTC-USDT", "buy", "0.001", "limit", px="65000", td_mode="cash")

cancel_order

Cancel a single order.

python
ctx.okx.cancel_order(inst_id: str, order_id: str = None, cl_ord_id: str = None) -> dict

cancel_all_orders

Cancel ALL pending orders, optionally filtered.

python
ctx.okx.cancel_all_orders(inst_type: str = None, inst_id: str = None) -> dict
python
# Kill switch — cancel everything
ctx.okx.cancel_all_orders()

amend_order

Modify qty / price of an unfilled order.

python
ctx.okx.amend_order(
    inst_id: str,
    order_id: str = None,
    cl_ord_id: str = None,
    new_sz: str = None,
    new_px: str = None,
) -> dict

get_orders

Active (unfilled) orders.

python
ctx.okx.get_orders(inst_type: str = None) -> dict

WebSocket cache

PRO/MAX: cached at 0ms.

get_order_history

Filled / cancelled order history (last 7 days).

python
ctx.okx.get_order_history(
    inst_type: str = "SWAP",
    inst_id: str = None,
    state: str = None,           # "canceled" | "filled" | "partially_filled"
    limit: int = 100,
) -> dict

get_fills

Trade fills with fees.

python
ctx.okx.get_fills(inst_type: str = None, inst_id: str = None) -> dict

close_position

Close a position immediately.

python
ctx.okx.close_position(inst_id: str, mgn_mode: str = "cross") -> dict

Algo Orders

OKX's algo orders are SDK-level smart orders — placed and managed independently of regular orders. Use them for TP/SL pairs, conditional triggers, trailing stops, iceberg, and TWAP.

place_algo_order

Universal algo-order entry point.

python
ctx.okx.place_algo_order(
    inst_id: str,
    side: str,                       # "buy" | "sell"
    sz,
    ord_type: str = "conditional",
    td_mode: str = "cross",
    # ── For "conditional" / "oco" (TP+SL paired) ──
    tp_trigger_px = None,            # take-profit trigger
    tp_ord_px = None,                # take-profit limit price (-1 = market)
    sl_trigger_px = None,            # stop-loss trigger
    sl_ord_px = None,                # stop-loss limit price (-1 = market)
    # ── For "trigger" (price → market/limit) ──
    trigger_px = None,
    order_px = None,                 # -1 = market
    # ── Common ──
    algo_cl_ord_id: str = None,
    reduce_only: bool = False,
) -> dict
ord_typeUse for
"conditional"One-way TP or SL
"oco"TP and SL paired (one cancels the other)
"trigger"Price trigger then market or limit
"move_order_stop"Trailing stop
"iceberg"Iceberg (visible chunks of a large order)
"twap"TWAP (time-weighted average price)
python
# OCO: take 5% profit OR stop-loss at -2%
entry = 65000
ctx.okx.place_algo_order(
    inst_id="BTC-USDT-SWAP",
    side="sell", sz="1",
    ord_type="oco",
    tp_trigger_px=str(entry * 1.05), tp_ord_px="-1",  # market take-profit
    sl_trigger_px=str(entry * 0.98), sl_ord_px="-1",  # market stop-loss
    reduce_only=True,
)

cancel_algo_order

Cancel an algo order by algoId.

python
ctx.okx.cancel_algo_order(algo_id: str, inst_id: str) -> dict

get_algo_orders

List active algo orders.

python
ctx.okx.get_algo_orders(
    ord_type: str = "conditional",
    inst_type: str = None,
    inst_id: str = None,
    limit: int = 100,
) -> dict

Common Patterns

Demo mode during development

Set the API-key mode to demo in Settings → API Keys → OKX. All worker calls auto-add the x-simulated-trading: 1 header.

Error handling

python
def tick(ctx):
    try:
        positions = ctx.okx.get_positions()
    except Exception as e:
        ctx.log.error(f"OKX unreachable: {e}")
        return

OkxAPIError (extends ExchangeAPIError) is raised for API errors. Network failures raise httpx.HTTPStatusError.

Cloud-Run proxy

PRO+ workers route OKX traffic through a Cloud Run proxy with rotating exit IPs. Transparent — no code changes.

WebSocket caching

PRO+ subscribes to public + private streams in the background. get_ticker, get_orderbook, get_balance, get_positions, get_orders auto-prefer the cache when fresh.

Recipes

OCO entry (TP + SL paired)

python
def tick(ctx):
    pos = ctx.okx.get_positions(inst_type="SWAP")
    if any(p["instId"] == "BTC-USDT-SWAP" and float(p["pos"]) != 0
           for p in pos.get("data", [])):
        return  # already in a position

    px = float(ctx.okx.get_ticker("BTC-USDT-SWAP")["data"][0]["last"])

    # Limit-buy 1 contract
    ctx.okx.place_order("BTC-USDT-SWAP", "buy", "1", "limit", px=str(round(px - 50)))

    # Pre-stage OCO: TP +3%, SL -1.5%
    ctx.okx.place_algo_order(
        inst_id="BTC-USDT-SWAP",
        side="sell", sz="1",
        ord_type="oco",
        tp_trigger_px=str(round(px * 1.03, 1)), tp_ord_px="-1",
        sl_trigger_px=str(round(px * 0.985, 1)), sl_ord_px="-1",
        reduce_only=True,
    )
    ctx.log.info(f"Entry placed at {px:.2f} with OCO exits")

Trailing stop after 2% in profit

python
def tick(ctx):
    pos = ctx.okx.get_positions(inst_type="SWAP")
    long = next((p for p in pos.get("data", [])
                 if p["instId"] == "BTC-USDT-SWAP" and float(p["pos"]) > 0), None)
    if not long:
        return

    entry = float(long["avgPx"])
    mark = float(ctx.okx.get_mark_price(inst_id="BTC-USDT-SWAP")["data"][0]["markPx"])

    # Activate 1% trailing stop once we're +2%
    if mark > entry * 1.02:
        existing = ctx.okx.get_algo_orders(ord_type="move_order_stop",
                                            inst_id="BTC-USDT-SWAP")
        if existing.get("data"):
            return  # already active
        ctx.okx.place_algo_order(
            inst_id="BTC-USDT-SWAP",
            side="sell", sz=long["pos"],
            ord_type="move_order_stop",
            order_px="-1",                     # -1 = market once triggered
            reduce_only=True,
        )
        ctx.log.info("Trailing stop activated")

Cross-instrument funding-rate arb scanner

python
def tick(ctx):
    swaps = ctx.okx.get_instruments(inst_type="SWAP")["data"]
    rates = []
    for s in swaps[:20]:
        if not s["instId"].endswith("-USDT-SWAP"):
            continue
        try:
            r = ctx.okx.get_funding_rate(s["instId"])
            rates.append((s["instId"], float(r["data"][0]["fundingRate"])))
        except Exception:
            pass
    rates.sort(key=lambda x: abs(x[1]), reverse=True)

    for inst, rate in rates[:5]:
        ctx.log.info(f"{inst:25} funding={rate*100:+.4f}%")

Reference

OKX V5 endpointSDK method
GET /api/v5/market/tickerget_ticker
GET /api/v5/market/booksget_orderbook
GET /api/v5/market/candlesget_klines
GET /api/v5/public/instrumentsget_instruments
GET /api/v5/public/funding-rateget_funding_rate
GET /api/v5/public/mark-priceget_mark_price
GET /api/v5/public/open-interestget_open_interest
GET /api/v5/account/balanceget_balance
GET /api/v5/account/positionsget_positions
GET /api/v5/account/positions-historyget_position_history
GET /api/v5/account/configget_account_config
POST /api/v5/account/set-position-modeset_position_mode
POST /api/v5/account/set-leverageset_leverage
GET /api/v5/account/max-sizeget_max_size
POST /api/v5/trade/orderplace_order
POST /api/v5/trade/cancel-ordercancel_order
POST /api/v5/trade/cancel-batch-orderscancel_all_orders
POST /api/v5/trade/amend-orderamend_order
GET /api/v5/trade/orders-pendingget_orders
GET /api/v5/trade/orders-historyget_order_history
GET /api/v5/trade/fillsget_fills
POST /api/v5/trade/close-positionclose_position
POST /api/v5/trade/order-algoplace_algo_order
POST /api/v5/trade/cancel-algoscancel_algo_order
GET /api/v5/trade/orders-algo-pendingget_algo_orders

AiSpinner Documentation