nautechsystems/nautilus_trader · error

Invalid `confidence` for `ExpectedShortfall`

Error message

Invalid `confidence` for `ExpectedShortfall`

What it means

ExpectedShortfall::new is the infallible constructor wrapping new_checked, which validates that confidence is finite and strictly within (0, 1) (e.g. 0.95 or 0.99). The expect panics when the supplied value fails validation, since the panicking constructor is meant for known-good constants.

Source

Thrown at crates/analysis/src/statistics/expected_shortfall.rs:83

    ///
    /// Returns an error if `confidence` is not finite and in the range `(0, 1)`.
    pub fn new_checked(confidence: Option<f64>) -> anyhow::Result<Self> {
        let confidence = confidence.unwrap_or(0.95);
        check_predicate_true(
            confidence.is_finite() && confidence > 0.0 && confidence < 1.0,
            "confidence must be finite and in the range (0, 1)",
        )?;
        Ok(Self { confidence })
    }

    /// Creates a new [`ExpectedShortfall`] instance.
    ///
    /// # Panics
    ///
    /// Panics if `confidence` is not finite and in the range `(0, 1)`.
    #[must_use]
    pub fn new(confidence: Option<f64>) -> Self {
        Self::new_checked(confidence).expect("Invalid `confidence` for `ExpectedShortfall`")
    }
}

impl Display for ExpectedShortfall {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Expected Shortfall (confidence {})", self.confidence)
    }
}

impl PortfolioStatistic for ExpectedShortfall {
    type Item = f64;

    fn name(&self) -> String {
        self.to_string()
    }

    fn calculate_from_returns(&self, raw_returns: &Returns) -> Option<Self::Item> {
        if !self.check_valid_returns(raw_returns) {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass confidence as a fraction strictly between 0 and 1 (e.g. 0.99, not 99).
  2. Validate/clamp the config value before constructing: require x.is_finite() && 0.0 < x && x < 1.0.
  3. Use ExpectedShortfall::new_checked(...) and handle the Result instead of the panicking new().

Example fix

// before
let es = ExpectedShortfall::new(Some(95.0)); // panics: 95 not in (0,1)

// after
let es = ExpectedShortfall::new(Some(0.95));
Defensive patterns

Strategy: validation

Validate before calling

# python caller guard
confidence = config["confidence"]  # e.g. 95 meaning percent
confidence = confidence / 100.0 if confidence > 1.0 else confidence
assert 0.0 < confidence < 1.0, "confidence must be in (0, 1)"
es = ExpectedShortfall(confidence)

Type guard

fn valid_confidence(c: f64) -> bool { c.is_finite() && c > 0.0 && c < 1.0 }

Try / catch

# Rust side: prefer the checked constructor
match ExpectedShortfall::new_checked(Some(c)) {
    Ok(es) => es,
    Err(e) => { log::error!("bad confidence {c}: {e}"); ExpectedShortfall::new(None) }
}

Prevention

When it happens

Trigger: Calling ExpectedShortfall::new with Some(x) where x <= 0, x >= 1, or x is NaN/infinity; also None default path if its internal default were invalid (it is not, so practically only bad Some values).

Common situations: Confidence expressed as a percentage (95.0 instead of 0.95); reading the value from config as '95%' string remainder; NaN propagating from parsed config or computed parameters.

Related errors


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