nautechsystems/nautilus_trader · error · anyhow::Error

quantity size= cannot be represented with precision=

Error message

quantity size={} cannot be represented with precision={}

What it means

checked_quantity validates that an f64 size from IB can be exactly represented as a domain Quantity at the given precision. Quantity::new_checked rounds to precision; if the rounded value differs from the original size beyond a tiny tolerance, this error is bailed to avoid silently distorting order/tick quantities.

Solutions

  1. Increase the precision argument to match the instrument's allowed quantity precision
  2. Verify the instrument definition in the cache has correct quantity precision
  3. Sanitize/round the size at the source (IB) before parsing
  4. Reject or rescale the tick if the size is genuinely finer-grained than the instrument supports

Example fix

// before
let qty = checked_quantity(size, 2)?;
// after
let qty = checked_quantity(size, instrument.precision() /* e.g. 6 */)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_representable(size: f64, precision: u8) -> bool {
    let rounded = round_to_precision(size, precision);
    (rounded - size).abs() <= 10f64.powi(-i32::from(precision)) * 1e-9
}
// guard: if !is_representable(size, precision) { return Err(...); }

Type guard

fn valid_quantity(size: f64, precision: u8) -> Option<f64> {
    if !size.is_finite() { return None; }
    let tol = 10f64.powi(-i32::from(precision)) * 1e-9;
    ((size.round() - size).abs() <= tol).then_some(size)
}

Try / catch

match checked_quantity(size, precision) {
    Ok(q) => q,
    Err(e) => { warn!("skipping tick with unusable size: {e}"); return Ok(()); }
}

Prevention

When it happens

Trigger: parse_quote_tick or parse_trade_tick passes a size like 0.1234567 to checked_quantity with a small precision (e.g. 2 or 3), so rounding changes the value more than the tolerance; also triggered by NaN/inf-ish or absurdly large f64 sizes.

Common situations: Crypto/forex instruments with sub-tick sizes exceeding the configured precision; precision derived from the instrument definition not matching IB-reported sizes; wrong precision passed by the caller.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at crates/adapters/interactive_brokers/src/data/parse.rs:35

use ibapi::contracts::{OptionComputation, tick_types::TickType};
use nautilus_core::UnixNanos;
use nautilus_model::{
    data::{
        Bar, BarType, IndexPriceUpdate, QuoteTick, TradeTick, greeks::OptionGreekValues,
        option_chain::OptionGreeks,
    },
    enums::{AggressorSide, BookAction, GreeksConvention},
    identifiers::{InstrumentId, TradeId},
    types::{Price, Quantity},
};

fn checked_quantity(size: f64, precision: u8) -> anyhow::Result<Quantity> {
    let quantity = Quantity::new_checked(size, precision)
        .map_err(|e| anyhow::anyhow!("invalid quantity size={size}: {e}"))?;
    let tolerance = 10_f64.powi(-i32::from(precision)) * 1e-9;
    if (quantity.as_f64() - size).abs() > tolerance {
        anyhow::bail!(
            "quantity size={} cannot be represented with precision={}",
            size,
            precision
        );
    }
    Ok(quantity)
}

/// Parse IB tick price and size data into a QuoteTick.
///
/// This builds a quote from individual tick updates. You typically need to accumulate
/// bid/ask prices and sizes from multiple tick updates before creating a QuoteTick.
///
/// # Errors
///
/// Returns an error if price or size conversion fails.
#[allow(clippy::too_many_arguments)]
pub fn parse_quote_tick(

View on GitHub (pinned to 18893faf8b)