nautechsystems/nautilus_trader · error

Inverse instrument {} has no base currency

Error message

Inverse instrument {} has no base currency

What it means

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.

Source

Thrown at crates/model/src/accounts/margin_model.rs:224

    fn default() -> Self {
        MarginModelAny::default().into()
    }
}

impl From<MarginModelAny> for MarginModelHandle {
    fn from(model: MarginModelAny) -> Self {
        Self::new(model)
    }
}

/// Resolves the margin currency based on instrument properties.
fn margin_currency(
    instrument: &dyn Instrument,
    use_quote_for_inverse: bool,
) -> anyhow::Result<crate::types::Currency> {
    if instrument.is_inverse() && !use_quote_for_inverse {
        instrument.base_currency().ok_or_else(|| {
            anyhow::anyhow!(
                "Inverse instrument {} has no base currency",
                instrument.id()
            )
        })
    } else {
        Ok(instrument.quote_currency())
    }
}

/// Uses fixed margin percentages without leverage division.
///
/// Margin is calculated as `notional_value * margin_rate`, ignoring the
/// account leverage. Appropriate for traditional brokers where margin
/// requirements are fixed percentages of notional value.
#[derive(Debug, Clone, Copy)]
#[cfg_attr(
    feature = "python",
    pyo3::pyclass(module = "nautilus_trader.model", from_py_object)

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set use_quote_for_inverse to Some(true)/true when calculating margin for an inverse instrument lacking a base currency
  2. Fix the instrument definition so the inverse instrument has a valid base currency
  3. Guard the call: check instrument.is_inverse() && instrument.base_currency().is_none() before computing margin and surface a configuration error

Example fix

// before
let margin = model.calculate_initial_margin(&instrument, qty, price, None)?;
// after
let use_quote = instrument.is_inverse() && instrument.base_currency().is_none();
let margin = model.calculate_initial_margin(&instrument, qty, price, Some(use_quote))?;
Defensive patterns

Strategy: validation

Validate before calling

fn can_compute_margin(inst: &dyn Instrument, use_quote: Option<bool>) -> bool {
    !(inst.is_inverse() && !use_quote.unwrap_or(false) && inst.base_currency().is_none())
}

Type guard

fn has_base_currency(inst: &dyn Instrument) -> bool {
    !inst.is_inverse() || inst.base_currency().is_some()
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/b0fa2f97983c77d8. Report an issue: GitHub.