v1.226.0
open-mmlab/Amphionv1.226.0Apr 29, 2026by github-actions[bot]
AI Summary
A major beta release introducing new portfolio tracking queries, expanded exchange support (Coinbase, Interactive Brokers Rust), and a significant migration of the Polymarket adapter to CLOB V2.
Key Highlights
- New portfolio queries (`mark_values`, `equity`, `missing_price_instruments`) for Rust and Python
- Major Polymarket adapter migration to CLOB V2 (new EIP-712 domain, pUSD collateral)
- New Coinbase initial integration adapter and Interactive Brokers Rust adapter with PyO3
- Enhanced WebSocket transport support with `sockudo` feature and proxy tunneling
- Added ADL/liquidation detection logging across major venues (Binance, Bybit, etc.)
Breaking Changes
- Portfolio queries now require `Option<&AccountId>`
- WebSocketConfig now requires `backend` and `proxy_url` fields
- Polymarket adapter migrated to CLOB V2 (breaking contract logic)
- Multiple config constructors (`new`) removed in favor of `builder()` pattern
- Ax adapters replaced `is_sandbox` with `environment` enum
- MarginAccount `margins_init`/`margins_maint` changed to per-instrument only
New Features
- Added `instrument_status` cache queries and auto-caching
- Added `calculate_commission` to `ExecutionClient`
- Added Betfair tiered tick scheme for `BettingInstrument`
- Added Binance Futures `use_trade_lite` config
- Added Hyperliquid `OrderBookDepth10` subscription
- Added Kraken xStocks tokenized asset support
- Added OKX option greeks support
- Added Polymarket batch `SubmitOrderList`
- Added `compression` config for Tardis Machine replay
Full Release Notes
# NautilusTrader 1.226.0 Beta
Released on 29th April 2026 (UTC).
### Enhancements
- Added `Portfolio::mark_values`, `equity`, and `missing_price_instruments` queries for Rust and Python
- Added `instrument_status` / `instrument_statuses` cache queries and auto-caching in the data engine (#3858)
- Added `environment` enum config for BitMEX, Deribit, dYdX, Hyperliquid, and OKX adapters
- Added `BybitEnvironment` to `BybitDataClientConfig` and `BybitExecClientConfig`
- Added missing config values to `LiveExecEngineConfig` (#3841), thanks @Javdu10
- Added `calculate_commission` to `ExecutionClient` for venue-specific reconciliation fills
- Added PyO3 bindings for `DataEngineConfig`, `ExecutionEngineConfig`, and `OrderEmulatorConfig` so they can be constructed from Python
- Added `cache`, `msgbus`, `data_engine`, `exec_engine`, and `portfolio` keyword arguments to `BacktestEngineConfig` Python constructor
- Added `MarginAccount.margin_for_currency` + `margin_init/maint_for_currency` helpers for cross-margin queries
- Added `MarginAccount.total_margin_init(currency)` / `total_margin_maint(currency)` summing both margin buckets
- Added `MarginAccount.account_margins`, `account_margins_init/maint`, and `clear_account_margin` accessors
- Added `transport-sockudo` feature with `TransportBackend` runtime selector for the WebSocket transport (Rust)
- Added `TransportBackend` PyO3 enum and `WebSocketConfig.backend` kwarg for backend selection from Python
- Added custom upgrade-header support on the sockudo backend so adapters carry the same `User-Agent` and per-venue headers on both backends (#3932), thanks @sunlei
- Added `WebSocketConfig.proxy_url` for HTTP `CONNECT` proxy tunneling with basic-auth support
- Added Betfair tiered tick scheme to `BettingInstrument` for ladder-snapped pricing
- Added Binance Futures `use_trade_lite` config to opt into low-latency `TRADE_LITE` fills (Rust, default `False`)
- Added Binance `proxy_url` plumbing for market and user-data WS streams (#3937), thanks for reporting @huangqingchi
- Added Bybit user-related endpoints (#3894), thanks @sunlei
- Added Bybit `BybitPositionIdx` enum and `bybit_resolve_position_idx` PyO3 helper
- Added Coinbase initial integration adapter (Rust)
- Added `DydxNetwork` re-export on the `nautilus_trader.adapters.dydx` package
- Added Hyperliquid historical funding rates via `fundingHistory` info endpoint
- Added Hyperliquid configurable MARKET slippage (`market_order_slippage_bps`) with per-order override
- Added Hyperliquid `OrderBookDepth10` subscription backed by the `l2Book` feed
- Added Hyperliquid `nSigFigs` / `mantissa` L2 precision controls via `subscribe_params`
- Added Interactive Brokers Rust adapter with PyO3 compatibility layer (#3864), thanks @faysou
- Added Kraken xStocks tokenized asset support for spot market data, order submission, and futures instruments
- Added OKX option greeks support for both Black-Scholes and price-adjusted conventions on every tick
- Added OKX `params["greeks_convention"]` (string or list) to narrow option greeks subscriptions
- Added OKX `transport_backend` config to switch websockets between `Tungstenite` and `Sockudo` backends
- Added Polymarket game_id and fee_schedule to instrument info (#3811), thanks @Javdu10
- Added Polymarket batch `SubmitOrderList` via `POST /orders` for limit-order batches (Rust)
- Added Polymarket WebSocket `idle_timeout_ms` for zombie detection (#3908), thanks for reporting @camarigor
- Added Polymarket WebSocket `proxy_url` plumbing
- Added Polymarket `pUSD` collateral currency (`Currency::pUSD()` in Rust, `pUSD` in Python) for the CLOB V2 cutover
- Added configurable `compression` for Tardis Machine replay, defaulting to `zstd`
- Added `ExecutionReport::OrderWithFills` and `send_order_with_fills` emitter for bundled status + fill reconciliation
- Added ADL / liquidation detection and logging across Binance, Bybit, OKX, BitMEX, Hyperliquid, Deribit, and dYdX
- Added Binance Futures COIN-M `delivery_autoclose-` prefix recognition for expiring contract auto-close events
- Added Bybit `adlRankIndicator` warning log when an open position is ranked 4 or higher (next to deleverage)
- Added Hyperliquid liquidation metadata logging on fills and `userEvents.liquidation` routing
- Added Hyperliquid `Auto-Deleveraging` fill detection with warn logging on HTTP and WebSocket paths
### Breaking Changes
- Added `Option<&AccountId>` to Rust `Portfolio::unrealized_pnls`, `realized_pnls`, `total_pnls`; pass `None` to keep prior behavior
- Added `backend: TransportBackend` to `WebSocketConfig`; struct-literal callers must add the field (Rust)
- Added `proxy_url: Option<String>` to `WebSocketConfig`; struct-literal callers must add the field (Rust)
- Migrated Polymarket adapter to CLOB V2: new EIP-712 domain version `2`, new exchange contract addresses, `timestamp`/`metadata`/`builder` order fields replace `taker`/`nonce`/`feeRateBps`, and pUSD replaces USDC.e as collateral; the Python adapter now uses `py-clob-client-v2`
- Consolidated adapter HTTP and WebSocket proxy plumbing onto a single `proxy_url` field, replacing the prior `http_proxy_url` / `ws_proxy_url` split across adapter Rust and Python configs
- Removed `DockerizedIBGatewayConfig::from_env_or_defaults` (Rust); use the bon builder or `Default::default`, which still falls back to `TWS_USERNAME`/`TWS_PASSWORD`
- Removed `OrderMatchingEngineConfig::new` and `with_price_protection_points` (Rust); use `OrderMatchingEngineConfig::builder()` instead
- Removed `BlockchainDataClientConfig::new`, `BlockchainExecutionClientConfig::new`, and `DexPoolFilters::new` (Rust); use the corresponding `::builder()` instead
- Removed `DeribitExecClientConfig::new` and `HyperliquidExecClientConfig::new` convenience constructors (Rust); use the `::builder()` instead
- Removed `DataEngineConfig::new` 12-arg positional constructor (Rust); use `DataEngineConfig::builder()` instead
- Removed synthetic `ACCOUNT-*` placeholders from margin adapters; `MarginBalance` emits with currency only
- Removed `nautilus_system::factories` module; import factory traits from `nautilus_common::factories` (Rust)
- Removed `indicators` from `nautilus-common` default features; enable with `features = ["indicators"]` (Rust)
- Renamed Python `DatabaseConfig.timeout` to `connection_timeout` and `response_timeout` to match the Redis/PyO3 wire schema
- Replaced `is_sandbox: bool` with `environment: AxEnvironment` on `AxDataClientConfig` and `AxExecClientConfig` (Rust and Python), aligning with the Binance/Bybit/Kraken adapter pattern. Default is `Sandbox`.
- Changed `BacktestEngine::add_venue` and `SimulatedExchange::new` (Rust) to take `SimulatedVenueConfig` (bon builder)
- Changed Interactive Brokers Rust configs to use bon builders: `InteractiveBrokersDataClientConfig`, `InteractiveBrokersExecClientConfig`, `InteractiveBrokersInstrumentProviderConfig`, and `DockerizedIBGatewayConfig`
- Changed `get_cached_bybit_http_client` signature: replaced `demo`/`testnet` bools with `environment: BybitEnvironment`
- Changed `UnsubscribeBookSnapshots` to require `interval_ms` for exact snapshot interval unsubscribe (Rust)
- Changed `OrderError::Invariant` variant to wrap `CorrectnessError` instead of `anyhow::Error` (Rust)
- Changed `HyperliquidEip712Signer::new()` to return `Result` and take `&EvmPrivateKey` (Rust)
- Changed `HyperliquidExchangeRequest::new/with_vault` to accept `HyperliquidSignature` directly (Rust)
- Changed Binance USD-M Futures WebSocket URLs from `/ws` to `/market/ws` and `/private/ws`
- Changed Cap'n Proto and SBE wire formats to preserve `Option` state (unstable, may change)
- Changed Python and Serde-backed Rust config decoding to reject unknown fields, so stale or misspelled keys now fail fast during config parsing
- Changed `MarginBalance.instrument_id` to optional; `None` marks account-wide (cross margin) entries keyed by currency
- Changed `MarginAccount.margins_init`/`margins_maint` to per-instrument only; use `account_margins_*` for cross margin
- Changed Binance Futures COIN-M to emit one `MarginBalance` per base coin (previously hardcoded USDT)
- Changed matching-engine `TradeId` format to `T-{hash}-{count}` from `{venue}-{raw_id}-{count}`; `ts_init`-keyed
- Changed `use_random_ids` to no longer govern `TradeId`; flag still affects `VenueOrderId` and `PositionId`
- Changed workspace `nautilus-live` to `default-features = false`; enable `features = ["node"]` for `LiveNode` (Rust)
- Changed adapter `LiveNode` examples to require `--features examples` to build (Rust)
- Changed `ParquetDataCatalog::to_object_path` and `to_object_path_parsed` to return `anyhow::Result` so cross-store URIs surface as errors instead of silently rewriting against the catalog bucket (Rust)
- Changed prefixed remote catalogs (`s3://bucket/base/path`, etc.) to read and write under their declared URI prefix; data previously written to the bucket root by the prior buggy behavior will not be discovered after upgrading and must be moved into the prefix (#3930)
### Security
- Hardened Binance Ed25519 credential detection so base64 HMAC secrets no longer pass as Ed25519 keys (Rust)
- Hardened Binance HTTP request signing by URL-encoding Ed25519 signatures in query strings (Rust)
- Replaced the third-party `urlencoding` crate with the in-tree `nautilus_core::urlencoding` to shrink the supply-chain surface (Rust)
- Bumped pinned SHAs for security-relevant GitHub Actions (`harden-runner`, `codeql-action`, `setup-uv`, `setup-rust-toolchain`) to current upstream releases
- Refreshed `cargo-deny` and `osv-scanner` advisory configuration; removed the stale `pygments` advisory ignore now that upstream is patched
### Fixes
- Fixed sockudo WebSocket backend dropping handshake leftover bytes when the server piggybacks the first frame on the 101 response (#3932), thanks @sunlei
- Fixed account state regeneration dropping account-wide margins on every fill across live and backtest paths
- Fixed `AccountState` to accept empty `balances` and `margins`
- Fixed `FillModel` determinism via `IndexMap` in `OrderMatchingEngine` (#3914), thanks for reporting @timkoopmans
- Fixed quote midpoint raw arithmetic across precision modes (#3849), thanks @BurnOutTrader
- Fixed `quote_quantity` propagation in execution algorithm spawn orders (#3845), thanks @dxwil
- Fixed streaming backtest shutdown determinism on `FORCE_STOP` (#3920)
- Fixed `mark_values`/`equity` keying by base currency when conversion is off; now keys by settlement currency
- Fixed `PortfolioAnalyzer` AttributeError on `MaxDrawdown`/`CAGR`/`CalmarRatio` (#3941), thanks for reporting @a1zb2yc3z
- Fixed `stop_timer` in `TimeBarAggregator` (#3822), thanks @faysou
- Fixed `RiskEngine` applying base `min_quantity`/`max_quantity` bounds to quote-denominated orders
- Fixed backtest `OrderMatchingEngine` treating `quote_quantity=True` orders as base quantity; the quote notional is now converted to a base quantity before fill simulation (#3873), thanks for reporting @fedoraiver
- Fixed `subscribe_option_chain` hanging on bootstrap in backtest (#3938), thanks for reporting @aaurix
- Fixed backtest option expiry fills missing from cache and fills report (#3939), thanks for reporting @hotelmike
- Fixed backtest physical option assignment closing the option leg at the opening premium (#3948), thanks for reporting @hotelmike
- Fixed `DataBackendSession` GIL deadlock when streaming custom data types (#3847), thanks for reporting @GianC0
- Fixed `BacktestNode` streaming with mixed built-in and custom data types (#3853), thanks for reporting @GianC0
- Fixed `DataBackendSession` chunked streaming memory leak causing RSS growth (#3889), thanks for reporting @GianC0
- Fixed book snapshot subscriptions to preserve exact `(instrument_id, interval_ms)` semantics for shared intervals and exact unsubscribe handling (Rust) (#3823), thanks for reporting @dwolfesberger
- Fixed WebSocket auth state during reconnection for Bybit, OKX, and Deribit (#3820), thanks for reporting @KaizynX
- Fixed WebSocket `idle_timeout_ms` reset on `Ping`/`Pong` keep-alive frames (#3907), thanks for reporting @camarigor
- Fixed `TradingNodeConfig.parse` dropping importable live client config `path` and `factory` fields during raw config decoding
- Fixed `OrderTriggered` ValueError on market-style stop orders (#3812), thanks for reporting @jindrichsirucek
- Fixed `consolidate_data_by_period` pairwise merging on fragment-per-flush catalogs (#3857), thanks for reporting @M-Advis
- Fixed `consolidate_data_by_period` destroying data on repeat runs and when straddling files spanned the consolidation window, mirrored in the Rust catalog backend (#3883), thanks @M-Advis
- Fixed `ParquetDataCatalog.get_intervals(identifier=None)` on per-identifier data (#3903), thanks for reporting @GianC0
- Fixed `ParquetDataCatalog.consolidate_data` raising `IndexError` when the start/end range did not overlap any files, and `consolidate_catalog_by_period` aborting the loop on the first unrecognized directory rather than skipping it (#3910), thanks for reporting @M-Advis
- Fixed remote catalog object paths under URI prefix so writes and reads under `s3://bucket/base/path` (and other remote schemes) no longer collapse to the bucket root (#3930), thanks @fedoraiver
- Fixed S3-backed custom data queries and remote Feather discovery (#3931), thanks for reporting @fedoraiver
- Fixed `FeatherWriter` writing 0-precision metadata on leading `CLEAR` delta (#3913), thanks for reporting @fedoraiver
- Fixed empty error log on `TradingNode` clean shutdown from `CancelledError` (#3862), thanks for reporting @jxstanford
- Fixed `Symbol` and `PositionId` deserialize of non-ASCII escaped strings (#3893), thanks for reporting @volemont
- Fixed execution engine ignoring user-supplied `position_id` from `submit_order` (Rust)
- Fixed `ExecutionEngine` leg-fill position events not publishing to subscribers (#3939)
- Fixed cache load not repairing OTO contingent child `position_id` after a partial fill-time crash (Rust)
- Fixed `TestDataGenerator.generate_trade_ticks` using random UUID4; now sequences deterministic `T-{idx}` IDs
- Fixed reconciliation IDs non-deterministic across restarts (#3878), thanks for reporting @peanut-copilot
- Fixed reconciliation synthetic `OrderStatusReport` now propagates fill price to `avg_px` for downstream inferred fills
- Fixed `reconcile_fill_report` dropping fills for unknown orders; now bootstraps external orders for venue closures
- Fixed PyO3 `InstrumentStatus` persistence and backtest streaming through `ParquetDataCatalog` (#3855)
- Fixed PyO3 `LiveNode` `request_bars()` historical callbacks dropped during startup warmup (#3825), thanks @BurnOutTrader
- Fixed PyO3 `DataActor` missing `on_historical_funding_rates` and `on_historical_data` forwarding `None`
- Fixed PyO3 crypto instrument `from_dict` for unregistered base/underlying codes (#3882), thanks for reporting @volemont
- Fixed PyO3 catalog `instruments()` failing on unregistered currencies (#3898), thanks for reporting @volemont
- Fixed PyO3 `from_dict` on non-ASCII strings via `ensure_ascii=False` in `json.dumps` (#3895), thanks @costajohnt
- Fixed Betfair event order: `Instrument` now emits before `InstrumentStatus`/`InstrumentClose` within each MCM
- Fixed Betfair scratched runners (`Removed`/`RemovedVacant`) emitting close only at market close; now fire immediately
- Fixed Betfair non-snapshot book deltas emitting inline; now tailed after trades/tickers to match Python semantics
- Fixed Betfair BSP deltas emitting before book deltas; now tailed after book deltas within each MCM
- Fixed Betfair order rejection reason dropping instruction-level `errorMessage` detail
- Fixed Betfair `query_order` to emit status reports via `customer_order_ref` and `bet_id` lookups (Rust)
- Fixed Binance user data stream not recovering after keepalive failure (#3861), thanks for reporting @KaizynX
- Fixed Binance Futures user data stream event loss during listen key rotation (#3861), thanks for reporting @KaizynX
- Fixed Binance Futures WebSocket trades by forcing `@aggTrade` (#3861), thanks for reporting @KaizynX
- Fixed Binance Futures exchange-generated fills losing real `trade_id` and `commission` by bundling status + fill
- Fixed Binance Ed25519 detector silently accepting base64 HMAC secrets as Ed25519 keys (Rust)
- Fixed Binance HTTP request Ed25519 signature URL-encoding in query strings (Rust)
- Fixed Binance Futures USD-M `cancel_all_orders` silently failing; routes through HTTP (WS API does not support it)
- Fixed Binance Futures `TRADE_LITE` user data events logging "Unknown event type" warnings on every fill
- Fixed Binance USD-M Futures WebSocket routing for `fstream-mm` and `fstream-auth` hosts
- Fixed BitMEX trade ID fallback using random UUID4 when `trdMatchID` missing; now hashed from trade fields
- Fixed Bybit demo mode websocket data URLs (#3742), thanks for reporting @jindrichsirucek
- Fixed Bybit position deserialization for closed positions (#3836), thanks for reporting @pusteckiy
- Fixed Bybit perpetual instrument status to emit `PreClose` when scheduled for delisting (#3829), thanks @dxwil
- Fixed Bybit `load_all_async` dropping `base_coin` filter for options (#3865), thanks for reporting @Baerenstein
- Fixed Bybit `InstrumentStatus` messages silently dropped instead of forwarded to the data engine
- Fixed Bybit and Deribit option chain example `subscribe_option_chain` call (#3887), thanks @sunlei
- Fixed Bybit margin missing for accounts with orders but no positions (#3725), thanks for reporting @marco-rigoni
- Fixed Bybit JSON pong websocket frames not being skipped before classification (#3936), thanks @sunlei
- Fixed Bybit hedge mode `positionIdx` rejection when `position_mode` set (#3944), thanks for reporting @pusteckiy
- Fixed Bybit execution client not applying configured leverage, position mode, or margin mode on connect (Rust)
- Fixed Databento CMBP1 and TCBBO trade IDs using random UUID4 instead of deterministic hash of trade fields
- Fixed Databento dropping `start_ns` after session start; now logs error (#3877), thanks for reporting @jxstanford
- Fixed Deribit mark/index price subscriptions silently dropping data in Python (#3821), thanks for reporting @linimin
- Fixed Deribit `StopMarket` `OrderRejected` on `market_price` price field (#3925), thanks for reporting @marco-rigoni
- Fixed dYdX `generate_order_status_report` fetching only the first order and missing later matches in the response
- Fixed dYdX orderbook snapshots missing `F_SNAPSHOT` flag on deltas; empty-book Clear now emits `F_SNAPSHOT | F_LAST`
- Fixed dYdX crossed-book resolution stripping `F_SNAPSHOT` from synthetic uncrossing deltas and the terminator
- Fixed dYdX trade-tick pagination dedup missing non-adjacent duplicates across page boundaries
- Fixed dYdX trade-tick pagination overshooting target `end` block from fixed block-time estimate
- Fixed dYdX crossed-book size arithmetic using `f64` subtraction; now uses `Decimal` at full precision
- Fixed dYdX position reports overriding venue `side` from `size` sign; venue side now preserved end-to-end
- Fixed dYdX `DydxAdapterConfig` defaulting to mainnet URLs regardless of `network`; added `for_network` helper
- Fixed Hyperliquid `LiveNode` bootstrap panic on HIP-3 instrument symbols containing `*`/`?` (e.g. `dex:STREAMABCD****-USD-PERP`) by substituting wildcard bytes with `x` in `InstrumentId.symbol` while preserving the venue-official name on `raw_symbol` (#3896), thanks for reporting @daiwanwei
- Fixed Hyperliquid bracket order submission grouping (#3810), thanks for reporting @jindrichsirucek
- Fixed Hyperliquid modify cancel-replace emitting stale `OrderCanceled` (#3827), thanks for reporting @P1YU5H-50N1
- Fixed Hyperliquid order status query for closed orders (#3879), thanks for reporting @pusteckiy
- Fixed Hyperliquid batch cancel silently dropping per-item errors (#3879), thanks for reporting @pusteckiy
- Fixed Hyperliquid Rust `query_order` handler to emit status reports (#3879), thanks for reporting @pusteckiy
- Fixed Hyperliquid `request_account_state` discarding parsed margins (#3725), thanks for reporting @marco-rigoni
- Fixed Hyperliquid `cancel_all_orders` dropping per-order rejection events on partial or transport failure
- Fixed Hyperliquid `request_trades` silently returning empty; now bails explicitly
- Fixed Hyperliquid `Auto-Deleveraging` fill direction deserialization (#3922), thanks for reporting @AlphaTraderK
- Fixed IB Gateway Docker image failing on ARM64 hosts (#3813), thanks for reporting @Baki-0501
- Fixed Interactive Brokers rejecting negative average fill price on combo/spread net-credit fills (#3884), thanks @faysou
- Fixed Interactive Brokers position reconciliation `TypeError` when `priceMagnifier` is `None` (#3885), thanks @davidsblom
- Fixed Kraken Futures limit order `OrderUpdated` panic from wire `stop_price: 0.0` treated as trigger price
- Fixed Kraken Futures fast-fill market orders resolving as rejected during order status reconciliation (#3870), thanks for reporting @Stamppot82
- Fixed Kraken Futures margin-account balance parse violating the `AccountBalance` invariant (`total == locked + free`) when Kraken's `af` field and the derived `amount - af` round independently at the currency precision
- Fixed Kraken Spot quote-quantity orders never reaching terminal state from base/quote size mismatch
- Fixed Kraken Spot ticker `QuoteTick.ts_event` using local init time instead of the exchange `timestamp` field (#3926), thanks @ptzafos
- Fixed Kraken trade dedup clearing the entire set at capacity instead of evicting the oldest entry
- Fixed Kraken Futures `AccountBalance` invariant panic on margin parse (#3868), thanks @Stamppot82
- Fixed Kraken Futures WebSocket re-authentication deadlock on reconnect (#3871), thanks for reporting @Stamppot82
- Fixed OKX option greeks not forwarded due to inaccessible Cython `cdef` subscription attribute
- Fixed OKX option greeks emitting `BlackScholes` convention regardless of subscribed greeks type
- Fixed OKX order identity registration race during concurrent order submission (Rust)
- Fixed OKX algo orders missing from order status reconciliation reports
- Fixed OKX spot margin position reconciliation preferring `CurrencyPair` with USDT/USDC/USD quote over alternatives
- Fixed OKX index-price subscription refcount leaking across reconnect and concurrent transitions
- Fixed OKX option summary subscription refcount not rolling back on subscribe failure
- Fixed OKX duplicate fills from empty `trade_id` using deterministic synthesized id instead of random UUID
- Fixed OKX panics on unmapped `OrderStatus` and empty `OptionType` values via `TryFrom` conversion (Rust)
- Fixed OKX `InstrumentStatus` messages logged as unhandled instead of forwarded to the data engine
- Fixed OKX `query_order` to emit status reports by merging regular and algo order lookups (Rust)
- Fixed Polymarket commission formula and fee source for fills (#3838), thanks for reporting @santivazq
- Fixed Polymarket reconciliation fills using incorrect commission (#3860), thanks for reporting @fedoraiver
- Fixed Polymarket instrument `min_quantity` denying market orders via limit-order shares rule (#3874), thanks for reporting @fedoraiver
- Fixed Polymarket `request_instrument(s)` dropping WS via stale `token_meta` (#3900), thanks for reporting @fedoraiver
- Fixed Polymarket `parse_to_quote_ticks` using changed level as top of book (#3905), thanks for reporting @camarigor
- Fixed Polymarket `parse_to_snapshot` missing `F_SNAPSHOT` flag on CLEAR and intermediate ADD deltas
- Fixed Polymarket `parse_to_deltas` flagging `F_LAST` on every delta instead of only the final one
- Fixed Polymarket `parse_to_trade_tick` using `uuid.uuid4()`, producing non-deterministic trade IDs
- Fixed Tardis replay handling of sparse `book_snapshot_*` levels (#3953), thanks for reporting @a1zb2yc3z
- Fixed Tardis trade ID fallback using random UUID4 when venue `id` missing/empty (CSV and WebSocket parsers)
### Internal Improvements
- Added `AccountBalance::from_total_and_locked` and `AccountBalance::from_total_and_free`, and migrated adapter balance parsing to preserve the `total == locked + free` invariant at currency precision (Rust)
- Added typed `CorrectnessError` enum to replace `anyhow::Error` in `correctness` helpers (Rust)
- Added `CorrectnessResultExt::expect_display` for display-formatted panics on typed correctness errors (Rust)
- Added deterministic simulation testing (DST) re-export module gated behind `simulation` feature (Rust)
- Added `wall_clock_now` seam in `nautilus-core` for virtual time under simulation (Rust)
- Added `biased` to `tokio::select!` blocks in network and live crates for deterministic poll order
- Added `nautilus_network::transport` module with `Message`/`TransportError`/`WsTransport` for future backend swap (Rust)
- Added neutral `Message`/`TransportError` re-exports on `nautilus_network` to ease future backend swaps (Rust)
- Added engine config methods on PyO3 `LiveNodeBuilder` (#3848), thanks @BurnOutTrader
- Added read-only `params()` accessor to `SubscribeCommand` and `TradingCommand` (#3846), thanks @faysou
- Added `ShutdownSystem` handling via `commands.system.shutdown` pub/sub topic, wired to kernel, backtest, and live (Rust)
- Added PyO3 `DataActor` parity with v1 for `publish_data`, `publish_signal`, `subscribe_signal`, `unsubscribe_signal`, `add_synthetic`, and `update_synthetic` (Rust)
- Added per-currency account-wide margin storage to `MarginAccount`, routing event margins by `instrument_id` presence
- Added Architect AX unit and integration tests for execution, request filters, and WebSocket parsers
- Added dYdX debug logging to `generate_order_status_report` showing filter scope and `page_full` on `None` results
- Added Polymarket `determine_trade_id` helper with FNV-1a (Rust) and blake2b (Python) deterministic hashing
- Added Hyperliquid criterion benchmarks for L1 signing path
- Added Hyperliquid integration tests for funding rates, trades, cancel-all, and `handle_l2_book` routing
- Added Hyperliquid `minTradeSpotNtlRejected` order status and `Unknown` liquidation method fallback
- Added Binance unit tests for spot/futures dispatch dedup, post-only rejection, and value conversions
- Added `derive_trade_id` FNV-1a helpers in BitMEX and Tardis common parse modules for deterministic fallback
- Added `derive_cmbp_trade_id` in Databento decode for schemas without a native trade ID
- Added property-based tests for Databento trade ID derivation (stability and 16-hex format)
- Added Rust/Python parity tests pinning matching-engine `TradeId` format across language bindings
- Added `node` feature to `nautilus-live` gating `builder`, `config`, `manager`, and `node` modules (default on)
- Added support for user-provided Tokio runtime in live module (#3918), thanks @filipmacek
- Added continuous futures support for bar requests and subscriptions (#3921), thanks @faysou
- Improved `nautilus-live/defi` to no longer pull `LiveNode` orchestration deps
- Improved CI uv cache via `setup-uv` auto mode to skip GHA uploads on self-hosted runners (#3933), thanks @sunlei
- Cleaned up unused dependencies (#3886), thanks @sunlei
- Improved CI cache hygiene on self-hosted runners with uv prune, prek auto-gate, and footprint summary
- Migrated `WebSocketClient` onto the `WsTransport` trait, decoupling reconnect/auth from tungstenite types (Rust)
- Changed Polymarket `PolymarketQuote.best_bid`/`best_ask` to optional, matching the Rust `Option<String>` schema
- Ported Interactive Brokers Rust historical bar replay with Python parity fixes (#3892), thanks @faysou
- Standardized adapter example manifests and trading deps (#3891), thanks @sunlei
- Standardized margin emission convention across live derivatives adapters to use currency-keyed `MarginBalance` entries
- Refactored `reconciliation` module into `types`, `ids`, `positions`, and `orders` submodules (Rust)
- Refactored Binance Futures user data stream dispatch and listen key recovery into dedicated modules (Rust)
- Refactored Binance Futures value conversions into a new `futures::conversions` module (Rust)
- Replaced `AHashMap`/`AHashSet` with `IndexMap`/`IndexSet` in `ExecutionManager` for deterministic ordering in simulations (Rust)
- Refined `nautilus-system` to optional in adapter crates (gated by `python`); default builds drop heavy transitive deps
- Refined DST convention hook to enforce `IndexMap` in `OrderMatchingEngine`
- Refined make cargo-test to not include binaries for test harness builds (#3828), thanks @faysou
- Refined Interactive Brokers combo fill average price calculation (#3834), thanks @faysou
- Refined Kraken WebSocket execution dispatch to emit typed events for tracked orders via per-product modules
- Refined Kraken Spot WS auth via `AuthTracker` with `is_authenticated`/`wait_until_authenticated` Python APIs
- Optimized Hyperliquid L1 signing by caching `PrivateKeySigner` and EIP-712 domain (#3851)
- Optimized `ClientOrderId` generation with cached prefix buffer (#3935), thanks @sunlei
- Optimized `OrderListId` and `PositionId` generation with cached prefix buffers (Rust)
- Upgraded Rust (MSRV) to 1.95.0
- Upgraded Cap'n Proto to v1.4.0
- Upgraded `alloy` crate to v2.0.1
- Upgraded `capnp` crate to v0.25.4 (regenerated schemas with 4-space indents and version headers)
- Upgraded `databento` crate to v0.48.0
- Upgraded `datafusion` crate to v53.1.0
- Upgraded `msgspec` to v0.21.1
- Upgraded `pyarrow` to v24.0.0
- Upgraded `tokio` crate to v1.52.1
### Documentation Updates
- Added Polymarket Python and Rust adapter config tables and updated rate limits
- Added ID determinism invariant to the reconciliation live and execution concept guides
- Added Trade ID derivation sections to Polymarket, Databento, BitMEX, and Tardis integration guides
- Added Trade ID derivation section to the backtesting concept guide
- Added "Equity and mark-to-market" section to the portfolio concept guide
- Added ADL / liquidation handling sections to the Binance, Bybit, OKX, BitMEX, Hyperliquid, Deribit, dYdX guides
- Added reconciliation reports section to the execution concept guide
- Refined docs to follow style guide for symbols and filler words (#3830), thanks @JKDasondee
- Refined Interactive Brokers documentation regarding UTC timestamps (#3826), thanks @faysou
- Refined dYdX integration guide config tables to match the Python API (`environment`, `subaccount`, `base_url_grpc`)
- Updated Hyperliquid integration guide with funding history, depth10, subscribe_params, and slippage
- Updated the configuration concept guide to define unknown-field rejection as the config standard in Python and Rust
### Deprecations
- Deprecated `demo`/`testnet` bools on `BybitDataClientConfig`/`BybitExecClientConfig` - use `environment`
- Deprecated `is_demo` on `OKXDataClientConfig`/`OKXExecClientConfig` - use `environment`
- Deprecated `testnet` on `HyperliquidDataClientConfig`/`HyperliquidExecClientConfig` - use `environment`
- Deprecated `is_testnet` on `DeribitDataClientConfig`/`DeribitExecClientConfig` - use `environment`
- Deprecated `is_testnet` on `DydxDataClientConfig`/`DydxExecClientConfig` - use `environment`
- Deprecated `testnet` on `BitmexDataClientConfig`/`BitmexExecClientConfig` - use `environment`