nautechsystems/nautilus_trader · error · anyhow::Error

Invalid tickSize of 0 for symbol '{}', cannot create instrum

Error message

Invalid tickSize of 0 for symbol '{}', cannot create instrument

What it means

After parsing PRICE_FILTER.tickSize for a USD-M symbol, parse_usdm_instrument_with_fees rejects a tick size of exactly zero: tick size parameterizes the instrument's price increment and precision, so a zero tick cannot produce a valid instrument.

Source

Thrown at crates/adapters/binance/src/common/parse.rs:314

        anyhow::bail!(
            "Symbol '{}' is not trading (status: {:?})",
            symbol.symbol,
            symbol.status
        );
    }

    let quote_currency = get_currency(symbol.quote_asset.as_str());
    let settlement_currency = get_currency(symbol.margin_asset.as_str());

    let instrument_id = format_instrument_id(&symbol.symbol, BinanceProductType::UsdM);
    let raw_symbol = Symbol::new(symbol.symbol.as_str());

    let price_filter = get_filter(&symbol.filters, "PRICE_FILTER")
        .context("Missing PRICE_FILTER in symbol filters")?;

    let tick_size = parse_filter_price(price_filter, "tickSize")?;
    if tick_size.is_zero() {
        anyhow::bail!(
            "Invalid tickSize of 0 for symbol '{}', cannot create instrument",
            symbol.symbol,
        );
    }
    let max_price = parse_filter_price(price_filter, "maxPrice").ok();
    let min_price = parse_filter_price(price_filter, "minPrice").ok();

    let lot_filter =
        get_filter(&symbol.filters, "LOT_SIZE").context("Missing LOT_SIZE in symbol filters")?;

    let step_size = parse_filter_quantity(lot_filter, "stepSize")?;
    let max_quantity = parse_filter_quantity(lot_filter, "maxQty").ok();
    let min_quantity = parse_filter_quantity(lot_filter, "minQty").ok();

    let min_notional = parse_futures_min_notional(&symbol.filters, quote_currency);

    // Default margin (0.1 = 10x leverage)
    let default_margin = Decimal::new(1, 1);

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Check the live exchangeInfo for the symbol; a zero tickSize usually means it is not tradable yet.
  2. Skip or defer loading of symbols whose tickSize is 0.
  3. Clear any exchangeInfo cache and retry with fresh data.
  4. If a TRADING-status symbol persistently reports tickSize 0, report it to Binance / the adapter maintainers.
Defensive patterns

Strategy: try-catch

Validate before calling

fn usdm_tick_size_is_valid(symbol: &BinanceFuturesUsdSymbol) -> bool {
    symbol
        .filters
        .iter()
        .find(|f| f.get("filterType").and_then(|v| v.as_str()) == Some("PRICE_FILTER"))
        .and_then(|f| f.get("tickSize").and_then(|v| v.as_str()))
        .map(|t| {
            rust_decimal::Decimal::from_str(t)
                .map(|d| !d.is_zero())
                .unwrap_or(false)
        })
        .unwrap_or(false)
}

Try / catch

match parse_usdm_instrument(&symbol, ts_event, ts_init) {
    Ok(inst) => instruments.push(inst),
    Err(e) if e.to_string().contains("Invalid tickSize of 0") => {
        tracing::warn!(symbol = %symbol.symbol, "venue reported zero tickSize, deferring load")
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: USD-M exchangeInfo contains a PRICE_FILTER with "tickSize": "0" — typically placeholder data on symbols in pre-listing/settlement states, or corrupted/cached responses.

Common situations: Pre-listing symbols before Binance populates real filters; a stale exchangeInfo cache or replayed fixture with zeroed filters; venue-side data glitch.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/84b45dd259cbdbfc. Report an issue: GitHub.