Skip to content

Kraken SDK

Complete reference for ctx.kraken — programmatic spot and margin trading on Kraken from worker code.

Kraken REST + WebSocket v2

This SDK wraps the Kraken REST API with optional WebSocket v2 acceleration. WS-first methods fall back to REST automatically; REST-only methods always work.

Setup

  1. Add a Kraken trading block to your workspace canvas.
  2. Open the inspector → API Keys → pick a key (Settings → API Keys → Kraken to add new).
  3. Connect the block to your Worker block via an edge.
  4. ctx.kraken is now available.
python
def tick(ctx):
    t = ctx.kraken.get_ticker("XBTUSD")
    ctx.log.info(f"BTC: {t}")

If no Kraken block is connected:

RuntimeError: No trading block connected. Connect a Kraken block to this worker.

Pairs

Kraken uses its own pair codes — sometimes the same as the common ticker, sometimes prefixed with X/Z (asset class). Examples:

CommonKraken pair
BTC/USDXBTUSD
ETH/USDETHUSD
BTC/EURXBTEUR
SOL/USDSOLUSD
Margin BTC/USDXBT/USD

Use get_asset_pairs to discover the canonical pair name for any market, plus its tick size, lot size, and trading status.

USD vs ZUSD

Kraken's "Z" prefix marks fiat assets (ZUSD, ZEUR). For account-level methods (get_trade_balance, get_ledgers) you typically pass ZUSD; for trading you use plain USD-suffix pair codes.

Market Data

get_ticker

Latest ticker for a pair.

python
ctx.kraken.get_ticker(pair: str = "XBTUSD") -> dict

Returns: {"XXBTZUSD": {"a": [ask, w_lot, lot], "b": [bid, w_lot, lot], "c": [last_price, last_lot], "v": [vol_today, vol_24h], "p": [vwap_today, vwap_24h], "t": [trades_today, trades_24h], "l": [low_today, low_24h], "h": [high_today, high_24h], "o": open_today}}

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.kraken.get_orderbook(pair: str = "XBTUSD") -> dict

get_ohlc

OHLCV candles.

python
ctx.kraken.get_ohlc(pair: str = "XBTUSD", interval: int = 1) -> dict
interval (minutes)Description
1, 5, 15, 30Intra-day
60, 240Hourly / 4h
1440Daily
10080, 21600Weekly / 15-day

get_recent_trades

Recent public trades for a pair.

python
ctx.kraken.get_recent_trades(pair: str = "XBTUSD", since: int = None) -> dict

get_spread

Recent bid/ask spreads — useful for liquidity profiling.

python
ctx.kraken.get_spread(pair: str = "XBTUSD", since: int = None) -> dict

get_asset_pairs

Tradable pair info: pair_decimals, lot_decimals, tick_size, ordermin, costmin, status.

python
ctx.kraken.get_asset_pairs(pair: str = None) -> dict

Adapter caches this after first call — pair metadata rarely changes.

get_trades

Get recent trades from the WebSocket stream (PRO/MAX only).

python
ctx.kraken.get_trades(pair: str = "BTC/USD") -> dict

get_system_status

Kraken-wide trading status.

python
ctx.kraken.get_system_status() -> dict
# Returns: {"status": "online" | "maintenance" | "cancel_only" | "post_only", "timestamp": ...}
python
def tick(ctx):
    s = ctx.kraken.get_system_status()
    if s.get("status") != "online":
        ctx.log.warn(f"Kraken {s.get('status')} — pausing")
        return
    # ... trade

Account & Wallet

get_balance

Account balance per currency.

python
ctx.kraken.get_balance() -> dict
# {"ZUSD": "1234.56", "XXBT": "0.5", ...}

WebSocket cache

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

get_trade_balance

Margin info: equity, P&L, margin, free margin, margin level.

python
ctx.kraken.get_trade_balance(asset: str = "ZUSD") -> dict

