nautechsystems/nautilus_trader · error · anyhow::Error

No liquidity available for market order on {instrument_id}

Error message

No liquidity available for market order on {instrument_id}

What it means

The preview call for an emulated MARKET order succeeded but returned limit_price = None. AX returns a take-through price only when the book has resting liquidity on the side you cross; a None price means the preview found no actionable depth (empty or one-sided book), so the adapter cannot price the IOC limit and refuses to submit rather than send an unpriced order. The remaining_quantity warning above it may also signal a too-thin book for your size.

Source

Thrown at crates/adapters/architect_ax/src/execution.rs:255

                    let response = http_client
                        .inner
                        .preview_aggressive_limit_order(&request)
                        .await
                        .map_err(|e| {
                            anyhow::anyhow!("Failed to preview aggressive limit order: {e}")
                        })?;

                    if response.remaining_quantity > 0 {
                        log::warn!(
                            "Market order book depth insufficient: \
                             filled_qty={} remaining_qty={} for {instrument_id}",
                            response.filled_quantity,
                            response.remaining_quantity,
                        );
                    }

                    let limit_price_decimal = response.limit_price.ok_or_else(|| {
                        anyhow::anyhow!(
                            "No liquidity available for market order on {instrument_id}"
                        )
                    })?;

                    let price =
                        Price::from_decimal_dp(limit_price_decimal, instrument.price_precision())
                            .with_context(|| {
                                format!(
                                    "Failed to convert AX take-through price {limit_price_decimal} for {instrument_id}"
                                )
                            })?;
                    log::debug!("Market order take-through price: {price} for {instrument_id}",);
                    Ok(price)
                }
                .await;

                let price = match preview_result {
                    Ok(price) => price,

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Subscribe to quotes for the instrument and require a bid/ask on both sides before sending market orders
  2. Send an aggressive LIMIT order (e.g. mid +/- k*spread) instead of MARKET so pricing does not depend on preview
  3. Reduce size and/or wait for the book to repopulate, then retry
  4. Confirm the instrument is in its active trading session on AX

Example fix

// before
if best_bid.is_none() || best_ask.is_none() {
    self.submit_order(&factory.market(id, side, qty)); // -> No liquidity
}
// after
if let (Some(bid), Some(ask)) = (best_bid, best_ask) {
    let px = if side == OrderSide::Buy { ask + offset } else { bid - offset };
    self.submit_order(&factory.limit(id, side, qty, px, TimeInForce::Ioc));
}
Defensive patterns

Strategy: validation

Validate before calling

// Require two-sided liquidity before any MARKET order
let book_ok = self.cache.book_order(id, BookType::Default)
    .map(|b| b.best_bid_price().is_some() && b.best_ask_price().is_some())
    .unwrap_or(false);
if !book_ok {
    self.warning("no two-sided book; skipping MARKET order");
    return;
}

Prevention

When it happens

Trigger: Market order on an illiquid symbol whose book is empty on the crossed side (new listing, overnight halt, stale venue book); trading outside the instrument's active hours; requesting more size than the entire book holds.

Common situations: Backtest-only symbols that are actually dead in production; testnet instruments with fake sparse books; market orders sent right at auction open/close where the continuous book is empty.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/35f8453886b5520a. Report an issue: GitHub.