NautilusTrader
Integrations

Nightly docs

These docs track unreleased changes and may change without notice. Their code examples can use APIs that the latest release lacks, so run them with a development wheel or switch to the latest release docs.

Kraken

Kraken offers spot and derivatives trading across a wide range of digital assets. This integration connects to Kraken Pro and supports live market data and order execution for Kraken Spot and Kraken Derivatives (Futures).

Overview

The adapter is implemented in Rust with Python bindings and does not require an external Kraken client library. Each data or execution configuration selects a Spot or Futures client through its product_type.

The main Python components are:

  • KrakenDataClientConfig and KrakenExecutionClientConfig: Live client configuration.
  • KrakenDataClientFactory and KrakenExecutionClientFactory: Factories used by the trading node builder.
  • KrakenSpotHttpClient and KrakenFuturesHttpClient: Lower-level HTTP access for direct requests.

The Rust crate also exposes KrakenSpotWebSocketClient and KrakenFuturesWebSocketClient for lower-level WebSocket access.

Most users configure these components through a live trading node and do not need to work directly with the lower-level clients.

Examples

Kraken documentation

Kraken provides detailed documentation for users:

Refer to the Kraken documentation in conjunction with this NautilusTrader integration guide.

Products

The adapter supports these product categories:

Product typeSupportedNotes
Spot currency pairs✓Cash trading and margin on eligible pairs.
Spot tokenized assets✓Loaded from Kraken's tokenized_asset asset class.
Futures✓Instruments returned by the Kraken Futures API.

Kraken Futures can return instrument definitions that need more than standard-precision mode's nine decimal places. Keep high-precision mode enabled for Futures. Standard-precision mode continues to support Spot, but Futures clients fail to start or return instruments when any definition cannot be parsed. Futures catalog requests return no partial result and never round, clamp, or omit an unsupported definition.

Single product type per client: Each Kraken data or execution client is configured for a single product_type (SPOT or FUTURES); a single client does not span both markets.

Spot instrument fees

Spot instruments do not carry maker or taker fee rates. Loading instruments does not call Kraken's TradeVolume endpoint.

A Spot API key without Funds permissions - Query (Query Funds) fails when the execution client requests account state.

Bar streaming

Supported intervals

The Kraken adapter supports real-time bar (OHLC) streaming for Spot markets via WebSocket. The following intervals are available:

IntervalBarType specification
1 minute1-MINUTE-LAST
5 minutes5-MINUTE-LAST
15 minutes15-MINUTE-LAST
30 minutes30-MINUTE-LAST
1 hour1-HOUR-LAST
4 hours4-HOUR-LAST
1 day1-DAY-LAST
1 week1-WEEK-LAST
15 days15-DAY-LAST

Futures limitation: Kraken Futures does not support bar streaming via WebSocket. Use request_bars() for historical bar data instead.

Bar emission latency

Kraken's Spot WebSocket OHLC channel updates the current, incomplete bar on trade events. It does not provide a field that marks a bar as closed.

During normal streaming, the adapter buffers the current bar and emits it after receiving an update with a new interval_begin. The delay therefore depends on the first trade in the next interval and is not bounded to one bar period when a market has no trades. When the WebSocket message handler stops, the adapter flushes its buffered bars, including a current bar that may still be incomplete.

The adapter uses buffering instead of timer-based emission because:

  • Timer-based emission could miss the final update before the bar closes.
  • Kraken's updates are not guaranteed to arrive at exact interval boundaries.

This favors the latest venue update at the cost of latency.

If bar latency matters for your strategy, consider using trade tick data and aggregating bars locally with BarAggregator.

For most use cases, we recommend using INTERNAL bar aggregation (subscribing to trades and aggregating bars locally) rather than EXTERNAL exchange-provided bars:

  • Bars are emitted immediately when complete, with no buffering delay.
  • Consistent behavior across all exchanges, simplifying multi-venue strategies.

Symbology

Spot symbol normalization

Kraken uses different Bitcoin symbol conventions across their APIs:

MarketSymbol FormatExampleNotes
SpotBTCBTC/USD.KRAKENAdapter normalizes XBT to BTC at load time.
FuturesXBTPI_XBTUSD.KRAKENInstrument symbols keep Kraken's native XBT.

Kraken's REST API can return XBT for Bitcoin, while its WebSocket v2 API requires BTC. The adapter normalizes Spot symbols to BTC when loading instruments, whether XBT appears as the base currency (for example, XBT/USD to BTC/USD) or quote currency (for example, ETH/XBT to ETH/BTC). Futures instrument symbols retain Kraken's native XBT format; futures currency codes do not, and are mapped like every other code (see Currency codes).

Kraken also uses XDG for Dogecoin in some Spot responses. The adapter normalizes it to DOGE, including in quote currency symbols.

