nautechsystems/nautilus_trader · error

cannot calculate CFD swap for position {}: currency conversi

Error message

cannot calculate CFD swap for position {}: currency conversion overflow

What it means

After computing the swap adjustment in the position's quote currency, the module converts it to the account base currency by multiplying with the exchange rate. If amount * xrate overflows Decimal, the conversion is impossible and this error is raised for that position.

Source

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

                                ),
                            );
                            return Ok(None);
                        }
                        Err(e) => {
                            self.log_calculation_failure(
                                booking_date,
                                instrument_id,
                                CfdSwapFailureKind::Xrate,
                                &format!(
                                    "Cannot calculate CFD swap for {instrument_id}: exchange rate from {} to {base_currency}: {e}",
                                    notional.currency
                                ),
                            );
                            return Ok(None);
                        }
                    };
                    let amount = amount.checked_mul(xrate).ok_or_else(|| {
                        anyhow::anyhow!(
                            "cannot calculate CFD swap for position {}: currency conversion overflow",
                            position.id
                        )
                    })?;
                    (amount, base_currency)
                } else {
                    (amount, notional.currency)
                };
                adjustments.push(Money::from_decimal(amount, currency)?);
            }
        }

        Ok(Some(adjustments))
    }

    fn log_totals(label: &str, totals: &AHashMap<Currency, Decimal>) -> anyhow::Result<()> {
        let mut currencies = totals.keys().copied().collect::<Vec<_>>();
        currencies.sort_unstable_by_key(|currency| currency.code);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify cached exchange rates for the quote->base pair are sane (order of magnitude ~1 for major pairs)
  2. Fix the swap rate/multiplier/notional so the pre-conversion amount is realistic
  3. Correct the account base_currency configuration if an unintended pair is being converted

Example fix

// before: trusting any cached rate blindly
let xrate = ctx.cache.try_get_xrate(quote, base)?.unwrap();
// after: sanity-check magnitude first
let xrate = ctx.cache.try_get_xrate(quote, base)?.unwrap();
assert!(xrate > Decimal::ZERO && xrate < Decimal::from(1_000_000));
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check cached FX rate before conversion
if let Some(xrate) = ctx.cache.try_get_xrate(quote, base)? {
    assert!(xrate > Decimal::ZERO && xrate < Decimal::from(1_000_000), "implausible xrate");
}

Try / catch

match module.process(ts_now) {
    Err(e) if e.to_string().contains("currency conversion overflow") => {
        log::error!("bad FX rate or inflated amount: {e:#}");
        SimulationModuleResult::NotReady
    }
    other => other,
}

Prevention

When it happens

Trigger: calculate_adjustments (via process) converts a swap amount using an exchange rate from cache.try_get_xrate where the product exceeds Decimal::MAX — caused by an inflated adjustment (huge notional/rate) or a wildly wrong stored exchange rate.

Common situations: Bad FX rate in the cache (scale error, e.g. rate stored as 1e15); base currency misconfigured so conversion uses an inappropriate rate; upstream overflow from 3713's causes propagating into conversion.

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