nautechsystems/nautilus_trader · error · anyhow::Error

Invalid peg_offset_value: {s}

Error message

Invalid peg_offset_value: {s}

What it means

parse_peg_offset_value reads the optional peg_offset_value string from order command Params and parses it as f64. A present value that is not a valid f64 number produces this error, preventing a malformed peg offset from being sent to BitMEX.

Source

Thrown at crates/adapters/bitmex/src/common/parse.rs:522

        Some(s) => BitmexPegPriceType::from_str(s)
            .map(Some)
            .map_err(|_| anyhow::anyhow!("Invalid peg_price_type: {s}")),
        None => Ok(None),
    }
}

/// Extracts the peg offset value from order command parameters.
///
/// # Errors
///
/// Returns an error if the value is present but not a valid `f64`.
pub fn parse_peg_offset_value(params: Option<&Params>) -> anyhow::Result<Option<f64>> {
    let value = params.and_then(|p| p.get_str("peg_offset_value"));
    match value {
        Some(s) => s
            .parse::<f64>()
            .map(Some)
            .map_err(|_| anyhow::anyhow!("Invalid peg_offset_value: {s}")),
        None => Ok(None),
    }
}

/// Derives a deterministic [`TradeId`] for BitMEX trades that arrive without a
/// `trdMatchID` (e.g. certain historical or bucketed rows).
///
/// The hash combines the symbol, timestamp, price, size, and side so replayed
/// data yields the same identifier across runs. FNV-1a is stable across
/// architectures and crate versions; the 0x1f delimiter keeps variable-length
/// fields from colliding.
#[must_use]
pub fn derive_trade_id(
    symbol: Ustr,
    ts_event_ns: u64,
    price: f64,
    size: i64,
    side: Option<BitmexSide>,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass peg_offset_value as a plain numeric string, e.g. "0.005"
  2. Convert Decimal/price values with a plain to_string (no thousands separators or suffixes) before inserting into Params
  3. Validate the value parses as f64 before submitting

Example fix

// before
params.insert("peg_offset_value", format!("{} bps", offset_bps));
// after
params.insert("peg_offset_value", (offset_bps as f64 / 10000.0).to_string());
Defensive patterns

Strategy: validation

Validate before calling

fn peg_offset_ok(s: &str) -> bool { s.trim().parse::<f64>().is_ok() }

Type guard

fn is_numeric_string(s: &str) -> bool { s.parse::<f64>().is_ok() }

Try / catch

match client.submit_order(order) {
    Err(e) if e.to_string().starts_with("Invalid peg_offset_value") => {
        log::error!("peg_offset_value must be a plain f64 string: {e}");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Submitting an order with peg_offset_value in Params set to a non-numeric string (e.g. "10 bps", "1,000", empty string).

Common situations: Strategies formatting the offset with units or locale separators; passing a Decimal-formatted value with commas; wiring a config string directly into Params.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/84a8ee9c5a0ad722. Report an issue: GitHub.