nautechsystems/nautilus_trader · error · anyhow::Error
AX initial_margin_pct must be positive, was {initial_margin_
Error message
AX initial_margin_pct must be positive, was {initial_margin_pct} What it means
parse_margin_rates requires initial_margin_pct to be strictly greater than zero before converting percent to a rate for the instrument's margin fields. A zero or negative value — typically an unset field defaulting to 0 — fails instrument parsing immediately.
Source
Thrown at crates/adapters/architect_ax/src/http/parse.rs:384
None,
Some(margin_init),
Some(margin_maint),
Some(maker_fee),
Some(taker_fee),
None,
Some(info),
ts_event,
ts_init,
);
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 a4b06ed870)
Solutions
- Check the symbol's margin fields in AX venue config and set a positive initial margin percent
- Verify the field name/type against the AX API docs for your version — a renamed field silently deserializes to 0
- If a symbol genuinely has no margin yet (spot-like listing), configure a nominal positive value or exclude it from loading
- Retry after config changes; no client-side workaround exists
Example fix
// before (AX contract metadata) "initial_margin_pct": "0" // after "initial_margin_pct": "1.5"
Defensive patterns
Strategy: try-catch
Validate before calling
// Vet margin fields before definitions reach the parser
fn initial_margin_ok(v: Decimal) -> bool { v > Decimal::ZERO }
if !initial_margin_ok(definition.initial_margin_pct) {
anyhow::bail!("symbol {} has non-positive initial_margin_pct {}}", definition.symbol, definition.initial_margin_pct);
} Try / catch
match parse_instrument(&definition, ts_event, ts_init) {
Ok(instrument) => Ok(instrument),
Err(e) if e.to_string().contains("initial_margin_pct must be positive") => {
log::error!("symbol {} margin config incomplete (initial_margin_pct <= 0)", definition.symbol);
Err(e)
}
Err(e) => Err(e),
} Prevention
- Make margin percent fields mandatory in your venue-config publish pipeline
- Alert when a newly listed symbol parses with default-zero margin fields instead of failing silently at trade time
- Verify API field names after AX upgrades — renamed fields deserialize to zero defaults
When it happens
Trigger: An instrument definition carries initial_margin_pct of 0 (field never configured for a new listing) or a negative value; any instrument load or /instrument fetch for that symbol then errors during parse_margin_rates.
Common situations: Newly listed symbols whose margin configuration has not been populated in AX yet; an API change renaming the field so deserialization falls back to a zero default; contract templates copied without margin values.
Related errors
- AX maintenance_margin_pct must be positive, was {maintenance
- AX instrument product must be non-empty without surrounding
- AX minimum_order_size must be a positive whole number, was {
- AX maintenance_margin_pct {maintenance_margin_pct} exceeds i
- AX dated contract {} has different quote and settlement curr
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/4f86f3760b229b7e.
Report an issue: GitHub.