nautechsystems/nautilus_trader · error · anyhow::Error
Cannot cache futures spread: no reference futures…
Error message
Cannot cache futures spread: no reference futures instrument for {futures_instrument_id} What it means
GreeksCalculator::cache_futures_spread derives a futures spread from a call/put option pair against a reference future. Before doing any math it looks up the reference future instrument in the Cache; if the Cache has no instrument registered under futures_instrument_id it bails with this error. The library requires all three instruments (call, put, reference future) to be loaded into the Cache before spread caching can run.
Solutions
- Ensure the reference future instrument is added to the Cache (cache.add_instrument) before calling cache_futures_spread; wait for the instrument-definition response from the data client.
- Verify futures_instrument_id matches an instrument actually defined on the venue (symbol, expiry, venue code all correct).
- If the future is intentionally unavailable, derive the underlying ID differently or skip spread caching and handle the Err instead of unwrapping.
Example fix
// before
let price = greeks.cache_futures_spread(call_id, put_id, future_id)?;
// after
if cache.instrument(&future_id).is_none() {
// request/await the future's instrument definition first
client.request_instrument(&future_id);
return Ok(None);
}
let price = greeks.cache_futures_spread(call_id, put_id, future_id)?; Defensive patterns
Strategy: validation
Validate before calling
// rust
fn have_reference_future(cache: &Cache, future_id: &InstrumentId) -> bool {
cache.instrument(future_id).is_some()
}
if !have_reference_future(&cache, &future_id) {
client.request_instrument(&future_id); // load definition first
return Ok(None);
} Type guard
fn reference_future(cache: &Cache, id: &InstrumentId) -> Option<&InstrumentAny> {
cache.instrument(id)
} Try / catch
match greeks.cache_futures_spread(call_id, put_id, future_id) {
Ok(price) => use(price),
Err(e) if e.to_string().contains("no reference futures instrument") => request_future_definition(),
Err(e) => return Err(e),
} Prevention
- Load all instrument definitions (options and the reference future) before enabling greeks computation.
- Centralize instrument-ID construction so venue/symbol formatting is consistent.
- Subscribe to instrument-definition events and gate spread caching on their arrival.
When it happens
Trigger: Calling cache_futures_spread(call_id, put_id, futures_id) where futures_id was never added to the Cache via add_instrument — e.g. the future definition was not received from the venue/adapter before the options, or the ID is misspelled or belongs to a different venue.
Common situations: Subscribing to option greeks before the data client has downloaded the futures instrument definitions; passing a synthetic or truncated instrument ID (wrong symbol/expiry in the future's ID); switching adapters where only the options were loaded into cache.
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 price for
- Cannot cache futures spread: underlying
- Account not found after cache update
- AX dated contract has different quote and settlement…
- Binance Futures position request has unresolved instrument
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bc6a72b655cb87db.
Report an issue: GitHub.
Appendix: source
Thrown at crates/common/src/greeks.rs:1066
) -> anyhow::Result<Price> {
let cache = self.cache.borrow();
let call_instrument = cache.instrument(&call_instrument_id).cloned();
let put_instrument = cache.instrument(&put_instrument_id).cloned();
let reference_future_instrument = cache.instrument(&futures_instrument_id).cloned();
drop(cache);
let Some(call_instrument) = call_instrument else {
anyhow::bail!(
"Cannot cache futures spread: missing option instrument {call_instrument_id}"
);
};
let Some(put_instrument) = put_instrument else {
anyhow::bail!(
"Cannot cache futures spread: missing option instrument {put_instrument_id}"
);
};
let Some(reference_future_instrument) = reference_future_instrument else {
anyhow::bail!(
"Cannot cache futures spread: no reference futures instrument for {futures_instrument_id}"
);
};
if call_instrument.instrument_class() != InstrumentClass::Option
|| put_instrument.instrument_class() != InstrumentClass::Option
{
anyhow::bail!(
"Cannot cache futures spread: non-option instruments provided call_instrument_id={call_instrument_id} put_instrument_id={put_instrument_id}"
);
}
if call_instrument.option_kind() != Some(OptionKind::Call)
|| put_instrument.option_kind() != Some(OptionKind::Put)
{
anyhow::bail!(
"Cannot cache futures spread: expected call/put pair call_instrument_id={call_instrument_id} put_instrument_id={put_instrument_id}"
);View on GitHub (pinned to 18893faf8b)