nautechsystems/nautilus_trader · error

Invalid `threshold` for `OmegaRatio`

Error message

Invalid `threshold` for `OmegaRatio`

What it means

OmegaRatio::new is the infallible constructor wrapping new_checked, which requires threshold to be a finite f64. The expect panics when the value is NaN or +/- infinity, because the panicking constructor assumes callers pass valid constants.

Source

Thrown at crates/analysis/src/statistics/omega_ratio.rs:76

    /// Creates a new checked [`OmegaRatio`] instance.
    ///
    /// # Errors
    ///
    /// Returns an error if `threshold` is not finite.
    pub fn new_checked(threshold: Option<f64>) -> anyhow::Result<Self> {
        let threshold = threshold.unwrap_or(0.0);
        check_predicate_true(threshold.is_finite(), "threshold must be finite")?;
        Ok(Self { threshold })
    }

    /// Creates a new [`OmegaRatio`] instance.
    ///
    /// # Panics
    ///
    /// Panics if `threshold` is not finite.
    #[must_use]
    pub fn new(threshold: Option<f64>) -> Self {
        Self::new_checked(threshold).expect("Invalid `threshold` for `OmegaRatio`")
    }
}

impl Display for OmegaRatio {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Omega Ratio (threshold {})", self.threshold)
    }
}

impl PortfolioStatistic for OmegaRatio {
    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 a finite threshold (e.g. Some(0.0)); replace NaN/inf values before construction.
  2. Sanitize upstream computations: check is_finite() on the derived threshold.
  3. Use OmegaRatio::new_checked(...) and handle the Err instead of the panicking new().

Example fix

// before
let threshold = gains / losses; // 0/0 -> NaN
let ratio = OmegaRatio::new(Some(threshold)); // panics

// after
let threshold = if gains.is_finite() && losses.is_finite() { gains / losses } else { 0.0 };
let ratio = OmegaRatio::new(Some(threshold));
Defensive patterns

Strategy: validation

Validate before calling

fn valid_threshold(t: f64) -> bool { t.is_finite() }

Type guard

fn finite_f64(x: f64) -> Option<f64> {
    if x.is_finite() { Some(x) } else { None }
}

Try / catch

match OmegaRatio::new_checked(Some(threshold)) {
    Ok(r) => r,
    Err(e) => { log::error!("bad threshold {threshold}: {e}"); OmegaRatio::new(None) }
}

Prevention

When it happens

Trigger: Calling OmegaRatio::new with Some(f64::NAN), Some(f64::INFINITY), or a NaN computed from upstream data (e.g. a ratio of infinities) instead of a finite threshold.

Common situations: Threshold derived from market data that produced NaN/inf (0/0 divisions); config parsed to float infinity; passing an unvalidated externally supplied parameter.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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