nautechsystems/nautilus_trader · error · anyhow::Error
Cannot cache futures spread: missing option price for {put_i
Error message
Cannot cache futures spread: missing option price for {put_instrument_id} What it means
Same flow as the call-side error: `cache_futures_spread` fetches the PUT option's price via `get_price`, and bails with this error when the cache holds no price for the put instrument. Both legs (call and put) are required to derive the synthetic futures spread.
Source
Thrown at crates/common/src/greeks.rs:1127
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
{
anyhow::bail!(
"Cannot cache futures spread: underlying {underlying_instrument_id} is not a futures contract"
);
}
}View on GitHub (pinned to 18893faf8b)
Solutions
- Subscribe to quotes/trades for the put instrument and wait for a price before calling.
- Verify the put instrument ID encodes the correct strike/expiry/venue.
- Skip strikes lacking put quotes or fall back to a model price; only cache spreads for fully quoted pairs.
- Check contract activity status/expiry before calling.
Example fix
// before
engine.cache_futures_spread(&fut_id, &call_id, &put_id, &underlying)?;
// after
match engine.cache_futures_spread(&fut_id, &call_id, &put_id, &underlying) {
Ok(()) => {}
Err(e) if e.to_string().contains(&put_id.to_string()) => warn!("no put price for {put_id}; skipping"),
Err(e) => return Err(e),
} Defensive patterns
Strategy: fallback
Validate before calling
// Rust: check put leg before computing the spread
if cache.price(&put_instrument_id).is_none() {
return Ok(()); // skip strikes without put 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(&put_id.to_string()) => debug!("no put price {put_id}"),
other => other?,
} Prevention
- Build put IDs programmatically from the chain definition to avoid symbol mistakes.
- Skip illiquid strikes or substitute put spreads from nearby strikes.
- Verify both legs exist and are active before scheduling spread caching.
- Log the full failing instrument ID from the error to spot systematic symbol bugs.
When it happens
Trigger: cache_futures_spread called when the put option instrument has no cached price — no subscription for the put, no quotes at that strike, wrong/swap-corrected put ID, or the put contract has expired.
Common situations: Sparse put quotes on far strikes; subscribing only calls for a synthetic-short strategy; instrument-ID construction mistakes (wrong expiry/strike encoded in the put symbol); pre-market hours with empty option books.
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: missing option price for {call_
- Cannot cache futures spread: no reference futures price for
- option_summary_family_subs mutex poisoned
- DataActor {} must be registered before calling `cache()` - t
- Order {client_order_id} not found
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/131634716bca3d0e.
Report an issue: GitHub.