{"record":{"id":"6d1b2523c8754624","repo":"nautechsystems/nautilus_trader","slug":"total-pnl-overflow","errorCode":null,"errorMessage":"total PnL overflow","messagePattern":"total PnL overflow","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/position.rs","lineNumber":1231,"sourceCode":"\n    /// Returns total P&L (realized + unrealized) based on the last price.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if unrealized P&L cannot be calculated, the realized and unrealized\n    /// currencies differ, or the total cannot be represented as [`Money`].\n    pub fn try_total_pnl(&self, last: Price) -> anyhow::Result<Money> {\n        let unrealized = self.try_unrealized_pnl(last)?;\n\n        match self.realized_pnl {\n            Some(realized) => {\n                anyhow::ensure!(\n                    realized.currency == unrealized.currency,\n                    \"realized and unrealized PnL currencies differ\"\n                );\n                realized\n                    .checked_add(unrealized)\n                    .ok_or_else(|| anyhow::anyhow!(\"total PnL overflow\"))\n            }\n            None => Ok(unrealized),\n        }\n    }\n\n    /// Returns total P&L (realized + unrealized) based on the last price.\n    #[must_use]\n    pub fn total_pnl(&self, last: Price) -> Money {\n        self.try_total_pnl(last).unwrap_or_else(|e| {\n            log::error!(\"Error calculating total PnL: {e}\");\n            Money::zero(self.settlement_currency)\n        })\n    }\n\n    /// Returns unrealized P&L based on the last price.\n    ///\n    /// # Errors\n    ///","sourceCodeStart":1213,"sourceCodeEnd":1249,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/position.rs#L1213-L1249","documentation":"try_total_pnl returns 'total PnL overflow' when Money::checked_add of realized and unrealized PnL fails because the sum cannot be represented in the Money type (fixed-precision raw value overflow for that currency). The currency check passed, but the arithmetic result exceeds the representable range.","triggerScenarios":"Summing extremely large realized and unrealized PnL values whose combined raw integer amount exceeds the Money precision limit — e.g. very high notional instruments, wrong multiplier (contract size) configured orders of magnitude too large, or accumulated PnL over a very long-lived position.","commonSituations":"Misconfigured contract multiplier or size precision inflating PnL amounts; simulators generating unrealistic prices; running the same fills through the position repeatedly so realized PnL accumulates beyond bounds.","solutions":["Verify the instrument's multiplier, size precision, and price precision are configured correctly — inflated values overflow Money.","Check for duplicated fills inflating realized PnL and rebuild the position from authoritative history.","Work with raw f64 PnL components (calculate_pnl_raw paths) and aggregate in a wider numeric type if your magnitudes are genuinely large."],"exampleFix":"// before\nlet total = position.try_total_pnl(last)?; // Err: total PnL overflow\n// after: fall back to f64 aggregation for huge magnitudes\nlet total = match position.try_total_pnl(last) {\n    Ok(m) => m,\n    Err(_) => {\n        let r = position.realized_pnl.map(|m| m.as_f64()).unwrap_or(0.0);\n        Money::new(r + position.try_unrealized_pnl(last)?.as_f64(), currency, precision)\n    }\n};","handlingStrategy":"try-catch","validationCode":"// estimate magnitude before calling\nlet approx = position.realized_pnl.as_ref().map(|m| m.as_f64()).unwrap_or(0.0)\n    + position.try_unrealized_pnl(last)?.as_f64();\nif approx.abs() > 9.0e15 { /* use f64 aggregation path */ }","typeGuard":null,"tryCatchPattern":"let total = match position.try_total_pnl(last) {\n    Ok(m) => m,\n    Err(e) if e.to_string().contains(\"overflow\") => {\n        let r = position.realized_pnl.map(|m| m.as_f64()).unwrap_or(0.0);\n        let u = position.try_unrealized_pnl(last)?.as_f64();\n        Money::new(r + u, position.quote_currency, position.size_precision)\n    }\n    Err(e) => return Err(e),\n};","preventionTips":["Verify instrument multiplier and precision configuration — inflated values overflow Money.","Watch for duplicate fills inflating realized PnL over long-lived positions.","Fall back to f64 aggregation when PnL magnitudes approach Money limits."],"tags":["position","pnl","overflow","money","rust"],"backgroundTag":"value-out-of-range","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"}