Currency codes

Kraken reports some assets under legacy codes, prefixing them with X or Z: XXBT for Bitcoin, ZEUR for the euro. The adapter maps those to the standard code used everywhere else on the platform, so instruments, balances, fees and currency configuration all agree: XXBT and XBT become BTC, XXDG and XDG become DOGE, ZEUR becomes EUR, ZUSD becomes USD.

The mapping is an explicit table rather than a prefix rule, because the prefix is not a rule. XTZ, XRP, XLM, XAUT, ZRX and ZEC legitimately begin with those letters, and a code the table does not list passes through unchanged. Kraken's own CLI normalizes the same way.

Fees are booked in the currency the venue reports, where it reports one. Futures fills carry a fee currency, which on an inverse contract is the base rather than the quote. Kraken's Spot TradesHistory reports a fee amount without a currency, so those fills are booked in the instrument's quote currency.

This changes the currency codes the adapter emits, in three places that previously disagreed with each other.

Instruments carried Kraken's codes unchanged, so stored instruments were denominated in XXBT, XETH, XXDG, ZUSD and ZEUR, and so were the fills and positions that reference them. Those become BTC, ETH, DOGE, USD and EUR.

Spot balances and the margin balance asset stripped one leading X or Z, so stored records carry XBT and XDG rather than BTC and DOGE, and the corrupted forms TZ, RX and AUT rather than XTZ, ZRX and XAUT. KFEE becomes FEE.

Futures balances used the venue's own spelling, which differs per wallet: cash and margin wallets key an asset xbt while the flex wallet keys it XBT. Both become BTC, and usd becomes USD. Because the spellings now meet under one code, an asset held in several wallets is reported as one balance whose total and locked amounts are the sum of the wallets', each wallet's locked amount bounded to its own total first and the sums then reported as they are. Free can therefore be negative when one wallet's reservation exceeds the combined holding, which is a real shortfall rather than something to clamp away. Previously each wallet produced its own entry and the account kept whichever it read last.

A cache or database written by an earlier version needs migrating or rebuilding.

Configuration follows the same mapping and accepts either spelling, so spot_positions_quote_currency="ZEUR" and "EUR" both match a euro-quoted instrument.

Money precision changes where a code now resolves to a built-in currency. ZEUR and ZUSD were unknown to the platform and were registered as 8-decimal crypto; EUR and USD are built-in fiat with 2 decimals, and JPY with none. That affects the instrument quote currency, REST fill commissions and the PnL derived from them. Account balances keep their 8-decimal precision, because the balance parsers construct their own currency from the code rather than resolving a registered one. The single exception runs the other way: the futures flex portfolioValue entry was built on the 2-decimal USD and now shares the 8-decimal balance currency, which widens it without loss.

Spot markets

NautilusTrader uses normalized, slash-separated symbols for Kraken Spot instruments. The adapter translates them to Kraken's native format internally.

Instrument ID format:

InstrumentId.from_str("BTC/USD.KRAKEN")  # Spot BTC/USD
InstrumentId.from_str("ETH/USD.KRAKEN")  # Spot ETH/USD
InstrumentId.from_str("SOL/USD.KRAKEN")  # Spot SOL/USD
InstrumentId.from_str("BTC/USDT.KRAKEN")  # Spot BTC/USDT
InstrumentId.from_str("ETH/BTC.KRAKEN")  # Spot ETH/BTC (normalized from ETH/XBT)

Futures markets

Kraken Futures instruments use a specific naming convention with prefixes:

  • PI_ - Perpetual Inverse contracts (e.g., PI_XBTUSD)
  • PF_ - Perpetual Fixed-margin contracts (e.g., PF_XBTUSD)
  • PV_ - Perpetual Vanilla contracts (e.g., PV_XRPXBT)
  • FI_ - Fixed maturity Inverse contracts (e.g., FI_XBTUSD_230929)
  • FF_ - Flex futures contracts

Instrument ID format:

InstrumentId.from_str("PI_XBTUSD.KRAKEN")  # Perpetual inverse BTC
InstrumentId.from_str("PI_ETHUSD.KRAKEN")  # Perpetual inverse ETH
InstrumentId.from_str("PF_XBTUSD.KRAKEN")  # Perpetual fixed-margin BTC

Data capability

Subscriptions (real-time)

Data typeSpotFuturesNotes
QuoteTick✓✓Spot ticker; Futures L2 book.
TradeTick✓✓
OrderBookDeltas✓✓Spot L2/L3 and Futures L2 updates.
OrderBookDepth--Use OrderBookDeltas with depth 10.
Bar✓-Spot WS OHLC channel. See bar section.
MarkPriceUpdate-✓From futures ticker feed.
IndexPriceUpdate-✓From futures ticker feed.
FundingRateUpdate-✓Perpetuals only.
InstrumentStatus--Live clients do not emit status updates.

