nautechsystems/nautilus_trader · error

commission calculation overflow

Error message

commission calculation overflow

What it means

Fee models compute commissions with `Decimal` arithmetic. `mul_checked` wraps `Decimal::checked_mul` and raises this error when multiplying the rate by a quantity/price (or similar factors) would overflow the Decimal representation. It is a guard against silently producing an invalid commission.

Source

Thrown at crates/execution/src/models/fee.rs:326

}

impl PerContractFeeModel {
    /// Creates a new [`PerContractFeeModel`] instance.
    ///
    /// # Errors
    ///
    /// Returns an error if `commission` is negative.
    pub fn new(commission: Money) -> anyhow::Result<Self> {
        if commission.raw < 0 {
            anyhow::bail!("Commission must be greater than or equal to zero")
        }
        Ok(Self { commission })
    }
}

fn mul_checked(lhs: Decimal, rhs: Decimal) -> anyhow::Result<Decimal> {
    lhs.checked_mul(rhs)
        .ok_or_else(|| anyhow::anyhow!("commission calculation overflow"))
}

impl FeeModel for PerContractFeeModel {
    fn get_commission(
        &self,
        _order: &OrderAny,
        fill_quantity: Quantity,
        _fill_px: Price,
        instrument: &InstrumentAny,
    ) -> anyhow::Result<Money> {
        let contracts = spread_contract_count(instrument)?;
        let total = mul_checked(self.commission.as_decimal(), fill_quantity.as_decimal())
            .and_then(|v| mul_checked(v, contracts))?;
        Money::from_decimal(total, self.commission.currency).map_err(Into::into)
    }
}

fn spread_contract_count(instrument: &InstrumentAny) -> anyhow::Result<Decimal> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Validate fill quantity, fill price, and instrument multiplier are sane before computing commission.
  2. Reduce/fix the fee model parameters (rate, cap) that produce overflow-sized products.
  3. If legitimately large values are needed, scale the computation or use a wider numeric representation upstream.

Example fix

// before: unchecked inputs
let fee = model.get_commission(&order, qty, px, &instrument)?;
// after: pre-validate magnitudes
assert!(qty.as_decimal() < Decimal::MAX / instrument.multiplier().as_decimal());
let fee = model.get_commission(&order, qty, px, &instrument)?;
Defensive patterns

Strategy: validation

Validate before calling

assert qty.as_decimal() > Decimal::ZERO && qty.as_decimal() < Decimal::from(1_000_000)
assert instrument.multiplier().as_decimal() < Decimal::MAX / px.as_decimal()

Try / catch

match model.get_commission(&order, qty, px, &instrument) {
    Ok(fee) => fee,
    Err(e) if e.to_string().contains("overflow") => Money::zero(currency),
}

Prevention

When it happens

Trigger: Calling `get_commission`/`get_commission_with_context` on a fee model (e.g. PerContractFeeModel, capped option fee model) with extreme fill quantities, prices, multipliers, or cap values whose product exceeds Decimal range.

Common situations: Instruments with enormous multipliers, malformed fill data (astronomical quantity), or a misconfigured fee cap/rate; running backtests on synthetic data with unbounded values.

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