nautechsystems/nautilus_trader · error

quantity `{}` rounds to 0 ticks at size_precision {}

Error message

quantity `{}` rounds to 0 ticks at size_precision {}

What it means

The order quantity converted to integer Lighter base-amount ticks is zero because quantity_to_ticks floors the quantity using the instrument's size_precision. Lighter only accepts discrete tick amounts, so a sub-minimum quantity is rejected up front rather than sending an invalid order.

Source

Thrown at crates/adapters/lighter/src/execution.rs:1604

        let order_kind = nautilus_to_lighter_order_type(order.order_type())?;

        let tif = nautilus_to_lighter_tif(
            order.order_type(),
            order.time_in_force(),
            order.is_post_only(),
        )?;
        let now_ms = (self.clock.get_time_ns().as_u64() / 1_000_000) as i64;
        let order_expiry = order_expiry_for(
            order.order_type(),
            &order.time_in_force(),
            order.expire_time(),
            now_ms,
        )?;

        let base_amount = quantity_to_ticks(&order.quantity(), instrument.size_precision())?;

        // `quantity_to_ticks` floors sub-precision quantities to 0.
        anyhow::ensure!(
            base_amount > 0,
            "quantity `{}` rounds to 0 ticks at size_precision {}",
            order.quantity(),
            instrument.size_precision(),
        );
        let price_precision = instrument.price_precision();
        let is_buy = matches!(order.order_side(), OrderSide::Buy);

        // Lighter requires `price` on market-style orders as the worst
        // acceptable cap; derive it from far-side quote or trigger.
        let price_ticks = match order.order_type() {
            OrderType::Market => {
                let quote = self
                    .core
                    .cache()
                    .quote(&instrument_id)
                    .copied()
                    .ok_or_else(|| {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Increase the order quantity to at least one size tick for the instrument.
  2. Check the instrument's size_precision/size_increment and enforce a minimum-size check before submitting.
  3. Skip or accumulate dust amounts until they exceed one tick.
  4. Verify the instrument definition loaded matches the venue's actual precision.

Example fix

// before
let qty = Quantity::from_decimal(dec!(0.0004));
let order = order_factory.limit(instrument_id, Side::Buy, qty, price);
// after
let min_qty = Quantity::new(1.0, instrument.size_precision());
anyhow::ensure!(order.quantity() >= min_qty, "qty below one tick");
let order = order_factory.limit(instrument_id, Side::Buy, order.quantity(), price);
Defensive patterns

Strategy: validation

Validate before calling

// Rust
let ticks = qty.as_decimal() / dec!(10).powi(instrument.size_precision() as i64);
anyhow::ensure!(ticks >= dec!(1), "quantity below one size tick");

Try / catch

if quantity_to_ticks(&qty, instrument.size_precision()).unwrap_or(0) == 0 {
    log::warn!("skipping sub-tick quantity {qty}");
    return Ok(());
}

Prevention

When it happens

Trigger: submit_order/submit_order_list with a quantity smaller than one tick at the instrument's size_precision (e.g. qty 0.0004 when size_precision allows only 0.001 steps).

Common situations: Position-sizing math producing tiny fractions; Decimal division rounding down; using an instrument definition with coarser precision than the strategy assumes; leftover-dust sells.

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