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
- Verify cached exchange rates for the quote->base pair are sane (order of magnitude ~1 for major pairs)
- Fix the swap rate/multiplier/notional so the pre-conversion amount is realistic
- 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
- Seed the cache with correct-magnitude exchange rates
- Confirm account base_currency matches your conversion expectations
- Fix upstream amount overflow (rate/multiplier scale) first
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
- cannot calculate CFD swap for {instrument_id}: midpoint over
- cannot calculate CFD swap for position {}: adjustment overfl
- CFD swap diagnostic total overflow
- unapplied CFD swap total overflow
- CFD swap rollover day is not initialized
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/d45eab055d9533e8.
Report an issue: GitHub.