nautechsystems/nautilus_trader · error
CFD swap diagnostic total overflow
Error message
CFD swap diagnostic total overflow
What it means
Raised when accumulating an applied CFD swap adjustment into the per-currency diagnostic `swap_totals` would overflow the Decimal total. The totals are diagnostic aggregates; a checked_add failure stops the run rather than silently corrupting the reported totals.
Source
Thrown at crates/backtest/src/modules/cfd_swap.rs:485
.pending_adjustments
.take()
.ok_or_else(|| anyhow::anyhow!("no completed CFD swap batch to acknowledge"))?;
let end_date = day
.pending_end_date
.ok_or_else(|| anyhow::anyhow!("CFD swap batch end date was not recorded"))?;
(adjustments, end_date)
};
let mut failed = Vec::new();
for (adjustment, outcome) in adjustments.into_iter().zip(outcomes) {
match outcome {
AccountAdjustmentOutcome::Applied => {
let mut totals = self.swap_totals.borrow_mut();
let total = totals.entry(adjustment.amount.currency).or_default();
*total = total
.checked_add(adjustment.amount.as_decimal())
.ok_or_else(|| anyhow::anyhow!("CFD swap diagnostic total overflow"))?;
}
AccountAdjustmentOutcome::Failed(error) if error.is_retryable() => {
log::warn!(
"Cannot apply CFD swap adjustment for {} on {}: {error}",
adjustment.amount.currency,
adjustment.booking_date
);
failed.push(adjustment);
}
AccountAdjustmentOutcome::Failed(error) => {
log::warn!(
"CFD swap adjustment {} on {} is recorded as unapplied: {error}",
adjustment.amount,
adjustment.booking_date
);
let mut totals = self.unapplied_swap_totals.borrow_mut();
let total = totals.entry(adjustment.amount.currency).or_default();
*total = totalView on GitHub (pinned to 18893faf8b)
Solutions
- Validate swap rate inputs and account sizes before the run so per-day adjustments are within realistic bounds.
- Shorten the backtest window or periodically reset/emit diagnostic totals if running over decades of simulated days.
- Sanitize the rates data source for outlier values (e.g. rates entered as 5250 instead of 5.25).
Example fix
// before
let rate = parse_rate(raw)?; // raw "5250" taken literally
// after
let rate = parse_rate(raw)?;
anyhow::ensure!(rate.abs() < 100.0, "implausible swap rate {rate}"); Defensive patterns
Strategy: validation
Validate before calling
anyhow::ensure!(swap_rate.abs() < 100.0, "swap rate out of plausible range: {swap_rate}");
anyhow::ensure!(notional.is_finite() && notional.abs() < Decimal::from(1_000_000_000), "notional too large"); Type guard
fn plausible_rate(v: f64) -> bool { v.is_finite() && v.abs() < 100.0 } Try / catch
if let Err(e) = engine.acknowledge(&outcomes) {
if e.to_string().contains("total overflow") {
log::error!("diagnostic totals overflowed; shorten run or fix inputs");
} else { return Err(e); }
} Prevention
- Sanity-check swap rates and notionals before long runs
- Screen rate data files for outliers and unit mistakes (bps vs %)
- Emit/reset diagnostic totals periodically on very long backtests
When it happens
Trigger: Accumulating swap amounts whose sum exceeds the Decimal precision/maximum for the accumulator over a long backtest or with extremely large swap amounts (huge notional or swap rate inputs).
Common situations: Very long backtests with daily swaps in one currency; bad swap-rate data files containing implausibly large rates; misconfigured account balances/instrument sizes feeding the adjustment amounts.
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
- unapplied CFD swap total overflow
- cannot calculate CFD swap for {instrument_id}: midpoint over
- cannot calculate CFD swap for position {}: adjustment overfl
- cannot calculate CFD swap for position {}: currency conversi
- Simulation module {module_index} log_diagnostics failed: {e:
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/886edf17ef89ceff.
Report an issue: GitHub.