{"record":{"id":"5dd5aecc11372dbd","repo":"nautechsystems/nautilus_trader","slug":"cannot-calculate-cfd-swap-for-position-adjustm","errorCode":null,"errorMessage":"cannot calculate CFD swap for position {}: adjustment overflow","messagePattern":"cannot calculate CFD swap for position (.+?): adjustment overflow","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/modules/cfd_swap.rs","lineNumber":287,"sourceCode":"            } else {\n                Decimal::ONE\n            };\n\n            for position in positions {\n                let daily_rate = if position.is_long() {\n                    rate.long_rate\n                } else if position.is_short() {\n                    rate.short_rate\n                } else {\n                    continue;\n                };\n                let notional = position.try_notional_value(settlement_price)?;\n                let amount = notional\n                    .as_decimal()\n                    .checked_mul(daily_rate)\n                    .and_then(|value| value.checked_mul(multiplier))\n                    .ok_or_else(|| {\n                        anyhow::anyhow!(\n                            \"cannot calculate CFD swap for position {}: adjustment overflow\",\n                            position.id\n                        )\n                    })?;\n                let (amount, currency) = if let Some(base_currency) = ctx.base_currency {\n                    let xrate = match ctx.cache.try_get_xrate(\n                        ctx.venue,\n                        notional.currency,\n                        base_currency,\n                        PriceType::Mid,\n                    ) {\n                        Ok(Some(xrate)) => xrate,\n                        Ok(None) => {\n                            self.log_calculation_failure(\n                                booking_date,\n                                instrument_id,\n                                CfdSwapFailureKind::Xrate,\n                                &format!(","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/modules/cfd_swap.rs#L269-L305","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the configured daily swap rate and contract multiplier for scale errors (rate should be a small fraction, e.g. 0.0001)","Validate position sizes and notional values for corruption before the rollover day","Reduce position sizes or correct the instrument definition so notional stays within Decimal range"],"exampleFix":"// before\n\"swap_rate\": 500.0, // meant 0.05%\n// after\n\"swap_rate\": 0.0005,","handlingStrategy":"validation","validationCode":"// validate config scale before running\nassert!(daily_rate.abs() < Decimal::new(1, 2), \"swap rate should be a small fraction\");\nassert!(*multiplier < Decimal::from(1_000_000), \"multiplier out of range\");","typeGuard":null,"tryCatchPattern":"match module.process(ts_now) {\n    Ok(r) => r,\n    Err(e) if e.to_string().contains(\"adjustment overflow\") => {\n        log::error!(\"check swap rate/multiplier/position size: {e:#}\");\n        SimulationModuleResult::NotReady\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Express swap rates as fractions (0.0001, not 1% = 100)","Verify contract multipliers against the instrument spec","Monitor position sizes for corruption from upstream feed errors"],"tags":["backtest","decimal-overflow","cfd","swap"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}