{"record":{"id":"146ef5c90bdeb6cc","repo":"nautechsystems/nautilus_trader","slug":"cannot-cache-futures-spread-missing-option-instru","errorCode":null,"errorMessage":"Cannot cache futures spread: missing option instrument {call_instrument_id}","messagePattern":"Cannot cache futures spread: missing option instrument (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/greeks.rs","lineNumber":1056,"sourceCode":"    /// Cache a futures spread derived from a call/put pair against a reference future.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if instruments or prices are missing or inconsistent.\n    pub fn cache_futures_spread(\n        &self,\n        call_instrument_id: InstrumentId,\n        put_instrument_id: InstrumentId,\n        futures_instrument_id: InstrumentId,\n    ) -> anyhow::Result<Price> {\n        let cache = self.cache.borrow();\n        let call_instrument = cache.instrument(&call_instrument_id).cloned();\n        let put_instrument = cache.instrument(&put_instrument_id).cloned();\n        let reference_future_instrument = cache.instrument(&futures_instrument_id).cloned();\n        drop(cache);\n\n        let Some(call_instrument) = call_instrument else {\n            anyhow::bail!(\n                \"Cannot cache futures spread: missing option instrument {call_instrument_id}\"\n            );\n        };\n        let Some(put_instrument) = put_instrument else {\n            anyhow::bail!(\n                \"Cannot cache futures spread: missing option instrument {put_instrument_id}\"\n            );\n        };\n        let Some(reference_future_instrument) = reference_future_instrument else {\n            anyhow::bail!(\n                \"Cannot cache futures spread: no reference futures instrument for {futures_instrument_id}\"\n            );\n        };\n\n        if call_instrument.instrument_class() != InstrumentClass::Option\n            || put_instrument.instrument_class() != InstrumentClass::Option\n        {\n            anyhow::bail!(","sourceCodeStart":1038,"sourceCodeEnd":1074,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/greeks.rs#L1038-L1074","documentation":"`cache_futures_spread` builds a synthetic futures-spread price cache from a call/put option pair and a reference future. This error is raised when the call option instrument cannot be found in the cache, so the spread cannot be computed. It indicates the required instrument was never added to (or was dropped from) the `Cache`.","triggerScenarios":"Calling `cache_futures_spread(...)` with a `call_instrument_id` that has no instrument registered in the cache — e.g. the ID was constructed from a symbol string rather than a loaded instrument definition, or instruments were loaded for a different venue.","commonSituations":"Instrument definitions for the option chain not loaded at startup; typo or wrong venue in the instrument ID; cache cleared between load and calculation; tests constructing IDs without registering instruments first.","solutions":["Ensure all option chain instruments are loaded and added to the cache before calling `cache_futures_spread`","Log/verify the exact `call_instrument_id` string and compare against `cache.instrument_ids()`","Fix the venue/symbol construction that produced the call instrument ID"],"exampleFix":"// before\ngreeks.cache_futures_spread(&call_id, &put_id, &future_id)?;\n// after\nif cache.instrument(&call_id).is_none() {\n    anyhow::bail!(\"call option {call_id} not in cache; load instruments first\");\n}\ngreeks.cache_futures_spread(&call_id, &put_id, &future_id)?;","handlingStrategy":"validation","validationCode":"fn ensure_cached(cache: &Cache, id: &InstrumentId) -> Result<(), String> {\n    if cache.instrument(id).is_some() { Ok(()) } else { Err(format!(\"{id} not in cache\")) }\n}","typeGuard":null,"tryCatchPattern":"match greeks.cache_futures_spread(&call_id, &put_id, &future_id) {\n    Ok(()) => (),\n    Err(e) if e.to_string().contains(\"missing option instrument\") => {\n        tracing::warn!(\"{e}; reload option chain instruments\");\n        return Ok(());\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Load the complete option chain (calls and puts) into the cache at startup","Validate all referenced instrument IDs exist in the cache before spread calculations","Keep instrument definitions and market-data subscriptions in sync"],"tags":["rust","greeks","cache","missing-instrument"],"backgroundTag":"resource-not-found","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}