nautechsystems/nautilus_trader · warning

Decimal average price must parse as f64

Error message

Decimal average price must parse as f64

What it means

In `get_avg_px_for_quantity` (crates/model/src/orderbook/analysis.rs), the cumulative Decimal average is converted to a string and parsed back to f64, panicking if parsing fails. Because a Decimal produced by dividing cumulative value by size always round-trips through its string representation, this panic signals an internal invariant break (e.g. a Decimal implementation emitting an unparseable representation such as NaN/Infinity text). Users hit it only via such a library-internal defect, not through invalid input.

Source

Thrown at crates/model/src/orderbook/analysis.rs:142

    for (book_price, level) in levels {
        let size_this_level = level.size_raw().min(qty.raw - cumulative_size_raw);
        let size_this_level_decimal = Quantity::raw_as_decimal(size_this_level);
        cumulative_size_raw += size_this_level;
        cumulative_size += size_this_level_decimal;
        cumulative_value += book_price.value.as_decimal() * size_this_level_decimal;

        if cumulative_size_raw >= qty.raw {
            break;
        }
    }

    if cumulative_size_raw == 0 {
        0.0
    } else {
        (cumulative_value / cumulative_size)
            .to_string()
            .parse::<f64>()
            .expect("Decimal average price must parse as f64")
    }
}

/// Calculates the worst (last-touched) price while filling a specified quantity
/// from order book levels.
///
/// For buy-side traversal this is the highest ask touched; for sell-side traversal
/// this is the lowest bid touched. Returns `None` when no quantity can be matched.
#[must_use]
pub fn get_worst_px_for_quantity(
    qty: Quantity,
    levels: &BTreeMap<BookPrice, BookLevel>,
) -> Option<Price> {
    let mut cumulative_size_raw: QuantityRaw = 0;
    let mut worst_price: Option<Price> = None;

    for (book_price, level) in levels {
        let size_this_level = level.size_raw().min(qty.raw - cumulative_size_raw);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Reduce the magnitude of inputs — cap quantity or operate on a shallower price range to avoid Decimal overflow.
  2. Check the rust_decimal version for known Display/parse round-trip regressions and pin a known-good version.
  3. Reproduce with the specific book snapshot and file an issue with the failing level data.
  4. As a workaround, compute the average in f64 incrementally instead of relying on the Decimal round-trip.

Example fix

// before
let avg = book.get_avg_px_for_quantity(OrderSide.BUY, huge_qty); // may panic
// after
let qty = huge_qty.min(book.total_volume(OrderSide.BUY));
let avg = book.get_avg_px_for_quantity(OrderSide.BUY, qty);
Defensive patterns

Strategy: fallback

Validate before calling

// Rust caller: bound the requested quantity to what the book can fill
let max_qty = book.cumulative_qty(side, book.best_price(side));
let qty = requested.min(max_qty);

Type guard

fn is_parseable_f64(s: &str) -> bool {
    s.parse::<f64>().is_ok()
}

Try / catch

// Cannot catch a Rust panic from Python; avoid triggering inputs.
qty = min(qty, book.total_volume(side))
avg_px = book.get_avg_px_for_quantity(side, qty)

Prevention

When it happens

Trigger: Calling get_avg_px_for_quantity with cumulative value/size that produce a non-finite Decimal (e.g. overflow of the internal Decimal representation from extremely large raw values), yielding a string like "Inf" that fails parse::<f64>... or a Decimal formatting regression.

Common situations: Deep books with enormous aggregated sizes/values on high-precision instruments, or after upgrading dependency versions where the Decimal type's Display output changed format.

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/ff2a69c64059bda0. Report an issue: GitHub.