nautechsystems/nautilus_trader · error

cannot calculate CFD swap for position {}: adjustment overfl

Error message

cannot calculate CFD swap for position {}: adjustment overflow

What it means

While computing a daily swap adjustment, the module multiplies the position's notional value by the daily rate and the contract multiplier using checked Decimal math. If any product overflows Decimal's maximum, the adjustment cannot be represented and this error is thrown for that position.

Source

Thrown at crates/backtest/src/modules/cfd_swap.rs:287

            } else {
                Decimal::ONE
            };

            for position in positions {
                let daily_rate = if position.is_long() {
                    rate.long_rate
                } else if position.is_short() {
                    rate.short_rate
                } else {
                    continue;
                };
                let notional = position.try_notional_value(settlement_price)?;
                let amount = notional
                    .as_decimal()
                    .checked_mul(daily_rate)
                    .and_then(|value| value.checked_mul(multiplier))
                    .ok_or_else(|| {
                        anyhow::anyhow!(
                            "cannot calculate CFD swap for position {}: adjustment overflow",
                            position.id
                        )
                    })?;
                let (amount, currency) = if let Some(base_currency) = ctx.base_currency {
                    let xrate = match ctx.cache.try_get_xrate(
                        ctx.venue,
                        notional.currency,
                        base_currency,
                        PriceType::Mid,
                    ) {
                        Ok(Some(xrate)) => xrate,
                        Ok(None) => {
                            self.log_calculation_failure(
                                booking_date,
                                instrument_id,
                                CfdSwapFailureKind::Xrate,
                                &format!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the configured daily swap rate and contract multiplier for scale errors (rate should be a small fraction, e.g. 0.0001)
  2. Validate position sizes and notional values for corruption before the rollover day
  3. Reduce position sizes or correct the instrument definition so notional stays within Decimal range

Example fix

// before
"swap_rate": 500.0, // meant 0.05%
// after
"swap_rate": 0.0005,
Defensive patterns

Strategy: validation

Validate before calling

// validate config scale before running
assert!(daily_rate.abs() < Decimal::new(1, 2), "swap rate should be a small fraction");
assert!(*multiplier < Decimal::from(1_000_000), "multiplier out of range");

Try / catch

match module.process(ts_now) {
    Ok(r) => r,
    Err(e) if e.to_string().contains("adjustment overflow") => {
        log::error!("check swap rate/multiplier/position size: {e:#}");
        SimulationModuleResult::NotReady
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: calculate_adjustments (via process) encounters a position whose try_notional_value * daily_rate * multiplier exceeds Decimal::MAX — typically from an enormous rate, multiplier, or notional (mis-scaled rate like 1e20 instead of 1e-4, or a gigantic position size).

Common situations: Misconfigured swap rate/multiplier config (percent given as 0.05 vs 5 vs 500); corrupted position sizes from earlier feed errors; currency with wrong precision inflating notional.

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/5dd5aecc11372dbd. Report an issue: GitHub.