nautechsystems/nautilus_trader · error · anyhow::Error
Cannot cache futures spread: no reference futures instrument
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.
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)
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: underlying {underlying_instrume
- Cannot cache futures spread: no reference futures price for
- Instrument not found in cache: {symbol}
- `close_position` cannot be combined with `reduce_only` on Bi
- DataActor {} must be registered before calling `cache()` - t
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bc6a72b655cb87db.
Report an issue: GitHub.