nautechsystems/nautilus_trader · error
cannot calculate CFD swap for {instrument_id}: midpoint over
Error message
cannot calculate CFD swap for {instrument_id}: midpoint overflow What it means
The CFD swap module computes the settlement price as the midpoint of the instrument's bid/ask using checked Decimal arithmetic. If bid+ask overflows the Decimal range (or division by two fails), it cannot form a midpoint and throws this error rather than producing a corrupted price.
Source
Thrown at crates/backtest/src/modules/cfd_swap.rs:188
}
fn settlement_price(
ctx: &ExchangeContext,
instrument_id: InstrumentId,
) -> anyhow::Result<Option<Price>> {
let Some(matching_engine) = ctx.matching_engines.get(&instrument_id) else {
return Ok(None);
};
let book = matching_engine.get_book();
match (book.best_bid_price(), book.best_ask_price()) {
(Some(bid), Some(ask)) => {
let midpoint = bid
.as_decimal()
.checked_add(ask.as_decimal())
.and_then(|sum| sum.checked_div(Decimal::TWO))
.ok_or_else(|| {
anyhow::anyhow!(
"cannot calculate CFD swap for {instrument_id}: midpoint overflow"
)
})?;
Ok(Some(Price::from_decimal(midpoint)?))
}
(Some(price), None) | (None, Some(price)) => Ok(Some(price)),
(None, None) => Ok(None),
}
}
fn log_calculation_failure(
&self,
booking_date: Date,
instrument_id: InstrumentId,
kind: CfdSwapFailureKind,
message: &str,
) {
let first_failure = selfView on GitHub (pinned to 18893faf8b)
Solutions
- Verify the instrument's price_precision/size and the data feed's price scaling; correct mis-scaled bid/ask data
- Clamp or normalize extreme bid/ask values before the bar/quote reaches the module
- Check upstream data for corruption (e.g. concatenated digits) and filter bad ticks
Example fix
// before: feeding raw prices with wrong scale let bid = Price::from_raw(79228162514264337593543950335); // near Decimal::MAX // after: validate magnitude before use assert!(bid.as_decimal() < Decimal::from(1_000_000), "bid out of expected range");
Defensive patterns
Strategy: validation
Validate before calling
// sanity-check quote magnitudes before the module computes midpoints
fn valid_price(p: Price) -> bool {
let d = p.as_decimal();
d > Decimal::ZERO && d < Decimal::from(1_000_000)
}
assert!(valid_price(bid) && valid_price(ask)); Type guard
fn sane_price(p: &Price) -> bool {
p.as_decimal() > Decimal::ZERO && p.as_decimal() < Decimal::from(1_000_000)
} Try / catch
match module.settlement_price(&instrument_id, ts) {
Ok(price) => /* use price */,
Err(e) if e.to_string().contains("midpoint overflow") => log::warn!("bad quote data: {e:#}"),
Err(e) => return Err(e),
} Prevention
- Verify instrument price_precision matches the data feed's scaling
- Filter or clamp out-of-range ticks/quotes at ingestion
- Validate data files for corrupted price fields
When it happens
Trigger: Calling settlement_price for an instrument whose bid and ask Decimals are so large their sum exceeds Decimal's maximum (e.g. mis-scaled prices like 1e28 for a low-precision instrument), when both bid and ask are present.
Common situations: Instruments configured with wrong precision/scale so prices parse as enormous Decimals; corrupted data where bid/ask carry garbage magnitudes; mixing price scales across data sources.
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 position {}: adjustment overfl
- cannot calculate CFD swap for position {}: currency conversi
- 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/02d58e36b1509b2b.
Report an issue: GitHub.