Returns: {"eb", "tb", "m", "n", "c", "v", "e", "mf", "ml"} (equity balance, trade balance, margin, unrealized P&L, cost basis, valuation, equity, free margin, margin level).

get_positions

Open margin positions.

python
ctx.kraken.get_positions() -> dict

WebSocket cache

PRO/MAX: cached at 0ms.

get_ledgers

Account ledger — every deposit, withdrawal, trade, fee, transfer, settlement.

python
ctx.kraken.get_ledgers(
    asset: str = None,
    ledger_type: str = "all",     # "all" | "deposit" | "withdrawal" | "trade" | "margin"
    start: int = None,
    end: int = None,
) -> dict

Orders

place_order

Place an order. Supports market, limit, stop-loss, take-profit, and stop-loss-limit.

python
ctx.kraken.place_order(
    pair: str,
    side: str,                  # "buy" | "sell"
    volume: float,
    ordertype: str = "market",  # "market" | "limit" | "stop-loss" | "take-profit" | "stop-loss-limit" | …
    price: float = None,
    leverage: float = None,     # None = spot; 2-5 for margin
    reduce_only: bool = False,
    time_in_force: str = None,  # "GTC" | "IOC" | "GTD"
    post_only: bool = False,
    cl_ord_id: str = None,
) -> dict
python
# Spot market buy
r = ctx.kraken.place_order("XBTUSD", "buy", 0.001, "market")

# 3x margin long
r = ctx.kraken.place_order("XBTUSD", "buy", 0.01, "limit",
                            price=65000, leverage=3)

WS-accelerated

In Server mode, orders route through Kraken's V2 WebSocket for ~10× faster acks than REST.

edit_order

Modify an unfilled order (volume / price). Keeps queue priority on the original timestamp.

python
ctx.kraken.edit_order(
    order_id: str,
    pair: str,
    volume: float = None,
    price: float = None,
    post_only: bool = None,
) -> dict

cancel_order

Cancel a single order by txid.

python
ctx.kraken.cancel_order(order_id: str) -> dict

cancel_all_orders

Cancel ALL open orders (account-wide). Kill switch.

python
ctx.kraken.cancel_all_orders() -> dict

batch_add

Place up to 15 orders atomically.

python
ctx.kraken.batch_add(orders: list, pair: str, validate: bool = False) -> dict
python
ctx.kraken.batch_add(
    pair="XBTUSD",
    orders=[
        {"ordertype": "limit", "type": "buy",  "volume": "0.001", "price": "60000"},
        {"ordertype": "limit", "type": "buy",  "volume": "0.001", "price": "59000"},
        {"ordertype": "limit", "type": "buy",  "volume": "0.001", "price": "58000"},
    ],
)

batch_cancel

Cancel multiple orders by txid.

python
ctx.kraken.batch_cancel(order_ids: list) -> dict

get_orders

Active (open) orders.

python
ctx.kraken.get_orders() -> dict

WebSocket cache

PRO/MAX: cached at 0ms.

query_orders

Detail of one or more specific orders by txid.

python
ctx.kraken.query_orders(txids, trades: bool = False) -> dict
python
detail = ctx.kraken.query_orders("OQCLML-BW3P3-BUCMWZ", trades=True)

get_closed_orders

Closed (filled / cancelled / expired) orders.

python
ctx.kraken.get_closed_orders() -> dict

get_trades_history

Trade fills with fees (the actual transactions, not just orders).

python
ctx.kraken.get_trades_history(
    trade_type: str = "all",       # "all" | "any position" | "closed position" | "closing position" | "no position"
    start: int = None,
    end: int = None,
) -> dict

Common Patterns

Error handling

python
def tick(ctx):
    try:
        balance = ctx.kraken.get_balance()
    except Exception as e:
        ctx.log.error(f"Kraken unreachable: {e}")
        return

KrakenAPIError (extends ExchangeAPIError) wraps the array of strings Kraken returns in error[]. Network failures raise httpx.HTTPStatusError.

Cloud-Run proxy

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

WebSocket-first

