nautechsystems/nautilus_trader · error

invalid notional value

Error message

invalid notional value

What it means

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.

Source

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

        crate::instruments::try_notional_value(
            self.quantity,
            last,
            self.multiplier,
            self.is_inverse,
            false,
            currency,
        )
    }

    /// Calculates the notional value based on the last price.
    ///
    /// # Panics
    ///
    /// Panics if [`Position::try_notional_value`] returns an error.
    #[must_use]
    pub fn notional_value(&self, last: Price) -> Money {
        self.try_notional_value(last)
            .expect("invalid notional value")
    }

    /// Returns the last `OrderFilled` event for the position (if any after purging).
    #[must_use]
    pub fn last_event(&self) -> Option<OrderFilled> {
        self.events.last().cloned()
    }

    /// Returns the last `TradeId` for the position (if any after purging).
    #[must_use]
    pub fn last_trade_id(&self) -> Option<TradeId> {
        self.events.last().map(|e| e.trade_id)
    }

    /// Returns whether the position is long (positive quantity).
    #[must_use]
    pub fn is_long(&self) -> bool {
        self.side == PositionSide::Long

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use Position::try_notional_value(last) and handle the Err case instead of the panicking notional_value
  2. Register the instrument in the cache before computing position metrics
  3. Fix the instrument definition (multiplier, quote/settlement currency) so notional is computable

Example fix

// before
let notional = position.notional_value(last);
// after
let notional = match position.try_notional_value(last) {
    Ok(m) => m,
    Err(e) => { log::error!("notional unavailable: {e}"); return; }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: prefer the fallible API
let notional = position.try_notional_value(last)?;

Type guard

// check instrument is registered and has multiplier/settlement currency before computing

Try / catch

// Python (pyo3 bindings)
try:
    notional = position.notional_value(last)
except Exception as e:
    log.warning(f"notional unavailable: {e}")
    notional = None

Prevention

When it happens

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

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

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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