nautechsystems/nautilus_trader · error

initial margin calculation overflow

Error message

initial margin calculation overflow

What it means

Thrown by the leveraged (non-standard) initial margin path when the checked decimal multiplication of |notional| by margin_init overflows, or when the resulting margin cannot be converted to a Money value at the currency's precision. It is a guard against arithmetic overflow rather than a logic error, since margin amounts can be extremely large for high notionals or rates.

Source

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

    }

    fn calculate_initial_margin(
        &self,
        instrument: &dyn Instrument,
        quantity: Quantity,
        price: Price,
        _leverage: Decimal,
        use_quote_for_inverse: Option<bool>,
    ) -> anyhow::Result<Money> {
        let use_quote = use_quote_for_inverse.unwrap_or(false);
        let notional = instrument.try_calculate_notional_value(quantity, price, Some(use_quote))?;
        // Spreads and options may quote negative, which carries the sign into the notional.
        // A requirement is a reserve against exposure magnitude, so take it on `abs`.
        let margin = notional
            .as_decimal()
            .abs()
            .checked_mul(instrument.margin_init())
            .ok_or_else(|| anyhow::anyhow!("initial margin calculation overflow"))?;
        let currency = margin_currency(instrument, use_quote)?;
        Money::from_decimal(margin, currency).map_err(Into::into)
    }

    fn calculate_maintenance_margin(
        &self,
        instrument: &dyn Instrument,
        quantity: Quantity,
        price: Price,
        _leverage: Decimal,
        use_quote_for_inverse: Option<bool>,
    ) -> anyhow::Result<Money> {
        let use_quote = use_quote_for_inverse.unwrap_or(false);
        let notional = instrument.try_calculate_notional_value(quantity, price, Some(use_quote))?;
        let margin = notional
            .as_decimal()
            .abs()
            .checked_mul(instrument.margin_maint())

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the quantity and price inputs for unreasonable magnitude before calling
  2. Verify instrument.margin_init() is a sane rate (e.g. 0.01–1.0, not 1000)
  3. Handle the error and skip/reject the position instead of unwrapping

Example fix

// before
let margin = model.calculate_initial_margin(&inst, qty, price, None).unwrap();
// after
match model.calculate_initial_margin(&inst, qty, price, None) {
    Ok(m) => ..., 
    Err(e) if e.to_string().contains("overflow") => warn!("margin overflow, rejecting"),
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: try-catch

Validate before calling

if qty.as_decimal().abs() * price.as_decimal() > Decimal::from(1e18) {
    return Err(anyhow!("notional too large for margin calc"));
}

Try / catch

match model.calculate_initial_margin(&inst, qty, price, use_quote) {
    Ok(m) => m,
    Err(e) if e.to_string().contains("overflow") => { warn!("initial margin overflow: {e}"); Money::zero(currency) }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: calculate_initial_margin with an extremely large notional value (huge quantity × price) multiplied by margin_init such that the rust_decimal product overflows; also when Money::from_decimal cannot represent the margin at the currency precision.

Common situations: Backtests with oversized or malformed prices/quantities; instruments with unreasonably large margin_init rates; low-precision currencies receiving very large margins.

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/386bfa2fea8863b1. Report an issue: GitHub.