nautechsystems/nautilus_trader · error · anyhow::Error
Cannot cache futures spread: no reference futures price for
Error message
Cannot cache futures spread: no reference futures price for {futures_instrument_id} What it means
`cache_futures_spread` computes a synthetic futures spread price from call/put option prices against a reference futures price. Before anything else it fetches the reference futures price via `get_price_object`; if the cache holds no price for that futures instrument it bails with this error, because the spread cannot be anchored without it.
Source
Thrown at crates/common/src/greeks.rs:1117
anyhow::bail!(
"Cannot cache futures spread: option underlyings differ call_instrument_id={call_instrument_id} put_instrument_id={put_instrument_id}"
);
}
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 futureView on GitHub (pinned to 18893faf8b)
Solutions
- Subscribe to quote/trade data for futures_instrument_id before calling cache_futures_spread.
- Check the futures instrument ID is the actual contract (e.g. ESZ5.GLBX), not the synthetic underlying.
- Verify the contract is still active/not expired and present in the cache.
- Seed the reference price in the cache if the venue does not stream it, or fall back to an earlier cached price.
Example fix
// before
engine.cache_futures_spread(&fut_id, &call_id, &put_id, &underlying)?;
// after
if engine.cache.price(&fut_id).is_none() {
engine.subscribe_quotes(fut_id)?; // ensure reference future has data
}
engine.cache_futures_spread(&fut_id, &call_id, &put_id, &underlying)?; Defensive patterns
Strategy: validation
Validate before calling
// Rust: verify reference future price exists first
if cache.price(&futures_instrument_id).is_none() {
anyhow::bail!("reference future {futures_instrument_id} not priced; subscribe before caching spread");
} Type guard
fn has_price(cache: &Cache, id: &InstrumentId) -> bool { cache.price(id).is_some() } Try / catch
if let Err(e) = engine.cache_futures_spread(&fut_id, &call_id, &put_id, &underlying) {
warn!("spread cache skipped: {e}");
} Prevention
- Subscribe to the underlying futures contract, not just options.
- Confirm contract expiry/rollover so IDs never point at delisted contracts.
- Run spread caching only after market-data warm-up completes.
- Keep a lookup of active contracts per venue instead of hard-coded symbols.
When it happens
Trigger: Calling cache_futures_spread(futures_instrument_id, call_instrument_id, put_instrument_id, ...) where the reference futures instrument has no cached price (no subscription, no trade/quote yet, or wrong instrument ID).
Common situations: Subscribing only to options but not the underlying future; referencing an expired or delisted futures contract; using the options-chain synthetic underlying ID instead of the tradable futures ID; calling before first market data arrives on a cold start.
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
- Cannot cache futures spread: no reference futures instrument
- Cannot cache futures spread: underlying {underlying_instrume
- Cannot cache futures spread: missing option price for {call_
- Cannot cache futures spread: missing option price for {put_i
- Instrument not found in cache: {symbol}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/223174dd480609ec.
Report an issue: GitHub.