nautechsystems/nautilus_trader · error · anyhow::Error

Cannot cache futures spread: missing option price for {call_

Error message

Cannot cache futures spread: missing option price for {call_instrument_id}

What it means

After fetching the reference futures price, `cache_futures_spread` fetches the CALL option's price via `get_price`. If no price is cached for the call instrument the spread cannot be computed and it bails with this error.

Source

Thrown at crates/common/src/greeks.rs:1122

        if call_instrument.strike_price() != put_instrument.strike_price() {
            anyhow::bail!(
                "Cannot cache futures spread: strike prices differ call_instrument_id={call_instrument_id} put_instrument_id={put_instrument_id}"
            );
        }

        if call_instrument.expiration_ns() != put_instrument.expiration_ns() {
            anyhow::bail!(
                "Cannot cache futures spread: expiration dates differ call_instrument_id={call_instrument_id} put_instrument_id={put_instrument_id}"
            );
        }

        let reference_future_price = self.get_price_object(&futures_instrument_id).ok_or_else(|| {
            anyhow::anyhow!(
                "Cannot cache futures spread: no reference futures price for {futures_instrument_id}"
            )
        })?;
        let call_price = self.get_price(&call_instrument_id).ok_or_else(|| {
            anyhow::anyhow!(
                "Cannot cache futures spread: missing option price for {call_instrument_id}"
            )
        })?;
        let put_price = self.get_price(&put_instrument_id).ok_or_else(|| {
            anyhow::anyhow!(
                "Cannot cache futures spread: missing option price for {put_instrument_id}"
            )
        })?;

        let underlying_instrument_id =
            InstrumentId::from(format!("{call_underlying}.{}", call_instrument_id.venue));

        // Reject if the underlying is present in cache but is not a future
        {
            let cache = self.cache.borrow();
            if let Some(underlying) = cache.instrument(&underlying_instrument_id)
                && underlying.instrument_class() != InstrumentClass::Future
            {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Subscribe to quotes/trades for the call instrument and confirm a price exists before caching the spread.
  2. Verify call/put instrument IDs are not swapped and match the same expiration.
  3. Pick a strike with active market data, or retry after the first quote tick.
  4. Handle the error at call sites and skip the synthetic-price caching for strikes without data.

Example fix

// before
engine.cache_futures_spread(&fut_id, &call_id, &put_id, &underlying)?;
// after
if engine.cache.price(&call_id).is_none() {
    return Ok(()); // skip strikes without market data
}
engine.cache_futures_spread(&fut_id, &call_id, &put_id, &underlying)?;
Defensive patterns

Strategy: fallback

Validate before calling

// Rust: check call leg before computing the spread
if cache.price(&call_instrument_id).is_none() {
    return Ok(()); // skip strikes without call quotes
}

Type guard

fn price_or_skip(cache: &Cache, id: &InstrumentId) -> Option<f64> { cache.price(id) }

Try / catch

match engine.cache_futures_spread(&fut_id, &call_id, &put_id, &u) {
    Err(e) if e.to_string().contains(&call_id.to_string()) => debug!("no call price {call_id}"),
    other => other?,
}

Prevention

When it happens

Trigger: cache_futures_spread called when the call option instrument has no quote/trade price in the cache (options not subscribed, illiquid strike with no market, wrong call instrument ID, or call expired).

Common situations: Deep OTM/ITM strikes with no quotes; subscribing to a subset of the chain; passing swapped call/put IDs; running during the first milliseconds after subscription before quotes arrive.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/2e00c0f10f86b7f7. Report an issue: GitHub.