{"record":{"id":"91c1e86a97c9f791","repo":"nautechsystems/nautilus_trader","slug":"cannot-calculate-price-impact-the-spot-price-befo","errorCode":null,"errorMessage":"Cannot calculate price impact, the spot price before is not set","messagePattern":"Cannot calculate price impact, the spot price before is not set","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/defi/data/swap_trade_info.rs","lineNumber":100,"sourceCode":"    /// excluding fees. This is the percentage change in spot price from\n    /// before to after the swap.\n    ///\n    /// # Returns\n    /// Price impact in basis points (10000 = 100%)\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the spot price before the swap is not set or is zero.\n    pub fn get_price_impact_bps(&self) -> anyhow::Result<u32> {\n        if let Some(spot_price_before) = self.spot_price_before {\n            Self::check_spot_price_before(spot_price_before, PriceMetric::Impact)?;\n            let price_change = self.spot_price - spot_price_before;\n            let price_impact =\n                (price_change.as_decimal() / spot_price_before.as_decimal()).abs() * dec!(10_000);\n\n            Ok(price_impact.round().to_u32().unwrap_or(0))\n        } else {\n            anyhow::bail!(\"Cannot calculate price impact, the spot price before is not set\");\n        }\n    }\n\n    /// Calculates slippage in basis points (requires token references for decimal adjustment).\n    ///\n    /// Slippage includes both price impact and fees, representing the total\n    /// deviation from the spot price before the swap. This measures the total\n    /// cost to the trader.\n    ///\n    /// # Returns\n    /// Total slippage in basis points (10000 = 100%)\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the spot price before the swap is not set or is zero.\n    pub fn get_slippage_bps(&self) -> anyhow::Result<u32> {\n        if let Some(spot_price_before) = self.spot_price_before {\n            Self::check_spot_price_before(spot_price_before, PriceMetric::Slippage)?;","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/defi/data/swap_trade_info.rs#L82-L118","documentation":"SwapTradeInfo::get_price_impact_bps computes price impact as (spot_price - spot_price_before)/spot_price_before * 10_000 bps. The calculation requires the prior spot price to be a positive, set Price; if spot_price_before is zero/unset the library bails instead of dividing by zero or returning a meaningless impact. The caller must supply a valid pre-swap spot price.","triggerScenarios":"Calling get_price_impact_bps with a spot_price_before argument equal to zero (e.g. Price::zero or default), typically when the pre-trade price was never captured from the swap's sqrt price data.","commonSituations":"Backtesting code that constructs SwapTradeInfo without computing the pre-swap price; pools where the previous price was never recorded; default-initialized Price fields passing through; unit tests probing the zero guard.","solutions":["Compute the pre-swap spot price from the pool's sqrt_price_x96 before the swap and pass it in","Guard the call: only invoke get_price_impact_bps when spot_price_before > 0","If no prior price exists, treat impact as unavailable (skip or record None) rather than passing zero","Verify the SwapTradeInfo builder/construction path sets spot_price_before from actual event data"],"exampleFix":"// before\nlet impact = swap.get_price_impact_bps(Price::zero())?;\n// after\nif spot_before.is_zero() {\n    return Ok(None); // impact not computable\n}\nlet impact = swap.get_price_impact_bps(spot_before)?;","handlingStrategy":"validation","validationCode":"if spot_price_before.is_zero() || spot_price_before.as_decimal() <= dec!(0) {\n    // cannot compute impact; skip or record None\n}","typeGuard":"fn has_valid_spot_price_before(p: &Price) -> bool { !p.is_zero() && p.as_decimal() > rust_decimal::Decimal::ZERO }","tryCatchPattern":"match swap.get_price_impact_bps(spot_before) {\n    Ok(impact) => Some(impact),\n    Err(e) if e.to_string().contains(\"spot price before is not set\") => None,\n    Err(e) => return Err(e),\n}","preventionTips":["Always capture the pre-swap spot price from the pool's sqrt price before building SwapTradeInfo","Never pass default/zero Price values into bps calculations","Return Option/Result for impact when the pre-price may be unavailable","Unit-test the zero-price path in swap analytics"],"tags":["rust","defi","swap","division-by-zero","price"],"backgroundTag":"invalid-argument-value","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"}