Requests (historical)

Data typeSpotFuturesNotes
TradeTick✓✓
Bar✓✓
OrderBook (snapshot)✓✓Via HTTP depth endpoint.
FundingRateUpdate-✓Client-side start/end/limit filtering.

L3 order book (market-by-order)

Kraken exposes Spot per-order book data via the WebSocket v2 level3 channel at wss://ws-l3.kraken.com/v2. This gives venue order IDs, per-order quantities, and true incremental events (add, modify, delete). The adapter hashes each venue order ID into the u64 BookOrder.order_id field used by NautilusTrader.

Prerequisites

L3 subscriptions require Spot API credentials because Kraken's level3 channel is authenticated. Pass them to KrakenDataClientConfig:

from nautilus_trader.adapters.kraken import KrakenDataClientConfig

config = KrakenDataClientConfig(
    api_key="YOUR_KEY",
    api_secret="YOUR_SECRET",
)

Then subscribe with book_type=BookType.L3_MBO:

from nautilus_trader.model import BookType

await client.subscribe_book_deltas(
    instrument_id=instrument_id,
    book_type=BookType.L3_MBO,
    depth=1000,  # valid: 10, 100, 1000
)

Valid depths are 10, 100, and 1000. A depth of 0 uses 1000.

CRC32 checksum validation

By default, the adapter validates the CRC32 checksum on each L3 snapshot and update when Kraken provides one. On mismatch, it emits a Clear delta, clears local L3 state, refreshes the auth token, and resubscribes so Kraken sends a fresh snapshot. To disable validation for benchmarking:

config = KrakenDataClientConfig(
    api_key="...",
    api_secret="...",
    validate_l3_checksum=False,
)

Storage recommendations

OrderBookDelta already carries order_id: u64 in its Arrow schema, so L3 data is stored identically to L2 in the ParquetDataCatalog. L3 generates significantly more events per instrument than L2. Recommended settings:

  • Lower chunk size (e.g. chunk_size=50_000) for faster parallel reads.
  • Enable zstd compression in catalog config.
  • Use per-instrument path partitioning (enabled by default).

Orders capability

Order types

Order typeSpotFuturesNotes
MARKET✓✓Immediate execution at market price.
LIMIT✓✓Execution at specified price or better.
STOP_MARKET✓✓Conditional market order (stop-loss).
MARKET_IF_TOUCHED✓✓Conditional market order (take-profit).
STOP_LIMIT✓✓Conditional limit order (stop-loss-limit).
LIMIT_IF_TOUCHED✓✓Maps to take_profit with limit_price.
TRAILING_STOP_MARKET✓-Trailing stop with trailing_offset.
TRAILING_STOP_LIMIT✓-Trailing stop-limit with limit_offset.

Time in force

Time in ForceSpotFuturesNotes
GTC✓✓Good Till Canceled.
GTD✓-Good Till Date (Spot only, requires expire_time).
IOC✓✓Immediate or Cancel.
FOK✓-Spot limit orders only.

Market orders are inherently immediate and do not support time-in-force. IOC only applies to limit-type orders.

Execution instructions

InstructionSpotFuturesNotes
post_only✓✓Available for limit orders.
reduce_only✓✓Spot requires a margin account and resolved leverage.
quote_quantity✓-Spot only. Volume in quote currency (viqc); REST routed.
display_qty✓-Spot only. Iceberg orders (displayvol).

Trigger types

Conditional orders (stop, take-profit, trailing stop) support a trigger price reference on Spot:

Trigger TypeSpotFuturesNotes
LAST_PRICE✓✓Default. Last traded price.
INDEX_PRICE✓✓Broader market index price.
MARK_PRICE-✓Futures only.

The adapter rejects unsupported trigger types (e.g., BID_ASK) at submission time rather than silently coercing them.

Batch operations

OperationSpotFuturesNotes
Batch Submit✓✓Spot chunks at 15 orders. Futures chunks at 10.
Batch Modify-✓Futures HTTP method only. Execution sends one command.
Batch Cancel✓✓Auto-chunks into batches of 50.

Cancel all orders:

  • Spot selects the matching open and in-flight orders for the requested instrument and cancels them by explicit order ID, with or without a side filter, so a request never reaches another instrument. In-flight orders are included because the venue can have accepted an order the cache still records as submitted.
  • Futures uses the venue's symbol-scoped bulk cancellation when no side filter is given, and selects matching cached open and in-flight orders by explicit order ID when one is.
  • Selected IDs go through the batch-cancel endpoint and are auto-chunked into batches of 50. Kraken keys the two identifier kinds separately, so venue order IDs are sent as orders and client order IDs as cl_ord_ids; the batch limit counts both together. Each cancel keeps the owning strategy of the order it targets, and aggregate or ambiguous responses are left to reconciliation rather than producing per-order outcomes.

