v1.225.0

nautechsystems/nautilus_traderv1.225.0Apr 6, 2026by github-actions[bot]

AI Summary

Beta release adding option chains, greeks, and new adapters.

Key Highlights

  • Option chains and greeks in Rust and Python
  • Tokenized asset instrument type (xStocks)
  • Binance Futures exchange-generated order handling
  • Bybit native TP/SL params

Breaking Changes

  • Removed deprecated `convert_quote_qty_to_base`
  • Renamed `OrderEvent.kind()` to `type_name()`
  • Renamed `ParquetDataCatalogV2` to `ParquetDataCatalog`
  • Config structs to use `bon::Builder` defaults

New Features

  • Option chains and Greeks calculator
  • Binance Futures liquidation fills with client order ID detection
  • Bybit `submit_order_list` via WebSocket batch API
  • OKX options trading execution
  • Hyperliquid agent wallet support

Full Release Notes

# NautilusTrader 1.225.0 Beta

Released on 6th April 2026 (UTC).

### Enhancements
- Added option chains and greeks in Rust (#3637), thanks @filipmacek
- Added option chains and greeks in Python (#3677), thanks @filipmacek
- Added cached futures-spread support to `GreeksCalculator` (#3792), thanks @faysou
- Added custom data registration, persistence, and routing in Rust (#3542), thanks @faysou
- Added `nautilus_actor!` macro in `nautilus_common` for `Deref`/`DerefMut` boilerplate on actor types (Rust)
- Added `nautilus_strategy!` macro in `nautilus_trading` for `Deref`/`DerefMut` and `Strategy` trait boilerplate on strategy types, with optional block for hook overrides (Rust)
- Added `cache.orders_active_local(...)` function in Rust (#3716), thanks @Javdu10
- Added `interval` field to `FundingRateUpdate` (#3694), thanks @dxwil
- Added `BookImbalanceActor` example actor for order book quoted volume imbalance in Rust
- Added `ExecTesterConfig.test_reject_post_only` implicitly setting `post_only` on orders without requiring `use_post_only` (Python and Rust)
- Added `TieredTickScheme` and `TickScheme::Tiered` for price-dependent tick sizes (Rust)
- Added `TokenizedAsset` instrument type with configurable `asset_class` field for tokenized equities, ETFs, commodities, and other real-world assets
- Added Betfair backtest example streaming raw `.gz` data through `BacktestEngine` (Rust)
- Added Binance `decode_binance_spot_client_order_id` and `decode_binance_futures_client_order_id` utility functions for decoding Link & Trade encoded `clientOrderId` values from raw Binance API responses
- Added Binance Futures `subscribe_funding_rates` and `unsubscribe_funding_rates` with `FundingRateUpdate` emission via the mark price stream (Rust)
- Added Binance Futures exchange-generated order handling for liquidation, ADL, and settlement fills with client order ID prefix detection and `FillReport`/`OrderStatusReport` emission (Rust)
- Added Binance Futures `use_position_ids` config for hedging position IDs derived from instrument and position side on exchange-generated fills (Rust)
- Added Binance Futures `default_taker_fee` config with commission fallback estimation for exchange-generated fills when venue omits commission fields (Rust, USD-M only)
- Added Binance `NewAdl`, `NewInsurance`, and `PendingNew` variants to `BinanceOrderStatus` (Rust)
- Added Binance `Rpi` time-in-force, `PreSettle`/`Settling`/`Close` contract statuses, `None`/`Decrement`/`Transfer` STP modes, and income type variants (Rust)
- Added Binance instrument status polling in Rust
- Added Arrow schema support for `BinanceBar` and `BinanceFuturesMarkPriceUpdate` (#3749), thanks @twitu
- Added Binance Futures `close_position` parameter for algo stop orders to close an entire position at trigger price (Python and Rust) (#3751), thanks for reporting @dodge-basic
- Added Bybit native TP/SL params for order placement (#3754), thanks @jindrichsirucek
- Added Bybit instrument status polling and subscription (#3738), thanks @filipmacek
- Added Bybit options trade subscriptions using `baseCoin` topic with per-instrument filtering
- Added Bybit option instrument fee rate population from `/v5/account/fee-rate`
- Added Bybit `submit_order_list` via WebSocket batch API with TP/SL support and HTTP demo fallback (Rust)
- Added Bybit `query_order` via HTTP with open order and history fallback (Rust)
- Added Databento Arrow serialization for imbalance and statistics (#3689), thanks for reporting @GianC0
- Added Deribit `LimitIfTouched` and `MarketIfTouched` order type support (`take_limit`/`take_market`)
- Added Hyperliquid agent wallet support (#3668), thanks @oh92
- Added Hyperliquid product type config for live clients (#3783), thanks @lisiyuan656
- Added Kraken FOK, `LimitIfTouched` orders, and batch submit
- Added Kraken tokenized equity (xStocks) support via `aclass_base=tokenized_asset` with automatic dual-fetch on instrument loading (#3455), thanks for reporting @jilongjia
- Added Kraken `request_book_snapshot` for spot and futures via HTTP depth endpoints
- Added Kraken `request_funding_rates` for futures with client-side start/end/limit filtering
- Added Kraken `subscribe_instrument_status` for spot and futures (polling-based detection)
- Added Kraken spot trailing stop and trailing stop limit order submission with `trailing_offset` and `limit_offset` fields
- Added Kraken spot `trigger` parameter for conditional orders (`last` or `index` price reference)
- Added Kraken spot quote quantity orders via `viqc` order flag
- Added Kraken spot iceberg orders via `displayvol` parameter
- Added OKX `submit_order_list` via WebSocket batch endpoint for regular GTC orders
- Added OKX support for bracket order submission with attached TP/SL (#3701), thanks @Nickonomic
- Added OKX `subscribe_option_greeks` for venue-provided Greeks via the `opt-summary` WebSocket channel
- Added OKX configurable `ws_auth_timeout_secs` for WebSocket authentication (#3727), thanks for reporting @Stamppot82
- Added OKX `fwdPx` (forward price) to `OKXOptionSummaryMsg` and mapped to `underlying_price` on `OptionGreeks` for ATM tracking
- Added OKX `request_orderbook_snapshot` and `request_funding_rates` to Python data client via PyO3 bindings
- Added OKX options trading execution with limit orders, `px_usd`/`px_vol` pricing modes, `OpFok` order type, and `MarketToLimit`/conditional order rejection
- Added OKX options position-level Black-Scholes Greeks (`delta_bs`, `gamma_bs`, `theta_bs`, `vega_bs`) to position data
- Added OKX `determine_order_type_with_alt` for correct order type classification when options use alternative pricing fields
- Added `DeltaNeutralVol` strategy strangle entry via `px_vol` limit orders with configurable IV offset, time-in-force, and cache-based re-entry guard
- Added OKX missing WebSocket message fields across all channel structs
- Added Polymarket instrument provider and filters in Rust (#3708), thanks @filipmacek
- Added Polymarket strategy-driven data subscriptions (#3806), thanks @Javdu10
- Added Tardis `MarkPriceUpdate` and `IndexPriceUpdate` parsing from `derivative_ticker` messages in Rust
- Added Tardis `DerivativeTickerCache` for deduplicating unchanged funding rate, mark price, and index price updates
- Added Tardis `TardisDataType` enum for normalized Tardis Machine data type identifiers
- Added Tardis live streaming support via `stream_options` config with automatic reconnection and exponential backoff
- Added Tardis raw provider metadata to `Instrument.info` (#3730), thanks for reporting @volemont

### Breaking Changes
- Removed deprecated `convert_quote_qty_to_base` from `ExecEngineConfig` and `LiveExecEngineConfig`; adapters now handle quote-to-base conversion directly
- Removed `TARDIS_BASE_URL` constant from `nautilus_tardis::http` - use `nautilus_tardis::common::urls::TARDIS_HTTP_BASE_URL`
- Removed Hyperliquid `revoke_hyperliquid_builder_fee` function and builder fee revoke scripts
- Removed `DatabentoLiveClient.key` property (Python)
- Renamed `OrderEvent.kind()` to `type_name()` in Rust
- Renamed instrument `type_str` PyO3 getter to `type_name`
- Renamed `DatabentoHistoricalClient.key` property to `api_key` (Python)
- Renamed `ParquetDataCatalogV2` to `ParquetDataCatalog` and `StreamingFeatherWriterV2` to `StreamingFeatherWriter` (PyO3 persistence classes)
- Changed Tardis HTTP client from `reqwest::Client` to `nautilus_network::http::HttpClient` with rate limiting
- Changed `ExecutionEngine.register_client` to error when a venue is already routed to another client (Rust)
- Changed `ExecutionEngine.register_venue_routing` to error when re-routing a venue to a different client (Rust)
- Changed collection-cloning PyO3 getters to methods: `Position.events()`, `adjustments()`, `client_order_ids()`, `venue_order_ids()`, `trade_ids()`; and `events()` on all order types
- Changed config structs to use `bon::Builder` defaults as single source of truth; `Default` impls now delegate to `Self::builder().build()`
- Changed config fields that always had a sensible default from `Option<T>` to plain `T` with `#[builder(default)]` across all adapter, live, and engine configs (Rust)
- Changed `Option<T>` fields retained only where `None` carries distinct meaning (feature disabled, unbounded, etc.)

### Security
- Hardened Docker Compose to bind all ports to localhost and add `no-new-privileges` to all services
- Hardened CI egress policy to block by default and fall back to `audit` mode for fork pull requests
- Upgraded all `nautilustrader.io` URLs from HTTP to HTTPS (#3686), thanks @04cb
- Documented `aws-lc-rs` non-FIPS mode rationale (FIPS 140-3 module requires Go toolchain)

### Fixes
- Fixed `OrderBook` L1 stale event mutation corrupting bid/ask (#3790), thanks for reporting @linimin
- Fixed position index blob pollution in `update_position` (#3791), thanks @YeeTsai
- Fixed `purge_order` `KeyError` for position/exec_algorithm index access (#3799)
- Fixed strategy receiving historical events during startup reconciliation (#3793), thanks @filipmacek
- Fixed `Trader::add_exec_algorithm` not registering the `{id}.execute` msgbus endpoint, causing orders with `exec_algorithm_id` to be silently dropped
- Fixed `Trader::clear_exec_algorithms` and `dispose_components` not deregistering `{id}.execute` msgbus endpoints for removed algorithms
- Fixed `TopicRouter` stale index cache panic when unsubscribing one pattern invalidated indices for unrelated cached topics (#3755), thanks for reporting @Javdu10
- Fixed `PRICE_UNDEF` panic in `OrderBookDelta.to_pyo3_list` Cython conversion (#3697), thanks @zshuang15
- Fixed `ExecutionEngine` silently dropping `SubmitOrder` and `SubmitOrderList` commands when no execution client can be resolved; now emits `OrderDenied` (Rust)
- Fixed `RiskEngine` RefCell re-entrancy panic on order denial (#3680), thanks @husariancom
- Fixed reconciliation when trigger_price is set for non-conditional orders (#3673), thanks @husariancom
- Fixed `subscribe_instruments` using exact topic instead of wildcard pattern, causing venue-level subscriptions to miss per-instrument publishes from `DataEngine` (Rust)
- Fixed spurious "Timer replaced" warnings for expired timers in `LiveClock` and `TestClock` (#3690), thanks @HaakonFlaaronning
- Fixed time bar historical event deferral (#3698), thanks @faysou
- Fixed `DataActor` and `Strategy` timer callbacks in live mode silently lost on shared clock
- Fixed `DataActor::handle_time_event` missing `not_running()` state guard
- Fixed `SimulatedExchange` account balance adjustment mutation (#3704), thanks for reporting @thaning0
- Fixed analyzer and tearsheet returns to prefer portfolio-level daily returns when they can be derived from account balances
- Fixed backtest analyzer to include position snapshots in Rust (#3710), thanks @necofx
- Fixed `make_dict_serializer` incompatible with instance-method `to_dict` for `@customdataclass` types (#3722), thanks for reporting @Lacleman-trading
- Fixed Sandbox `RefCell` re-entrancy panic when submitting orders through `ExecutionEngine` in async runner (#3732), thanks for reporting @linimin
- Fixed triggered stop orders remaining in matching core after full fill, causing repeated duplicate fill log messages (#3741), thanks for reporting @linimin
- Fixed matching engine `L1_MBP` stale bid/ask when backtesting with trade-only data (Rust and Cython)
- Fixed matching engine GTD order expiry running after fills, allowing expired orders to fill before being expired
- Fixed `Order::calculate_overfill` emitting false `Quantity` saturation warnings during normal partial fills (#3746), thanks for reporting @linimin
- Fixed Sandbox reconciliation missing `account_id` (#3705), thanks for reporting @eliotOrderson
- Fixed Rust `Portfolio` account-scoped `net_exposure`, `net_exposures`, and balance updates in multi-account mode
- Fixed `RefCell` borrow conflict in `Portfolio::initialize_orders` (#3787), thanks @filipmacek
- Fixed reported `MarginAccount` updates dropping initial and maintenance margins (#3725), thanks for reporting @marco-rigoni
- Fixed option chains emitting data after expiry (#3735), thanks @filipmacek
- Fixed `BettingInstrument.selection_handicap` PyO3 name
- Fixed adapter `query_account` panic from `block_on` inside async runtime across all adapters (Rust)
- Fixed Betfair order modify `Quantity` serialization for partial cancel size reduction
- Fixed Binance trailing stop params and testnet URLs (#3778), thanks @eliotOrderson
- Fixed Binance Spot SBE schema version mismatch after Binance upgraded to schema 3:3 (released 2026-03-25)
- Fixed Binance algo order update (#3665), thanks @qu1zzyboy
- Fixed Binance SBE price/quantity precision derivation (#3670), thanks @husariancom
- Fixed Binance Futures `set_futures_hedge_mode` sending GET instead of POST to `positionSide/dual` endpoint (#3745), thanks for reporting @dodge-basic
- Fixed Binance order update silently dropped when instrument not cached (#3775), thanks for reporting @M-at-ti-a
- Fixed Binance Futures `OrderStatusReport` missing `avg_px` from WS order updates (Python)
- Fixed Binance Spot post-only (`LIMIT_MAKER`) rejection not setting `due_post_only` on `OrderRejected` events (Python and Rust)
- Fixed Binance Rust WS trading API not decoding SBE error responses, losing error codes on rejection
- Fixed Binance Rust WS trading request-response race condition where fast rejections arrived before pending request registration
- Fixed Binance Rust WS trading `OrderRejected` DashMap deadlock when `cleanup_terminal` ran while holding a read guard
- Fixed Binance Spot Rust `connect()` not waiting for WS session authentication before signaling connected
- Fixed Binance Futures account state parsing failing on empty string balances from inactive accounts
- Fixed Bybit demo exec client failing with error 10001 when `/v5/account/fee-rate` is unavailable (#3742), thanks for reporting @jindrichsirucek
- Fixed Bybit HTTP client not retrying on 429 rate limit responses
- Fixed Bybit HTTP cancellation token not resettable after `disconnect()`, causing REST calls to short-circuit on reconnect
- Fixed Bybit WebSocket subscription ACKs confirming all pending topics instead of the acknowledged topic (via `req_id` correlation)
- Fixed Bybit WebSocket failed subscription ACKs (success=false) not triggering `mark_failure` recovery path
- Fixed Bybit spot market orders ignoring `is_quote_quantity` on the order, causing all spot market buys to default to quote currency quantity via the Bybit API
- Fixed Bybit demo mode `submit_order` ignoring `is_leverage` param, hardcoding `false` instead of reading from order params
- Fixed Bybit `trigger_type` ignored on conditional orders, always submitting as `LastPrice` (#3794), thanks for reporting @marco-rigoni
- Fixed Bybit TP/SL conditional orders misclassified as plain Market/Limit during reconciliation
- Fixed Bybit bulk order status reports silently missing conditional (stop/MIT) orders
- Fixed Bybit account state free balance underflowing when locked margin exceeds wallet total during liquidation
- Fixed Databento price precision truncation for fractional tick sizes (#3696), thanks @pandashark
- Fixed Deribit stop order submission missing `trigger_price` and `trigger` fields in Python exec client (#3794), thanks for reporting @marco-rigoni
- Fixed Deribit cancel event lost during WebSocket reconnection gap when `user.orders` subscription update never arrives
- Fixed Deribit duplicate `OrderCanceled` events when cancel RPC response and `user.orders` subscription both emit
- Fixed Deribit `GenerateOrderStatusReport` unable to find closed orders when only `client_order_id` is provided
- Fixed Deribit `next_8_utc` GTD expiry calculation panicking on edge-case timestamps outside nanosecond range
- Fixed Deribit historical trade pagination dropping trades when >1000 share a millisecond boundary
- Fixed Deribit late-listed instruments not propagating to HTTP and WebSocket handler caches
- Fixed Deribit `request_book_snapshot` silently using default 8/8 precision when instrument not in cache
- Fixed Deribit `request_bars` ignoring `limit` parameter
- Fixed Deribit `request_forward_prices` ignoring request `client_id` override
- Fixed Deribit `reset()` leaking stream tasks by replacing cancellation token without canceling the old one
- Fixed Deribit `send_auth_request` silently dropping serialization and channel send errors
- Fixed Deribit `send_subscribe`/`send_unsubscribe` leaving subscription state wedged on command send failure
- Fixed Deribit `VenueOrderId` comparison via unnecessary string conversion in fill report filtering
- Fixed Deribit `OrderSide` conversion using fragile string round-trip instead of `order_side_to_pyo3` in `_submit_order` and `_submit_order_list`
- Fixed Deribit WebSocket `connect()` not clearing subscription state for manual disconnect/reconnect cycles
- Fixed dYdX WebSocket account state parsing failing on empty string balances from zero-equity accounts
- Fixed dYdX WebSocket handler repeatedly emitting `NewInstrumentDiscovered` for uncached instruments on every `v4_markets` update
- Fixed Hyperliquid `_submit_order_list` passing raw Cython orders to Rust, causing `TypeError` on bracket/batch orders (#3763), thanks for reporting @jindrichsirucek
- Fixed Hyperliquid `_modify_order` `OrderSide` conversion using fragile string round-trip instead of `order_side_to_pyo3`
- Fixed Hyperliquid vault orders rejected with "Builder fee has not been approved" when `vault_address` is configured (#3762), thanks for reporting @chester0
- Fixed Interactive Brokers docs `request_ticks` API and add contract example (#3699), thanks @faysou
- Fixed Interactive Brokers live-session synchronization and reconciliation (#3715), thanks @faysou
- Fixed Interactive Brokers shared historical request dedup for concurrent warmup (#3719), thanks @Johnkhk
- Fixed Interactive Brokers historical bar subscriptions not restored after daily gateway restart (#3733), thanks for reporting @bomber555
- Fixed Interactive Brokers inactive order status handling to prevent silent dropping (#3723), thanks @pandashark
- Fixed Interactive Brokers trailing stop order field parsing during reconciliation and open-order updates (#3771), thanks @faysou
- Fixed Interactive Brokers spread instrument not found on restart reconciliation (#3753), thanks @davidsblom
- Fixed Interactive Brokers adapter not reconnecting on error 326 during gateway restart (#3796), thanks @Johnkhk
- Fixed Kraken post-only order rejection not setting `due_post_only` on `OrderRejected` events (Spot and Futures)
- Fixed OKX option conditional order rejection emitting `OrderSubmitted` before `anyhow::bail!`, leaving orders stuck in `Submitted` state
- Fixed OKX `MarketToLimit` orders not rejected for options in HTTP and WebSocket clients
- Fixed OKX `determine_order_type` classifying IV/USD-priced option IOC orders as `Market` when primary `px` field is empty
- Fixed OKX BboTbt quote parsing spamming errors on empty bid/ask arrays for illiquid options by adding `QuoteCache` for partial quote merging
- Fixed OKX `_subscribe_instrument_status` raising `NotImplementedError` instead of being a no-op (status detected via polling)
- Fixed OKX `batch_cancel_all_orders` and `batch_cancel_orders` not emitting `OrderCancelRejected` events for regular (non-algo) batch cancel failures
- Fixed OKX `batch_submit_orders` not removing `order_identities` from dispatch state on batch submit failure
- Fixed OKX business WebSocket requiring API credentials for public-only candle data
- Fixed OKX `parse_fill_report` erroring on zero incremental fill quantity during reconnect replay instead of skipping gracefully
- Fixed OKX `request_position_status_reports` querying positions API for Spot/Margin instruments (unsupported by endpoint)
- Fixed OKX `cancel_all_orders` and `batch_cancel_orders` not seeding `order_identities` for reconciliation-loaded orders
- Fixed OKX `pending_orders`, `pending_cancels`, and `pending_amends` maps leaking entries on WebSocket send failure
- Fixed OKX duplicate fills after WebSocket reconnect when replayed messages have the same `trade_id`
- Fixed OKX HTTP algo order helpers ignoring per-item `sCode`, treating venue rejections as success
- Fixed OKX batch algo cancel not emitting `OrderCancelRejected` events for per-item or batch-level failures
- Fixed OKX spot margin short position quantity exceeding `size_precision` from quote-to-base division
- Fixed OKX `parse_rfc3339_timestamp` silently wrapping negative `i64` nanoseconds to garbage `u64`
- Fixed OKX `update_fee_fill_caches` diverging from shared `parse_fee_currency` (missing non-zero fee warning)
- Fixed OKX duplicate fill early return skipping terminal cleanup for `order_identities` and `order_state_cache`
- Fixed OKX position status reports incorrectly filtered by `start`/`end` time, dropping unchanged open positions
- Fixed OKX `connect()` not passing `instrument_families` for OPTION instrument requests (HTTP 400 from OKX API)
- Fixed OKX `base_url_ws` ignored for private and business WebSocket channels (#3727), thanks for reporting @Stamppot82
- Fixed OKX exec client crash on empty account when OKX returns empty strings for numeric balance fields (#3772), thanks for reporting @ProfitChef
- Fixed Polymarket WebSocket initial vs incremental subscribe (#3717), thanks @Javdu10
- Fixed Polymarket cancel request silently dropped when `venue_order_id` not yet available, causing order to remain open until next reconciliation (Python and Rust)
- Fixed Polymarket market BUY quote-to-base quantity calculation using worst crossing price instead of per-level accumulation (#3747), thanks @filipmacek
- Fixed Polymarket FOK orders stuck in accepted state when WS terminal status update is missed; deferred REST status check resolves after 5s
- Fixed Polymarket fee rate cache serving stale values indefinitely; added 5-minute TTL with graceful fallback on refresh failure
- Fixed Polymarket `calculate_market_price` not bailing when all book levels have zero price or size
- Fixed Polymarket `created_at` timestamp conversion (#3785), thanks @filipmacek
- Fixed Polymarket `ts_init` timestamps on reports and reconciliation (#3786), thanks @filipmacek
- Fixed Polymarket position reconciliation dust cycling by filtering sub-threshold positions and implementing Data API position reports (#3774), thanks @filipmacek
- Fixed Polymarket duplicate inferred fill panic when order update races trade (#3770), thanks for reporting @Javdu10
- Fixed Polymarket `query_order` panic from `block_on` inside async runtime (#3803), thanks for reporting @Javdu10
- Fixed Polymarket order stuck in non-terminal state when fills race with cancel (#3797), thanks for reporting @Javdu10
- Fixed Tardis data client CTRL+C not responding due to signal starvation in `LiveNode` event loop
- Fixed Tardis data client `stop()`/`disconnect()` lifecycle leaving tasks alive or `is_connected` stale
- Fixed Tardis data client `derivative_ticker` not streaming unless manually added to `data_types`

### Internal Improvements
- Added `SpreadQuoteAggregator` (#3698), thanks @faysou
- Added `Params` and `dict` field support for `#[custom_data]` and `@customdataclass` persistence (#3765), thanks @faysou
- Added `BINANCE_GTX_ORDER_REJECT_CODE` and `BINANCE_SPOT_POST_ONLY_REJECT_MSG` constants for reliable post-only rejection detection in Rust
- Added `batch_submit_limit_pair` to `ExecTesterConfig` for order list testing
- Added Python strategy support to v2 `LiveNode` with `add_strategy_from_config`
- Added Python exec algorithm support to v2 `LiveNode` with `add_exec_algorithm_from_config`
- Added `LiveNode` integration tests for actor, strategy, and exec algorithm registration
- Added `LiveNode::add_exec_algorithm` for registering execution algorithms on the Rust live trading node
- Added `LiveNode` stop-handle timeout test for shutdown reliability
- Added `ExecutionEngine` runtime external order creation from `OrderStatusReport` for exchange-generated orders (liquidation, ADL, settlement) not previously in cache (Rust)
- Added `add_exec_algorithm_from_config` PyO3 binding on `LiveNode` with `ImportableExecAlgorithmConfig`
- Added `msgbus::has_endpoint` for endpoint existence checks
- Added backtest margin models, `FXRolloverInterestModule`, `PerContractFeeModel`, and `SimulationModule` trait in Rust
- Added `subscribe_option_greeks` support to `DataTester` in Rust
- Added `WebSocketClient.notify_closed()` for stream-mode callers to signal reader EOF to the controller
- Added pending cancel/update to event emitter in Rust (#3739), thanks @Javdu10
- Added `LimitIfTouched`, `MarketToLimit`, `TrailingStopMarket`, and `TrailingStopLimit` to `transform_order_to_pyo3` Cython-to-PyO3 order converter
- Added PyO3 type assertions to adapter submit-order tests (Hyperliquid, Bybit, Kraken, Architect AX) to catch Cython/PyO3 type boundary regressions
- Added Binance missing `BinanceFilterType` variants and `RawRequests` rate limit type for complete API enum coverage (Rust)
- Added Binance unit tests for liquidation, ADL, settlement, and insurance fill parsing with `is_exchange_generated` detection (Rust)
- Added Binance parametrized tests for `resolve_commission` fallback and `make_venue_position_id` (Rust)
- Added Binance Futures priceMatch (BBO) order support (Rust)
- Added Bybit `BybitWsFrame` enum separating wire-level deserialization from public `BybitWsMessage` API per adapter spec pattern
- Added Bybit frame classification and subscription correlation test coverage (25 handler tests)
- Added Databento feed handler integration tests with mock LSG server
- Added Databento MBO buffering unit tests and proptests
- Added OKX `QuoteCache` integration and option greeks subscription lifecycle tests
- Added OKX reconciliation pagination cap warnings when fetches hit the maximum page limit
- Added OKX trade-level fill dedup via `emitted_trades` DashSet with atomic insert for cross-stream safety
- Added OKX `AlgoCancelContext` and `dispatch_algo_cancels` to centralize algo cancel partitioning and rejection handling
- Added OKX options fill fields (`fill_px_vol`, `fill_px_usd`, `fill_fwd_px`) and order pricing fields (`px_usd`, `px_vol`) to WebSocket and HTTP models
- Added OKX execution client integration tests for trade dedup, algo cancel rejections, batch cancel failures, and concurrent dedup
- Added OKX HTTP mock test for `place_algo_order` `sCode` rejection path
- Added OKX `OKXPriceType`, `OKXSettlementState`, `OKXQuickMarginType` enums for type-safe field deserialization
- Added Tardis HTTP and WebSocket mock server integration tests
- Replaced Binance `WsDispatchState` `DashSet` dedup with `FifoCache` from `nautilus_common` for bounded FIFO eviction with proper `remove()` cleanup
- Replaced Bybit topic string constants with `BybitWsPublicChannel` and `BybitWsPrivateChannel` enum references
- Replaced `AtomicMap` and `AtomicSet` type aliases with newtypes wrapping `ArcSwap` for ergonomic read-heavy concurrent collections
- Replaced `DashMap`/`DashSet` with `AtomicMap`/`AtomicSet` for subscription tracking sets, instrument caches, and bar type caches across all adapters
- Refactored computation of greeks (#3691), thanks @faysou
- Refactored `DataEngine` instrument subscribers to message bus pattern, enabling execution clients to receive live instrument updates via `on_instrument` without polling (#3766), thanks @filipmacek
- Refactored data and execution client startup into two phases with a data event drain between them (#3773), thanks @filipmacek
- Refactored Deribit trade pagination into `TradePaginator` with dedup and cursor logic shared across public trades and fill reports
- Refactored Polymarket HTTP client and improved outcome enum (#3702), thanks @filipmacek
- Refactored Tardis adapter module organization to align with adapter spec (`common/`, `machine/cache.rs`)
- Refactored Tardis `TardisDataClient` with `Credential::resolve()`, centralized URL resolution, and `AHashMap`
- Regenerated Binance Spot SBE codecs from schema 3:3 XML using Real Logic SBE tool v1.37.1
- Moved cache purge timers to base `ExecutionEngine` in Python
- Improved socket clients reconnect and shutdown reliability
- Improved `LiveNode` event loop to use biased `select!` with pinned `ctrl_c` for reliable signal handling
- Improved Binance Spot SBE HTTP parsers to use `block_length` from the message header for end-of-block skip, making decoders forward-compatible with future schema additions
- Improved Databento live price precision handling with maps populated from instrument definitions
- Improved Polymarket Rust adapter (#3726), thanks @filipmacek
- Improved Polymarket execution client (#3734), thanks @filipmacek
- Improved Polymarket adapter in Rust (#3760), thanks @filipmacek
- Refined `TimeEventHandler` ordering and fixed spread quote timestamps (#3764), thanks @faysou
- Refined `SpreadQuoteAggregator` transition from historical to live mode (#3759), thanks @faysou
- Refined handling of instruments in catalog (#3761), thanks @faysou
- Refined `AtomicTime` mode switching and datetime panics
- Refined base catalog interface (#3703), thanks @faysou
- Refined IB option symbols to be OCC compliant (#3731), thanks @faysou
- Standardized `type_name()` across order events and instruments
- Wired `ExecutionManager` into live event loop with full inflight lifecycle (Rust) (#3798), thanks @filipmacek
- Optimized network client performance and add benchmarks
- Upgraded Interactive Brokers `ibapi` to 10.45 (#3804)
- Upgraded Rust (MSRV) to 1.94.1
- Upgraded `capnp` and `capnpc` crates to v0.25.3 (regenerated schemas with 4-space indents and version headers)
- Upgraded `databento` crate to v0.45.0
- Upgraded `datafusion` crate to v53.0.0
- Upgraded `pyo3` crate to v0.28.3
- Upgraded `redis` crate to v1.2.0
- Upgraded `tokio` crate to v1.51.0
- Upgraded `tokio-tungstenite` crate to v0.29.0

### Documentation
- Added Rust tutorial for Betfair book imbalance backtest with `DataActor` walkthrough
- Added Options concept guide with chain architecture, subscription API, strike filtering, and snapshot modes
- Added Greeks concept guide covering venue-provided and local calculator paths
- Added end-to-end data flow and execution flow sequence diagrams to architecture concepts
- Added Events concept guide with event catalog, handler dispatch, and fill-to-position chain
- Added Rust concept guide with capability matrix, project setup, and feature flags
- Added `how_to/configure_live_trading.md` extracted from `concepts/live.md` configuration content
- Added adapter developer guide sections for WS unit tests, close/stream patterns, and split-client architecture
- Added adapter developer guide sections for symbol normalization, status diffing, task management, data event emission, and AuthTracker
- Added adapter developer guide section on configuration best practices: builder defaults, `T` vs `Option<T>` rules, `Default` delegation pattern
- Added adapter developer guide section on `block_on` safety rules and `spawn_task` usage in sync trait methods
- Added OKX options trading section to integration guide with pricing modes, order types, restrictions, and configuration
- Added Group 10 (options trading) to execution testing spec with venue-agnostic test cases
- Added `DeltaNeutralVol` README updates for strangle entry flow, config fields, and usage examples
- Added Binance Link & Trade `clientOrderId` decoding section with usage examples to integration docs
- Added Bybit options support matrix and trading limitations to integration docs
- Added OKX to adapter support tables in Options and Greeks concept guides
- Added option greeks test cases (TC-D62, TC-D63) with config examples to the data testing spec
- Added test style guidance against log capture assertions in developer testing guide
- Rewrote Live Trading concept guide for accuracy (reconciliation, periodic timers, lookback windows)
- Rewrote Custom Data architecture docs for two-mode (Rust/Python) registration
- Improved Value Types concept guide with full arithmetic operator and unary operation docs
- Improved accuracy of Greeks and Options concept guides, thanks @faysou
- Improved `concepts/live.md` to focus on reconciliation explanation, linking to how-to for configuration
- Updated all API reference links to Sphinx HTML paths
- Migrated Python API reference from sphinx-markdown-builder to Sphinx HTML with Furo theme
- Fixed actors timer example referencing nonexistent `on_timer` and `on_alert` hooks