{"record":{"id":"112981d2e9747814","repo":"nautechsystems/nautilus_trader","slug":"no-price-available-for-underlying-instrument-id","errorCode":null,"errorMessage":"No price available for {underlying_instrument_id}","messagePattern":"No price available for (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/greeks.rs","lineNumber":779,"sourceCode":"        }\n\n        // Only fall back to cached futures spread when the underlying is a future\n        // (or absent from the cache, since the spread was explicitly cached).\n        let is_future_or_absent = {\n            let cache = self.cache.borrow();\n            cache\n                .instrument(underlying_instrument_id)\n                .is_none_or(|inst| inst.instrument_class() == InstrumentClass::Future)\n        };\n\n        if is_future_or_absent\n            && let Some(underlying_price) =\n                self.get_cached_futures_spread_price(*underlying_instrument_id)\n        {\n            return Ok(underlying_price.as_f64());\n        }\n\n        anyhow::bail!(\"No price available for {underlying_instrument_id}\")\n    }\n\n    /// Modifies delta, gamma, and vega based on beta weighting and percentage calculations.\n    ///\n    /// The beta weighting of delta and gamma follows this equation linking the returns of a stock x to the ones of an index I:\n    /// (x - x0) / x0 = alpha + beta (I - I0) / I0 + epsilon\n    ///\n    /// beta can be obtained by linear regression of `stock_return` = alpha + beta `index_return`, it's equal to:\n    /// beta = Covariance(`stock_returns`, `index_returns`) / Variance(`index_returns`)\n    ///\n    /// Considering alpha == 0:\n    /// x = x0 + beta x0 / I0 (I-I0)\n    /// I = I0 + 1 / beta I0 / x0 (x - x0)\n    ///\n    /// These two last equations explain the beta weighting below, considering the price of an option is V(x) and delta and gamma\n    /// are the first and second derivatives respectively of V.\n    ///\n    /// Vega beta weighting follows the same change of variable with implied volatility and a volatility index.","sourceCodeStart":761,"sourceCodeEnd":797,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/greeks.rs#L761-L797","documentation":"`get_underlying_price` could not determine a price for the underlying instrument: there was no cached quote/price for the underlying and no cached futures-spread price either. The greeks calculation (e.g. `calculate_option_greeks`) requires the underlying spot price as input, so it aborts with this bail when no price source yields a value.","triggerScenarios":"Calling `calculate_option_greeks` when the underlying instrument has no cached quote/price (market data never subscribed, stale cache, or outside trading hours) and `get_cached_futures_spread_price` also returns None for that underlying.","commonSituations":"Running greeks calculations before subscribing to market data for the underlying; weekend/holiday sessions with no quotes; cash/margin accounts where the underlying trades on a different venue than cached; futures-spread fallback not yet populated via `cache_futures_spread`.","solutions":["Subscribe to quotes for the underlying instrument and wait for at least one price before computing greeks","Call `cache_futures_spread` to populate the spread-based fallback price","Guard the calculation: check the cache for an underlying price and skip/log if absent instead of erroring"],"exampleFix":"// before\nlet greeks = greeks_calc.calculate_option_greeks(&option_id, ...)?;\n// after\nif let Some(price) = cache.price(&underlying_id, PriceType::Last) {\n    let greeks = greeks_calc.calculate_option_greeks(&option_id, ...)?;\n} else {\n    tracing::warn!(\"no underlying price for {underlying_id}, skipping greeks\");\n}","handlingStrategy":"fallback","validationCode":"fn underlying_price_available(cache: &Cache, underlying: &InstrumentId) -> bool {\n    cache.price(underlying, PriceType::Last).is_some()\n        || cache.quote(underlying).is_some()\n}","typeGuard":null,"tryCatchPattern":"match greeks_calc.calculate_option_greeks(&option_id, ...) {\n    Ok(g) => g,\n    Err(e) if e.to_string().starts_with(\"No price available for\") => {\n        tracing::warn!(\"{e}; skipping greeks update\");\n        return Ok(());\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Subscribe to underlying quotes before enabling greeks calculations","Populate the futures-spread fallback via cache_futures_spread at startup","Skip greeks updates gracefully when no quote has arrived yet"],"tags":["rust","greeks","market-data","missing-price"],"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-14T05:17:10.506Z"}