Position management

FeatureSpotFuturesNotes
Query positions✓✓Spot margin via OpenPositions; spot cash opt-in.
Position mode--Single position per instrument.
Leverage control✓-Spot tiers; per-order params={"leverage": N}.
Margin mode✓✓Spot/Futures cross margin; no isolated spot margin.

Order querying

FeatureSpotFuturesNotes
Query open orders✓✓List all active orders.
Query order history✓✓Historical order data with pagination.
Order status updates✓✓Real-time order state changes via WebSocket.
Trade history✓✓Execution and fill reports.

Contingent orders

FeatureSpotFuturesNotes
Linked order lists--Submitted lists contain independent orders.
OCO orders--Not supported.
Bracket orders--Not supported.
Conditional orders✓✓Stop and take-profit orders.

Maker Protection (Futures)

Kraken Futures applies Maker Protection on selected markets: placements and edits that could take liquidity are held for the market's configured window before reaching the matching engine. The classification is by order type, so any order not marked post_only is held even when it would in fact have rested. Post-only placements and all cancellations are never held, and no held-order state is exposed on any API. The venue applies the hold per market to every client; the adapter decodes the per-market window (makerProtectionMillis) on the raw venue instrument model and exposes no configuration for it.

Order-state handling accounts for the held-order semantics:

  • A cancel acknowledged while an order is held is not terminal. The order is released as IOC and can still fill. Fills and terminal states are driven by venue order updates, never by the cancel acknowledgement itself.
  • An order that cannot trade after such a release is reported with the venue status iocWouldNotExecute on REST (IOC_WOULD_ENTER_BOOK on market data), which the adapter treats as a terminal rejection. On the order-update feed the same outcome arrives as a terminal cancellation whose venue reason the adapter preserves.
  • A released order cancels a resting order of the same account it would match, overriding the configured self-trade strategy. The resting order is reported canceled with reason CANCELLED_BY_SELF_TRADE.

The adapter closes an order only once the venue's fills for it are accounted.

Order-update feed

A removal with is_cancel=true and reason partial_fill discards the remainder and is terminal (a converted hold, or any IOC-style order). The delta carries the venue's cumulative filled.

  • For a tracked order, the adapter closes from the feed once the fills stream has accounted that quantity. A fill still in flight is never orphaned, and a tracked order is not left open after its fills are accounted.
  • For a removal it cannot match, the adapter skips and converges through reconciliation.
Unmatched removalReason
Cancel-only messageCarries no cumulative filled.
No resolvable client order IDCannot match a tracked order.

Reconciliation

A held order never reaches the book, so it is absent from /openorders. Mass status, open-only report runs, and targeted single-order queries consult POST /orders/status before treating the order as missing. That window reports orders that are open or were filled or canceled in the last 5 seconds.

A hold that fills after a cancel acknowledgement reconciles to its true terminal state with the venue's cumulative filled, not a premature cancellation.

Order routing (Spot)

The Spot execution client routes order submission, modification, cancellation, and batch cancellation through Kraken's authenticated WebSocket v2 trade channel by default. It falls back to REST when the WebSocket is inactive. Set use_ws_trade=False on KrakenExecutionClientConfig to route these operations through REST.

Order shapes routed via REST

Kraken's Spot WebSocket v2 add_order method supports these shapes, but the adapter routes them through REST:

ShapeAdapter behavior
FOK time in forceThe WebSocket parameter builder does not encode FOK.
Trailing stop / stop-limitThe WebSocket parameter builder does not encode trailing offsets.
Iceberg (display_qty)The WebSocket parameter builder does not encode iceberg orders.
Quote-quantity ordersWS supports non-margin buy market orders; the adapter uses REST.

Mixed-symbol order lists also use REST because Kraken's WebSocket batch_add request requires one shared symbol. Unsupported trigger references fall back to the REST path, which rejects them locally before sending a request to Kraken.

The per-call params={"use_ws_trade": False} override forces a single command through REST regardless of the configured default. Set it on SubmitOrder, ModifyOrder, CancelOrder, SubmitOrderList, or BatchCancelOrders.

WebSocket request timeout

When a WebSocket round-trip exceeds ws_request_timeout_secs (default 5), the venue outcome remains unknown. Submit, modify, cancel, and batch-add requests remain in flight without a terminal rejection. The dispatcher retains the request ID so a delayed matching response can still apply the normal success or definitive rejection handling.

Submit and batch-add timeouts also send a best-effort compensating cancel over the same WebSocket for every affected client order ID. This cancel limits exposure if Kraken accepted the order but delayed its response. It does not replace the unknown outcome with local terminal state.

