{"record":{"id":"b0fa2f97983c77d8","repo":"nautechsystems/nautilus_trader","slug":"inverse-instrument-has-no-base-currency","errorCode":null,"errorMessage":"Inverse instrument {} has no base currency","messagePattern":"Inverse instrument (.+?) has no base currency","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/accounts/margin_model.rs","lineNumber":224,"sourceCode":"    fn default() -> Self {\n        MarginModelAny::default().into()\n    }\n}\n\nimpl From<MarginModelAny> for MarginModelHandle {\n    fn from(model: MarginModelAny) -> Self {\n        Self::new(model)\n    }\n}\n\n/// Resolves the margin currency based on instrument properties.\nfn margin_currency(\n    instrument: &dyn Instrument,\n    use_quote_for_inverse: bool,\n) -> anyhow::Result<crate::types::Currency> {\n    if instrument.is_inverse() && !use_quote_for_inverse {\n        instrument.base_currency().ok_or_else(|| {\n            anyhow::anyhow!(\n                \"Inverse instrument {} has no base currency\",\n                instrument.id()\n            )\n        })\n    } else {\n        Ok(instrument.quote_currency())\n    }\n}\n\n/// Uses fixed margin percentages without leverage division.\n///\n/// Margin is calculated as `notional_value * margin_rate`, ignoring the\n/// account leverage. Appropriate for traditional brokers where margin\n/// requirements are fixed percentages of notional value.\n#[derive(Debug, Clone, Copy)]\n#[cfg_attr(\n    feature = \"python\",\n    pyo3::pyclass(module = \"nautilus_trader.model\", from_py_object)","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/accounts/margin_model.rs#L206-L242","documentation":"This error is thrown when a margin calculation is requested for an inverse instrument without a base currency, while the caller did not opt to use the quote currency. Inverse instruments are notionally denominated in the base currency, so margin_currency() requires a base currency to express the margin; if the instrument lacks one the computation cannot proceed. The library raises it explicitly rather than silently substituting a currency.","triggerScenarios":"Calling calculate_initial_margin or calculate_maintenance_margin on an instrument where is_inverse() is true, use_quote_for_inverse is false (or None), and instrument.base_currency() returns None (e.g. a crypto inverse perpetual modeled without a base currency).","commonSituations":"Configuring inverse crypto futures/perpetuals where the instrument definition omits base_currency; loading instruments from an adapter that does not populate base currency for inverse symbols; accidentally passing use_quote_for_inverse=None when the instrument has no base currency.","solutions":["Set use_quote_for_inverse to Some(true)/true when calculating margin for an inverse instrument lacking a base currency","Fix the instrument definition so the inverse instrument has a valid base currency","Guard the call: check instrument.is_inverse() && instrument.base_currency().is_none() before computing margin and surface a configuration error"],"exampleFix":"// before\nlet margin = model.calculate_initial_margin(&instrument, qty, price, None)?;\n// after\nlet use_quote = instrument.is_inverse() && instrument.base_currency().is_none();\nlet margin = model.calculate_initial_margin(&instrument, qty, price, Some(use_quote))?;","handlingStrategy":"validation","validationCode":"fn can_compute_margin(inst: &dyn Instrument, use_quote: Option<bool>) -> bool {\n    !(inst.is_inverse() && !use_quote.unwrap_or(false) && inst.base_currency().is_none())\n}","typeGuard":"fn has_base_currency(inst: &dyn Instrument) -> bool {\n    !inst.is_inverse() || inst.base_currency().is_some()\n}","tryCatchPattern":null,"preventionTips":["Always populate base_currency in inverse instrument definitions","Default use_quote_for_inverse to true for inverse instruments without a base currency","Validate instrument definitions when loading from adapters"],"tags":["rust","margin","instruments","configuration"],"backgroundTag":"resource-not-found","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}