Almost every method has a WebSocket fast-path on PRO+:

MethodWS pathREST fallback
get_ticker, get_orderbook, get_tradespublic stream cacheyes
get_balance, get_positions, get_ordersprivate stream cacheyes
place_order, cancel_order, edit_orderWS v2 add/cancel/amendyes
cancel_all_orders, batch_add, batch_cancelWS v2 batch opsyes (Phase 5)

The adapter probes _ws_client per call — when WS is connected and authenticated, it routes through; otherwise REST.

System-status guard

Kraken regularly enters cancel_only or post_only modes during volatility. Always check before placing market orders:

python
def tick(ctx):
    if ctx.kraken.get_system_status().get("status") != "online":
        return
    # safe to trade

Recipes

DCA on hourly close (with status guard)

python
def setup(ctx):
    ctx.state.set("last_buy_ts", 0)

def tick(ctx):
    import time
    now = int(time.time())
    if now - ctx.state.get("last_buy_ts", 0) < 3600:
        return

    if ctx.kraken.get_system_status().get("status") != "online":
        ctx.log.warn("Kraken not online, deferring buy")
        return

    px = float(ctx.kraken.get_ticker("XBTUSD")["XXBTZUSD"]["c"][0])
    qty = round(50 / px, 5)  # $50 worth

    r = ctx.kraken.place_order("XBTUSD", "buy", qty, "market")
    ctx.state.set("last_buy_ts", now)
    ctx.log.info(f"DCA: {qty} BTC @ {px}{r}")

Layered grid with batch placement

python
def setup(ctx):
    # Always cancel any leftovers from a previous run
    ctx.kraken.cancel_all_orders()

    px = float(ctx.kraken.get_ticker("XBTUSD")["XXBTZUSD"]["c"][0])
    step = px * 0.005

    orders = []
    for i in range(1, 6):
        orders.append({
            "ordertype": "limit", "type": "buy",
            "volume": "0.001",
            "price": str(round(px - i * step, 1)),
        })
        orders.append({
            "ordertype": "limit", "type": "sell",
            "volume": "0.001",
            "price": str(round(px + i * step, 1)),
        })
    ctx.kraken.batch_add(orders, pair="XBTUSD")
    ctx.state.set("grid_centre", px)
    ctx.log.info(f"Grid placed around ${px:.0f}")

Spread-aware market making

python
def tick(ctx):
    spreads = ctx.kraken.get_spread("XBTUSD")["XXBTZUSD"]
    if not spreads:
        return
    bid, ask, _ = spreads[-1]   # last record: [bid, ask, ts]
    spread_bps = (float(ask) - float(bid)) / float(bid) * 10000

    if spread_bps > 5:
        ctx.log.info(f"Spread {spread_bps:.1f} bps > target — quoting inside")
        # ... place limit orders inside the spread
    else:
        ctx.log.info(f"Spread tight ({spread_bps:.1f} bps) — staying out")

Reference

Kraken endpointSDK method
GET /0/public/Tickerget_ticker
GET /0/public/Depthget_orderbook
GET /0/public/OHLCget_ohlc
GET /0/public/Tradesget_recent_trades
GET /0/public/Spreadget_spread
GET /0/public/AssetPairsget_asset_pairs
GET /0/public/SystemStatusget_system_status
POST /0/private/Balanceget_balance
POST /0/private/TradeBalanceget_trade_balance
POST /0/private/OpenPositionsget_positions
POST /0/private/Ledgersget_ledgers
POST /0/private/AddOrderplace_order
POST /0/private/EditOrderedit_order
POST /0/private/CancelOrdercancel_order
POST /0/private/CancelAllcancel_all_orders
POST /0/private/AddOrderBatchbatch_add
POST /0/private/CancelOrderBatchbatch_cancel
POST /0/private/OpenOrdersget_orders
POST /0/private/QueryOrdersquery_orders
POST /0/private/ClosedOrdersget_closed_orders
POST /0/private/TradesHistoryget_trades_history

AiSpinner Documentation