nautechsystems/nautilus_trader · error

total PnL overflow

Error message

total PnL overflow

What it means

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.

Source

Thrown at crates/model/src/position.rs:1231

    /// Returns total P&L (realized + unrealized) based on the last price.
    ///
    /// # Errors
    ///
    /// Returns an error if unrealized P&L cannot be calculated, the realized and unrealized
    /// currencies differ, or the total cannot be represented as [`Money`].
    pub fn try_total_pnl(&self, last: Price) -> anyhow::Result<Money> {
        let unrealized = self.try_unrealized_pnl(last)?;

        match self.realized_pnl {
            Some(realized) => {
                anyhow::ensure!(
                    realized.currency == unrealized.currency,
                    "realized and unrealized PnL currencies differ"
                );
                realized
                    .checked_add(unrealized)
                    .ok_or_else(|| anyhow::anyhow!("total PnL overflow"))
            }
            None => Ok(unrealized),
        }
    }

    /// Returns total P&L (realized + unrealized) based on the last price.
    #[must_use]
    pub fn total_pnl(&self, last: Price) -> Money {
        self.try_total_pnl(last).unwrap_or_else(|e| {
            log::error!("Error calculating total PnL: {e}");
            Money::zero(self.settlement_currency)
        })
    }

    /// Returns unrealized P&L based on the last price.
    ///
    /// # Errors
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the instrument's multiplier, size precision, and price precision are configured correctly — inflated values overflow Money.
  2. Check for duplicated fills inflating realized PnL and rebuild the position from authoritative history.
  3. Work with raw f64 PnL components (calculate_pnl_raw paths) and aggregate in a wider numeric type if your magnitudes are genuinely large.

Example fix

// before
let total = position.try_total_pnl(last)?; // Err: total PnL overflow
// after: fall back to f64 aggregation for huge magnitudes
let total = match position.try_total_pnl(last) {
    Ok(m) => m,
    Err(_) => {
        let r = position.realized_pnl.map(|m| m.as_f64()).unwrap_or(0.0);
        Money::new(r + position.try_unrealized_pnl(last)?.as_f64(), currency, precision)
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// estimate magnitude before calling
let approx = position.realized_pnl.as_ref().map(|m| m.as_f64()).unwrap_or(0.0)
    + position.try_unrealized_pnl(last)?.as_f64();
if approx.abs() > 9.0e15 { /* use f64 aggregation path */ }

Try / catch

let total = match position.try_total_pnl(last) {
    Ok(m) => m,
    Err(e) if e.to_string().contains("overflow") => {
        let r = position.realized_pnl.map(|m| m.as_f64()).unwrap_or(0.0);
        let u = position.try_unrealized_pnl(last)?.as_f64();
        Money::new(r + u, position.quote_currency, position.size_precision)
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/6d1b2523c8754624. Report an issue: GitHub.