Stream updates and the live execution reconciliation engine resolve orders when no matching response arrives. Targeted status queries can resolve modify or cancel requests that already have a venue order ID. A matching response or execution client shutdown retires the retained request correlation.

Set ws_request_timeout_secs comfortably above your observed round-trip latency. A premature timeout can send a compensating cancel for a submit or batch add that Kraken accepted.

WebSocket order-routing options

KrakenExecutionClientConfig exposes:

OptionDefaultDescription
use_ws_tradeTrueRoute orders via WS when the trade channel is active.
ws_request_timeout_secs5Seconds to wait for a Spot WS order response.

Reconciliation

The Kraken adapter provides reconciliation capabilities for both Spot and Futures markets, allowing traders to synchronize their local state with the exchange state at startup or during operation.

Bounded reports

When reconciliation supplies a lookback, both execution clients derive a single cutoff and apply it to every historical query, then record it on the mass status through set_report_window. Using one cutoff avoids a report set that never existed at the venue, which a moving cutoff can produce.

Declaring the cutoff is what lets the engine apply its bounded-history rules; the completeness flag described below qualifies that set rather than gating it.

Order and fill records contribute to the completeness flag: the set is incomplete when a record's instrument could not be resolved, or when a record could not be parsed. Position records do not currently contribute, and the futures position read still drops an unresolved symbol silently.

Spot closed-order and fill reads page through an offset until the venue returns an empty page, and stop after 500 pages. A read cut short by that cap logs a warning, and how it surfaces depends on the caller. Startup mass status carries the completeness of the order and fill reads in its report window, so the engine sees the set as incomplete. generate_order_status_reports and generate_fill_reports return the records read up to the cap and do not expose a completeness flag.

Spot reconciliation

Order status reports:

  • Open orders: Fetches all currently active orders.
  • Closed orders: Fetches historical orders with pagination support.
  • Time-bounded queries: Supports filtering by start/end timestamps.
  • Startup mass status reads closed orders alongside open ones, so an order that reached a terminal state while the node was down is reconciled. The reconciliation lookback bounds the read, and a closed-order read cut short by the page cap leaves the mass status incomplete.

Fill reports:

  • Trade history: Fetches execution history with pagination.
  • Time-bounded queries: Supports filtering by start/end timestamps.
  • All fill types: Market, limit, and conditional order fills.

Pair spelling:

  • Kraken spells a pair two ways: the AssetPairs key (XXBTZEUR), used as the instrument raw_symbol, and the altname (XBTEUR). OpenPositions returns the key, while OpenOrders and TradesHistory return the altname.
  • The adapter resolves both spellings, so an order or fill on a legacy-named pair is reported.
  • A read scoped to one instrument resolves each row and compares instrument IDs, rather than comparing a cached raw_symbol against the venue's spelling, so a scoped read returns that pair's own records whichever way Kraken spells it.
  • A read scoped to an instrument the client does not hold returns nothing. Spot and futures IDs share the KRAKEN venue, so a futures ID can reach the spot client and the reverse; neither falls back to returning every instrument's records.
  • A spot instrument whose altname differs from its AssetPairs key carries the altname in its info map, so a client whose instruments arrive through cache_instrument or cache_instruments resolves altname-spelled records without refetching AssetPairs.
  • On an unscoped read, an open order whose pair cannot be resolved to a cached instrument fails the read, rather than being omitted from an otherwise successful one. A scoped read skips a record it cannot resolve, since it cannot belong to the requested instrument.
  • A closed order or fill that cannot be resolved is logged as a warning and skipped, preserving the records that do resolve. Historical records routinely outlive the loaded instrument set.

Account balances:

  • Wallet balances: Fetched from POST /0/private/BalanceEx, which reports both the total and the held (hold_trade) amount per asset. The held amount populates AccountBalance.locked, so free excludes funds Kraken has reserved against resting orders. For accounts with a credit line, net credit (credit - credit_used) is included in AccountBalance.total, so free matches Kraken's available balance of balance + credit - credit_used - hold_trade.
  • Zero balances: An asset Kraken lists at zero is reported at zero rather than omitted, on both spot and futures. The engine only ever inserts balances, so a currency left out of a snapshot keeps its previous value. On futures the zero joins the per-currency sum, so a funded wallet alongside an empty one of the same asset reports the funded amount. An asset Kraken drops from the response entirely still keeps its last reported value.

