nautechsystems/nautilus_trader · error · anyhow::Error

AX minimum_order_size must be a positive whole number, was

Error message

AX minimum_order_size must be a positive whole number, was {}

What it means

The AX instrument definition's `minimum_order_size` must be a positive whole number (strictly greater than zero with no fractional part). The adapter enforces this because NautilusTrader quantity increments derived from it require discrete whole-number minimums.

Solutions

  1. Check the raw definition's minimum_order_size value returned by the AX API.
  2. Round/floor to a whole number at the data source if the venue's value is representable that way, or truncate trailing fraction if it is a formatting artifact.
  3. If the venue now legitimately supports fractional minimums, extend the adapter's parsing logic instead of altering data.
  4. Fix fixture values to positive whole numbers in tests/mocks.

Example fix

// before (payload)
"minimum_order_size": "0.5"
// after
"minimum_order_size": "1"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_min_size(d: &InstrumentDefinition) -> bool {
    d.minimum_order_size > Decimal::ZERO && d.minimum_order_size.fract().is_zero()
}

Prevention

When it happens

Trigger: request_instruments/request_instrument -> parse_instrument on a definition where minimum_order_size is zero, negative, or fractional (e.g. 0, -1, 0.5, 10.25).

Common situations: AX venue changes instrument metadata to a fractional minimum lot size; fixtures with placeholder values like 0; a new instrument type (e.g. fractional notional minimums) not supported by the adapter yet.

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

Appendix: source

Thrown at crates/adapters/architect_ax/src/http/parse.rs:210

    {
        &symbol_prefix[..symbol_prefix.len() - quote_code.len()]
    } else {
        symbol_prefix
    };

    let asset_class = AssetClass::from(definition.category);

    // Only resolve base currency for FX/crypto where the base code is a currency
    let base_currency = match asset_class {
        AssetClass::FX | AssetClass::Cryptocurrency => Some(get_currency(base_code)),
        _ => None,
    };

    let quote_currency = get_currency(quote_code);
    let settlement_currency = get_currency(definition.funding_settlement_currency.as_str());

    let price_increment = decimal_to_price(definition.tick_size, "tick_size")?;
    anyhow::ensure!(
        definition.minimum_order_size > Decimal::ZERO
            && definition.minimum_order_size.fract().is_zero(),
        "AX minimum_order_size must be a positive whole number, was {}",
        definition.minimum_order_size
    );
    let size_increment = decimal_to_quantity(Decimal::ONE, "size_increment")?;
    let lot_size = Some(size_increment);
    let min_quantity = Some(decimal_to_quantity(
        definition.minimum_order_size.normalize(),
        "minimum_order_size",
    )?);

    let (margin_init, margin_maint) = parse_margin_rates(
        definition.initial_margin_pct,
        definition.maintenance_margin_pct,
    )?;

    let mut info = Params::new();

View on GitHub (pinned to 18893faf8b)