{"record":{"id":"f4aabfc28ba40275","repo":"nautechsystems/nautilus_trader","slug":"ax-maintenance-margin-pct-maintenance-margin-pct","errorCode":null,"errorMessage":"AX maintenance_margin_pct {maintenance_margin_pct} exceeds initial_margin_pct {initial_margin_pct}","messagePattern":"AX maintenance_margin_pct (.+?) exceeds initial_margin_pct (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/architect_ax/src/http/parse.rs","lineNumber":385,"sourceCode":"        .build()\n        .unwrap();\n\n    Ok(InstrumentAny::PerpetualContract(instrument))\n}\n\nfn parse_margin_rates(\n    initial_margin_pct: Decimal,\n    maintenance_margin_pct: Decimal,\n) -> anyhow::Result<(Decimal, Decimal)> {\n    anyhow::ensure!(\n        initial_margin_pct > Decimal::ZERO,\n        \"AX initial_margin_pct must be positive, was {initial_margin_pct}\"\n    );\n    anyhow::ensure!(\n        maintenance_margin_pct > Decimal::ZERO,\n        \"AX maintenance_margin_pct must be positive, was {maintenance_margin_pct}\"\n    );\n    anyhow::ensure!(\n        maintenance_margin_pct <= initial_margin_pct,\n        \"AX maintenance_margin_pct {maintenance_margin_pct} exceeds initial_margin_pct {initial_margin_pct}\"\n    );\n\n    Ok((\n        margin_percent_to_rate(initial_margin_pct, \"initial_margin_pct\")?,\n        margin_percent_to_rate(maintenance_margin_pct, \"maintenance_margin_pct\")?,\n    ))\n}\n\nfn margin_percent_to_rate(value: Decimal, field: &str) -> anyhow::Result<Decimal> {\n    let normalized = value.normalize();\n    let scale = normalized.scale();\n    anyhow::ensure!(\n        scale <= 26,\n        \"AX {field} scale must not exceed 26 for exact percent conversion, was {scale}\"\n    );\n    Decimal::try_from_i128_with_scale(normalized.mantissa(), scale + 2)","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/architect_ax/src/http/parse.rs#L367-L403","documentation":"parse_margin_rates enforces the invariant maintenance_margin_pct <= initial_margin_pct; maintenance margin exceeding initial margin is economically inconsistent (you would be liquidated before reaching full position margin).","triggerScenarios":"parse_instrument (via request_instruments/request_instrument) on a definition where maintenance_margin_pct > initial_margin_pct, e.g. initial 0.05 and maintenance 0.10.","commonSituations":"Swapped fields in venue metadata or in a hand-built fixture, unit confusion (one value expressed as percent, other as fraction), or venue data-entry error.","solutions":["Verify which field is initial vs maintenance in the raw payload; check for swapped values.","Fix the source data or fixture so maintenance <= initial.","Check units: both must be percentages in the same representation (e.g. 10 for 10% vs 0.10).","If the venue changed semantics, update the adapter mapping accordingly."],"exampleFix":"// before (payload)\n{ \"margin_init_pct\": \"0.05\", \"margin_maint_pct\": \"0.10\" }\n// after\n{ \"margin_init_pct\": \"0.10\", \"margin_maint_pct\": \"0.05\" }","handlingStrategy":"validation","validationCode":"fn margins_consistent(init: Decimal, maint: Decimal) -> bool {\n    init > Decimal::ZERO && maint > Decimal::ZERO && maint <= init\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check for swapped init/maint fields in venue metadata","Ensure both percentages use the same unit representation","Validate fixtures with a margin-consistency check"],"tags":["rust","validation","margin","invariant"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}