nautechsystems/nautilus_trader · error

Bid required

Error message

Bid required

What it means

For `TriggerType::Default`, `BidAsk`, or `LastOrBidAsk`, the trailing calculation is based on the current bid/ask quotes; the function requires both. The `bid: Option<Price>` argument was `None`, so no basis price exists to apply the trailing offset against and the call fails with 'Bid required'.

Source

Thrown at crates/execution/src/trailing.rs:136

    };

    match trigger_type {
        TriggerType::LastPrice | TriggerType::MarkPrice => {
            let last = last.ok_or(OrderError::InvalidStateTransition)?;
            let cand_trigger = compute(trailing_offset, last)?;
            new_trigger_price = maybe_move(&mut trigger_price, cand_trigger, better_trigger);

            if order_type == OrderType::TrailingStopLimit {
                let limit_offset = order.limit_offset().ok_or_else(|| {
                    anyhow::anyhow!("Missing `limit_offset` for trailing stop limit calculation")
                })?;
                let cand_limit = compute(limit_offset, last)?;
                new_limit_price = maybe_move(&mut limit_price, cand_limit, better_limit);
            }
        }
        TriggerType::Default | TriggerType::BidAsk | TriggerType::LastOrBidAsk => {
            let (bid, ask) = (
                bid.ok_or_else(|| anyhow::anyhow!("Bid required"))?,
                ask.ok_or_else(|| anyhow::anyhow!("Ask required"))?,
            );
            let basis = match order_side {
                OrderSide::Buy => ask,
                OrderSide::Sell => bid,
            };
            let cand_trigger = compute(trailing_offset, basis)?;
            new_trigger_price = maybe_move(&mut trigger_price, cand_trigger, better_trigger);

            if order_type == OrderType::TrailingStopLimit {
                let limit_offset = order.limit_offset().ok_or_else(|| {
                    anyhow::anyhow!("Missing `limit_offset` for trailing stop limit calculation")
                })?;
                let cand_limit = compute(limit_offset, basis)?;
                new_limit_price = maybe_move(&mut limit_price, cand_limit, better_limit);
            }

            if trigger_type == TriggerType::LastOrBidAsk {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure a quote subscription (bid/ask) is active for the instrument and pass the current top-of-book `bid`/`ask` to the call.
  2. Skip the trailing update until both bid and ask are available (return early on `bid.is_none() || ask.is_none()`).
  3. Switch the order's `trigger_type` to `LastPrice`/`MarkPrice` if quotes are not available but last-trade data is, and pass `last`.
  4. Check data-engine quote cache before invoking; log a warning and defer the update instead of erroring.

Example fix

// before
let (new_trigger, new_limit) = trailing_stop_calculate(increment, None, &order, None, None, None)?;
// after
let (bid, ask) = (cache.bid(&instrument_id), cache.ask(&instrument_id));
if let (Some(bid), Some(ask)) = (bid, ask) {
    let (new_trigger, new_limit) = trailing_stop_calculate(increment, None, &order, Some(bid), Some(ask), None)?;
}
Defensive patterns

Strategy: validation

Validate before calling

fn quotes_ready(bid: Option<Price>, ask: Option<Price>, trigger_type: TriggerType) -> bool {
    matches!(trigger_type, TriggerType::Default | TriggerType::BidAsk | TriggerType::LastOrBidAsk)
        ? bid.is_some() && ask.is_some()
        : true
}

Try / catch

match trailing_stop_calculate(increment, None, &order, bid, ask, last) {
    Err(e) if e.to_string().contains("Bid required") => {
        log::debug!("deferring trailing update: no bid quote yet for {}", order.instrument_id());
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `trailing_stop_calculate`/`update_trailing_stop_order` with `trigger_type` in {Default, BidAsk, LastOrBidAsk} while passing `bid: None` — e.g. no book top available for the instrument at update time.

Common situations: Running the update before the first quote arrives for the instrument; subscribing to trade/last-price data only while the order's trigger type needs quotes; a data outage or stale feed clearing the cached bid; an illiquid symbol with one-sided book where bid is absent.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/8e1c283f12fc0b38. Report an issue: GitHub.