Margin position reports (when spot_account_type=Margin):

  • Open positions: Fetched from POST /0/private/OpenPositions and aggregated by pair into PositionStatusReport entries. Kraken returns one entry per lot, so opposing lots for the same pair net into a single report.
  • Entry average: Each report carries avg_px_open, derived from the lot cost and vol fields and weighted by the volume still open. Long and short lots are averaged separately, so the reported average describes the side that survives netting. Reconciliation needs this value to open a position from a report when the cache holds no order or fill history for it.
  • The average is marked AvgPxReconciliation::OpeningOnly, because Kraken closes margin lots FIFO and drops a fully closed one from OpenPositions. After a partial close the average therefore describes the lots that remain open rather than the opening fills, and would not match a netting position's average. Reconciliation uses it to open a position from flat and never compares it. Futures keeps the default, since that endpoint reports one netted position whose price Kraken documents as the average entry price.
  • No synthetic FLAT cleanup: OpenPositions reports leveraged positions only, so an unleveraged spot holding never appears there and its absence is not evidence that the position is closed. The bulk read reports only what the venue returns.
  • Margin balances: POST /0/private/TradeBalance is called alongside the account-state refresh; used margin populates MarginBalance.initial, while equity and free margin populate the summary balance (see Spot margin trading).

A leveraged position closed while the node was down is not recovered from its closing fill when reconciliation_lookback_mins is set. A fully closed lot is absent from OpenPositions, so the instrument carries no position report, and the engine projects that order's fill as order-only: the order reaches FILLED, while the cached position keeps both its quantity and its realized PnL, so the closing PnL is never recorded. This is the shared engine's documented behavior for an instrument with no in-scope position report, not a Kraken rule. See Order-only fill projection. Removing the synthetic FLAT is what exposes Kraken spot margin to it, because the sweep previously supplied an explicit FLAT.

A periodic position check does not recover it either, since margin mode declares no bulk position coverage, and that skip is logged at debug level. The condition also persists across restarts: the closing order is then cached as FILLED and matches the venue exactly, so reconciliation treats it as already in sync.

Leaving reconciliation_lookback_mins unset avoids the projection but is not a general remedy. The closing order is external to the cache, so it is attributed to the EXTERNAL strategy and keys a netting position by instrument and strategy. Unless the cached position is itself EXTERNAL-owned or the instrument is claimed through external_order_claim, the recovered fill opens a second, opposite position rather than closing the cached one: net exposure reaches zero, but the stale position and its realized PnL remain.

Until this is addressed, reconcile a margin position closed during downtime manually, or run spot_account_type=Cash with use_spot_position_reports=True, where the wallet read enumerates every holding it covers and an absent report is genuine evidence of flat.

Futures reconciliation

Order status reports:

  • Open orders: Fetches all currently active futures orders.
  • Historical orders: Fetches closed and filled orders when open_only=False.
  • Order events: Full order lifecycle history via /api/history/v2/orders endpoint.

Fill reports:

  • Fill history: Fetches all execution reports.
  • Time filtering: Client-side filtering by start/end timestamps (parses RFC3339 timestamps).
  • All fill types: Maker and taker fills with fee information.

Position status reports:

  • Open positions: Fetches all active futures positions.
  • Real-time data: Includes unrealized funding, average price, and position size.

Futures time filtering: The Kraken Futures fills endpoint does not support server-side time range filtering. The adapter implements client-side filtering by parsing fillTime fields and comparing against requested start/end timestamps.

Spot position reports (cash mode)

In cash mode, the Kraken adapter can optionally report wallet balances as position status reports for spot instruments. This feature is disabled by default and must be explicitly enabled via configuration. Margin-mode accounts should leave it disabled and rely on OpenPositions instead (see Spot margin trading).

How it works:

  • When enabled, wallet balances are converted to PositionStatusReport objects.
  • Positive balances are reported as LONG positions.
  • Only instruments matching the configured quote currency are reported (default: USDT). The same filter decides which instruments the client declares bulk position coverage for, so an instrument quoted in anything else is never reconciled to flat from a missing report.
  • This prevents duplicate reports when the same asset is available with multiple quote currencies (e.g., BTC/USD, BTC/USDT, BTC/EUR).

Configuration:

from nautilus_trader.adapters.kraken import KrakenExecutionClientConfig
from nautilus_trader.model import AccountId


exec_config = KrakenExecutionClientConfig(
    account_id=AccountId.from_str("KRAKEN-001"),
    api_key="YOUR_API_KEY",
    api_secret="YOUR_API_SECRET",
    use_spot_position_reports=True,
    spot_positions_quote_currency="USDT",  # Default
)

Use with caution: Enabling spot position reports may lead to unintended behavior if your strategy is not designed to handle spot positions. For example, a strategy that expects to close positions may attempt to sell your wallet holdings.

Spot margin trading

Kraken Spot supports leveraged trading on selected pairs. Per-pair availability and the valid leverage tiers are advertised by Kraken on the instruments endpoint as AssetPairInfo.leverage_buy and leverage_sell; the adapter caches these at instrument-load time and validates the requested tier before order submission. Margin trading is enabled per-execution-client via spot_account_type, with per-order leverage params.

Configuration

