nautechsystems/nautilus_trader · error · anyhow::Error

`last_price` was zero when calculating base quantity

Error message

`last_price` was zero when calculating base quantity

What it means

Instrument::try_calculate_base_quantity converts a quote-currency quantity into a base quantity by dividing by last_price; a zero last_price would divide by zero, so the method bails with this error before computing.

Source

Thrown at crates/model/src/instruments/mod.rs:545

                ),
            });
        }

        Quantity::from_raw_checked(quantity.raw, precision)
    }

    /// # Errors
    ///
    /// Returns an error if `last_price` is zero, or if the value cannot be converted to a
    /// `Quantity`.
    fn try_calculate_base_quantity(
        &self,
        quantity: Quantity,
        last_price: Price,
    ) -> anyhow::Result<Quantity> {
        let last_px = last_price.as_decimal();
        if last_px.is_zero() {
            anyhow::bail!("`last_price` was zero when calculating base quantity");
        }
        let precision = u32::from(self.min_size_increment_precision());
        let value = (quantity.as_decimal() / last_px)
            .round_dp_with_strategy(precision, RoundingStrategy::MidpointNearestEven);
        Quantity::from_decimal_dp(value, self.size_precision()).map_err(Into::into)
    }

    /// # Panics
    ///
    /// Panics if `last_price` is zero, or if the value cannot be converted to a `Quantity`
    /// (see `try_calculate_base_quantity`).
    fn calculate_base_quantity(&self, quantity: Quantity, last_price: Price) -> Quantity {
        self.try_calculate_base_quantity(quantity, last_price)
            .unwrap()
    }

    /// Calculates the notional value for the given quantity and price.
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Guard that last_price.is_positive() before calling calculate_base_quantity.
  2. Wait for the first price update event before sizing orders.
  3. Use a fallback reference price (e.g. mid or last known good) when last is zero.

Example fix

// before
let base_qty = instrument.calculate_base_quantity(quote_qty, last_price)?;
// after
if last_price.as_decimal().is_zero() {
    anyhow::bail!("no valid last price yet; skipping sizing");
}
let base_qty = instrument.calculate_base_quantity(quote_qty, last_price)?;
Defensive patterns

Strategy: validation

Validate before calling

if last_price.as_decimal().is_zero() { return Err(anyhow::anyhow!("last price not initialized")); }

Try / catch

match instrument.try_calculate_base_quantity(qty, last_price) {
    Ok(base) => base,
    Err(_) => { /* skip sizing until a price arrives */ }
}

Prevention

When it happens

Trigger: Calling calculate_base_quantity(quantity, Price::zero()) — typically when the latest trade/price feed has not initialized and a default zero Price is passed.

Common situations: Strategy startup before the first quote/trade arrives, stale market data after a halt, or a price field default-initialized to zero.

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