nautechsystems/nautilus_trader · error · anyhow::Error

AX initial_margin_pct must be positive, was

Error message

AX initial_margin_pct must be positive, was {initial_margin_pct}

What it means

Validation in AX instrument parsing's parse_margin_rates: the parsed initial margin percentage is zero or negative, which cannot represent a valid margin requirement, so the instrument definition is rejected.

Solutions

  1. Check the raw margin fields on the AX instrument definition.
  2. Correct the source data so initial_margin_pct is > 0.
  3. Fix test fixtures to use realistic positive margins.
  4. If the venue legitimately sends 0 for some instruments, filter them out or update the adapter to handle the special case explicitly.

Example fix

// before (payload)
"margin_init_pct": "0"
// after
"margin_init_pct": "0.10"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_initial_margin(v: Decimal) -> bool { v > Decimal::ZERO }

Prevention

When it happens

Trigger: parse_instrument (via request_instruments/request_instrument) passing an instrument definition whose margin data yields initial_margin_pct <= 0 (zero, negative, or a Decimal parsed from '0'/'-0.1').

Common situations: Venue margin metadata missing/defaulted to zero, fixtures with 0 placeholders, negative values from a bad feed, or a field rename causing the parser to read the wrong column.

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

Appendix: source

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

        .maybe_min_quantity(min_quantity)
        .margin_init(margin_init)
        .margin_maint(margin_maint)
        .maker_fee(maker_fee)
        .taker_fee(taker_fee)
        .info(info)
        .ts_event(ts_event)
        .ts_init(ts_init)
        .build()
        .unwrap();

    Ok(InstrumentAny::PerpetualContract(instrument))
}

fn parse_margin_rates(
    initial_margin_pct: Decimal,
    maintenance_margin_pct: Decimal,
) -> anyhow::Result<(Decimal, Decimal)> {
    anyhow::ensure!(
        initial_margin_pct > Decimal::ZERO,
        "AX initial_margin_pct must be positive, was {initial_margin_pct}"
    );
    anyhow::ensure!(
        maintenance_margin_pct > Decimal::ZERO,
        "AX maintenance_margin_pct must be positive, was {maintenance_margin_pct}"
    );
    anyhow::ensure!(
        maintenance_margin_pct <= initial_margin_pct,
        "AX maintenance_margin_pct {maintenance_margin_pct} exceeds initial_margin_pct {initial_margin_pct}"
    );

    Ok((
        margin_percent_to_rate(initial_margin_pct, "initial_margin_pct")?,
        margin_percent_to_rate(maintenance_margin_pct, "maintenance_margin_pct")?,
    ))
}

View on GitHub (pinned to 18893faf8b)