from nautilus_trader.adapters.kraken import KrakenExecutionClientConfig
from nautilus_trader.model import AccountId
from nautilus_trader.model import AccountType


exec_config = KrakenExecutionClientConfig(
    account_id=AccountId.from_str("KRAKEN-001"),
    api_key="YOUR_API_KEY",
    api_secret="YOUR_API_SECRET",
    spot_account_type=AccountType.MARGIN,
    default_leverage=3,  # Optional config-level default
    margin_balance_asset="ZGBP",  # Optional summary-display asset
)

margin_balance_asset controls only the denomination of the account-summary metrics returned by Kraken's TradeBalance endpoint (equity, free margin, used margin, etc.). Per-position figures from OpenPositions are always in the traded pair's quote currency.

Per-order leverage

Override the configured default on a single order via params:

order = strategy.order_factory.limit(
    instrument_id=BTC_USD,
    order_side=OrderSide.BUY,
    quantity=Quantity.from_str("0.01"),
    price=Price.from_str("50000.00"),
    params={"leverage": 5},
)

The adapter validates the requested tier against AssetPairInfo.leverage_buy / leverage_sell for the pair before submitting; an invalid tier produces an OrderDenied event and never hits the venue.

Reduce-only

Margin orders can carry reduce_only=True so they reduce an existing position without opening a larger opposite position. Set spot_account_type=Margin and supply either default_leverage or per-order params={"leverage": N}. The adapter denies cash orders with reduce_only before sending them to Kraken.

Account state

When spot_account_type=Margin, the execution client calls Kraken's TradeBalance endpoint during account refreshes. The live account state uses:

  • Equity (e) and free margin (mf) for the balance denominated by margin_balance_asset.
  • Used margin (m) for MarginBalance.initial. Maintenance margin is zero because Kraken does not return a separate maintenance-margin amount.

The lower-level KrakenSpotHttpClient methods request_margin_metrics() and request_account_state_with_metrics() return the full TradeBalance metrics dictionary for direct consumers. The live execution client does not attach that dictionary to AccountState.info.

Position reconciliation

Open spot margin positions are surfaced via POST /0/private/OpenPositions on each position_check_interval_secs tick. This path is independent of use_spot_position_reports (which is wallet-derived, cash-mode-only).

The spot client declares bulk position coverage per instrument, and only for instruments the read would actually enumerate: cash mode with use_spot_position_reports=True, and the instrument quoted in spot_positions_quote_currency (see Spot position reports, which applies the same filter). Under spot_account_type=Margin the source is OpenPositions, which omits unleveraged lots, and cash mode without wallet-derived reports returns nothing at all. Wherever coverage is not declared, an absent report leaves the cached position untouched instead of closing it.

Funding rates

The adapter receives funding rate data from the Futures ticker WebSocket feed, which provides relative_funding_rate and next_funding_rate_time for perpetual futures.

The interval field on FundingRateUpdate is None for Kraken because the ticker feed does not include a funding interval field and the Kraken API documentation does not specify a fixed funding period.

Rate limiting

Each Kraken HTTP client applies an adapter-side request throttle. The default is five requests per second and max_requests_per_second can override it. This is a request-count throttle, not a complete model of Kraken's endpoint costs or account-tier budgets.

Kraken applies different venue limits to Spot and Futures:

  • Spot REST rate limits use a tier-dependent call counter. Ledger and trade history calls add 2, most other REST calls add 1, and order management uses a separate trading limiter.
  • Derivatives rate limits use endpoint costs and separate budgets for /derivatives and /history paths.

The current Spot REST call-counter limits are:

Spot tierMaximum counterCounter decay
Starter150.33/second
Intermediate200.5/second
Pro201/second

If the adapter's fixed request rate is too high for the endpoint mix and account tier, Kraken can still reject or throttle requests.

Reconciliation interval guidance

The execution engine's open_check_interval_secs and position_check_interval_secs settings create sustained private REST API load. Short intervals can exhaust Kraken's venue budgets even when the adapter stays below its configured requests-per-second throttle.

Use conservative intervals as a starting point, especially for a Spot Starter account:

exec_engine = LiveExecutionEngineConfig(
    reconciliation=True,
    open_check_interval_secs=30.0,  # Conservative Spot Starter-tier starting point
    position_check_interval_secs=120.0,
)

Tune these values for the account tier, enabled reconciliation checks, and other clients using the same API key. If Kraken returns EAPI:Rate limit exceeded, increase the intervals or reduce max_requests_per_second.

Configuration

The product type for each client is specified via the product_type option.

Data client configuration options

