{"record":{"id":"1acf8fe59595bbf9","repo":"nautechsystems/nautilus_trader","slug":"invalid-notional-value-1acf8f","errorCode":null,"errorMessage":"invalid notional value","messagePattern":"invalid notional value","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/position.rs","lineNumber":1385,"sourceCode":"        crate::instruments::try_notional_value(\n            self.quantity,\n            last,\n            self.multiplier,\n            self.is_inverse,\n            false,\n            currency,\n        )\n    }\n\n    /// Calculates the notional value based on the last price.\n    ///\n    /// # Panics\n    ///\n    /// Panics if [`Position::try_notional_value`] returns an error.\n    #[must_use]\n    pub fn notional_value(&self, last: Price) -> Money {\n        self.try_notional_value(last)\n            .expect(\"invalid notional value\")\n    }\n\n    /// Returns the last `OrderFilled` event for the position (if any after purging).\n    #[must_use]\n    pub fn last_event(&self) -> Option<OrderFilled> {\n        self.events.last().cloned()\n    }\n\n    /// Returns the last `TradeId` for the position (if any after purging).\n    #[must_use]\n    pub fn last_trade_id(&self) -> Option<TradeId> {\n        self.events.last().map(|e| e.trade_id)\n    }\n\n    /// Returns whether the position is long (positive quantity).\n    #[must_use]\n    pub fn is_long(&self) -> bool {\n        self.side == PositionSide::Long","sourceCodeStart":1367,"sourceCodeEnd":1403,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/position.rs#L1367-L1403","documentation":"Position::notional_value() is the panicking wrapper around try_notional_value(), which computes notional value for the instrument's quote (or settlement) currency. It panics when try_notional_value errors — e.g. unsupported/missing instrument definition data such as multiplier, size increment, or quote/settlement currency for exotic instrument types.","triggerScenarios":"Calling notional_value(last) on a position whose instrument cannot compute notional (e.g. a Quanto instrument lacking settlement currency info, or instrument not registered with the cache so multiplier/precision lookups fail).","commonSituations":"Portfolio/PnL analytics over instruments that were never added to the instrument cache; custom instrument definitions missing multiplier or settlement-currency fields; using the infallible API during tests with incomplete instruments.","solutions":["Use Position::try_notional_value(last) and handle the Err case instead of the panicking notional_value","Register the instrument in the cache before computing position metrics","Fix the instrument definition (multiplier, quote/settlement currency) so notional is computable"],"exampleFix":"// before\nlet notional = position.notional_value(last);\n// after\nlet notional = match position.try_notional_value(last) {\n    Ok(m) => m,\n    Err(e) => { log::error!(\"notional unavailable: {e}\"); return; }\n};","handlingStrategy":"try-catch","validationCode":"// Rust: prefer the fallible API\nlet notional = position.try_notional_value(last)?;","typeGuard":"// check instrument is registered and has multiplier/settlement currency before computing","tryCatchPattern":"// Python (pyo3 bindings)\ntry:\n    notional = position.notional_value(last)\nexcept Exception as e:\n    log.warning(f\"notional unavailable: {e}\")\n    notional = None","preventionTips":["Use try_notional_value in production code; reserve notional_value for infallible paths","Register instruments in the cache before position analytics","Complete instrument definitions (multiplier, quote/settlement currency) for exotic types"],"tags":["rust","panic","positions","notional"],"backgroundTag":"internal-invariant-violation","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"}