{"record":{"id":"81d940fb2a198f9e","repo":"nautechsystems/nautilus_trader","slug":"inverse-notional-calculation-overflow","errorCode":null,"errorMessage":"inverse notional calculation overflow","messagePattern":"inverse notional calculation overflow","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/instruments/mod.rs","lineNumber":720,"sourceCode":"\npub(crate) fn try_notional_value(\n    quantity: Quantity,\n    price: Price,\n    multiplier: Quantity,\n    is_inverse: bool,\n    use_quote_for_inverse: bool,\n    currency: Currency,\n) -> anyhow::Result<Money> {\n    let amount = if is_inverse && !use_quote_for_inverse {\n        anyhow::ensure!(\n            price.is_positive(),\n            \"price must be positive for inverse notional valuation\"\n        );\n        quantity\n            .as_decimal()\n            .checked_mul(multiplier.as_decimal())\n            .and_then(|value| value.checked_div(price.as_decimal()))\n            .ok_or_else(|| anyhow::anyhow!(\"inverse notional calculation overflow\"))?\n    } else if is_inverse {\n        quantity.as_decimal()\n    } else {\n        quantity\n            .as_decimal()\n            .checked_mul(multiplier.as_decimal())\n            .and_then(|value| value.checked_mul(price.as_decimal()))\n            .ok_or_else(|| anyhow::anyhow!(\"notional calculation overflow\"))?\n    };\n\n    Money::from_decimal(amount, currency).map_err(Into::into)\n}\n\nimpl Display for CurrencyPair {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(\n            f,\n            \"{}(instrument_id='{}', tick_scheme='{}', price_precision={}, size_precision={}, \\","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/instruments/mod.rs#L702-L738","documentation":"For inverse instruments the notional is (quantity * multiplier) / price computed with checked Decimal arithmetic. If any checked_mul/checked_div overflows or otherwise fails (None), try_notional_value raises this overflow error rather than silently producing a wrong value.","triggerScenarios":"try_calculate_notional_value on an inverse instrument where quantity * multiplier (or its division by price) exceeds the decimal arithmetic capacity — e.g. astronomically large quantity/multiplier values or a near-zero price inflating the quotient.","commonSituations":"Valuing positions with wrongly scaled multiplier units, instruments configured with huge multipliers, or extreme prices near zero in stressed backtests causing the division to blow past Decimal bounds.","solutions":["Sanity-check instrument multiplier and quantity magnitudes; correct the instrument definition if the multiplier is misconfigured.","Validate quantity against instrument.max_quantity before valuation.","Handle the Result from the try_ API and clamp/log rather than propagating a panic from the panicking wrapper."],"exampleFix":"// before\nlet notional = instrument.calculate_notional_value(price, huge_qty, None)?;\n// after\nanyhow::ensure!(huge_qty <= instrument.max_quantity(), \"quantity out of bounds\");\nlet notional = instrument.calculate_notional_value(price, huge_qty, None)?;","handlingStrategy":"try-catch","validationCode":"if qty > instrument.max_quantity() || multiplier.as_f64() > 1e12 { return Err(TradeError::NotionalOverflowRisk); }","typeGuard":null,"tryCatchPattern":"// Rust\nlet notional = instrument\n    .try_calculate_notional_value(price, qty, None)\n    .map_err(|e| { log::error!(\"inverse notional overflow: {e}\"); TradeError::NotionalOverflow })?;","preventionTips":["Validate instrument multiplier configuration at startup","Clamp quantities to instrument bounds before valuation","Prefer try_calculate_notional_value and handle Err instead of the panicking wrapper"],"tags":["notional","overflow","decimal-arithmetic","inverse-instrument"],"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-14T05:17:10.506Z"}