OptionDefaultDescription
product_typeSPOTProduct type for this client (SPOT or FUTURES).
environmentLIVETrading environment (LIVE or DEMO); demo only for Futures.
api_keyNoneAPI key for Spot L3 data.
api_secretNoneAPI secret for Spot L3 data.
base_urlNoneOverride for the Kraken REST base URL.
ws_public_urlNoneOverride for the public WebSocket URL.
ws_private_urlNoneOverride for the private WebSocket URL.
ws_l3_urlNoneOverride for the Spot L3 WebSocket URL.
validate_l3_checksumTrueValidate Kraken Spot L3 checksums and resync on mismatch.
proxy_urlNoneOptional proxy URL for HTTP and WebSocket transports.
timeout_secs30HTTP request timeout in seconds.
heartbeat_interval_secs30WebSocket heartbeat interval in seconds.
ws_idle_timeout_ms10,000Data-silence timeout for the Spot v2 WebSocket; 0 disables.
max_requests_per_secondNonePer-client request throttle; default is 5 req/s.
transport_backendSockudoWebSocket transport backend.

Execution client configuration options

OptionDefaultDescription
account_idrequiredAccount ID for the Kraken account.
api_keyrequiredKraken API key.
api_secretrequiredKraken API secret.
product_typeSPOTProduct type for this client (SPOT or FUTURES).
environmentLIVETrading environment (LIVE or DEMO); demo only for Futures.
base_urlNoneOverride for the Kraken REST base URL.
ws_urlNoneOverride for the Kraken WebSocket URL.
proxy_urlNoneOptional proxy URL for HTTP and WebSocket transports.
timeout_secs30HTTP request timeout in seconds.
heartbeat_interval_secs30WebSocket heartbeat interval in seconds.
auth_timeout_secsNoneFutures WebSocket auth timeout; None uses the client default.
max_requests_per_secondNonePer-client request throttle; default is 5 req/s.
max_retries3Maximum retry attempts for retryable REST requests.
spot_account_typeCASHAccount type for spot trading; MARGIN enables leverage and reports.
default_leverageNoneDefault spot margin leverage sent as "N:1" when set.
use_spot_position_reportsFalseReport wallet balances as positions; cash mode only.
spot_positions_quote_currency"USDT"Quote filter for spot wallet position reports and their coverage.
margin_balance_assetNoneSummary asset for TradeBalance; None defaults to ZUSD.
use_ws_tradeTrueUse Spot WebSocket v2 for order operations when active.
ws_request_timeout_secs5Spot WebSocket order response timeout.
transport_backendSockudoWebSocket transport backend.

For spot margin, default_leverage applies when an order has no per-order leverage param. margin_balance_asset only changes the TradeBalance summary denomination; per-position figures remain in the pair's quote currency.

Demo environment setup

To test with Kraken Futures demo (paper trading):

  1. Sign up at Kraken Futures demo and generate API credentials.
  2. Set environment variables with your demo credentials:
    • KRAKEN_FUTURES_DEMO_API_KEY
    • KRAKEN_FUTURES_DEMO_API_SECRET
  3. Read the credentials and pass them to KrakenExecutionClientConfig, then set environment=KrakenEnvironment.DEMO and product_type=KrakenProductType.FUTURES.

The Python examples show the complete demo and live LiveNode configurations.

Production configuration

Use KrakenDataClientConfig with KrakenDataClientFactory, and use KrakenExecutionClientConfig with KrakenExecutionClientFactory. The Python examples show the complete LiveNode.builder(...) configuration for data and execution clients.

API credentials

Live-node configuration objects do not read credential environment variables automatically. Pass api_key and api_secret explicitly to KrakenExecutionClientConfig and, for Spot L3 data, to KrakenDataClientConfig. Public market data does not require credentials.

The lower-level Python HTTP and WebSocket clients load the following variables when their credential arguments are omitted. Rust applications can use KrakenCredential::from_env_spot() or KrakenCredential::from_env_futures(demo) to load them before constructing live-node configs.

Environment VariableDescription
KRAKEN_SPOT_API_KEYAPI key for Kraken Spot live trading.
KRAKEN_SPOT_API_SECRETAPI secret for Kraken Spot live trading.
KRAKEN_FUTURES_API_KEYKraken Futures live API key.
KRAKEN_FUTURES_API_SECRETKraken Futures live API secret.
KRAKEN_FUTURES_DEMO_API_KEYAPI key for Kraken Futures (demo).
KRAKEN_FUTURES_DEMO_API_SECRETAPI secret for Kraken Futures (demo).

Demo environment: Only Kraken Futures offers a demo environment (https://demo-futures.kraken.com) for testing without real funds. Kraken Spot does not have a demo or testnet environment.

Use environment variables to store credentials, then pass their values into live-node configuration at the application boundary.

Authentication errors are reported when a private client connects or performs a private operation. Required permissions depend on the requested data or trading operation.

Contributing

For additional features or to contribute to the Kraken adapter, please see our contributing guide.

On this page