{"record":{"id":"58bd644c03865346","repo":"nautechsystems/nautilus_trader","slug":"overflow-when-scaling-f64-to-fixed-point-i64","errorCode":null,"errorMessage":"Overflow when scaling f64 to fixed-point i64","messagePattern":"Overflow when scaling f64 to fixed-point i64","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/types/fixed.rs","lineNumber":870,"sourceCode":"///\n/// # Panics\n///\n/// Panics if `precision` exceeds [`FIXED_PRECISION`], or if scaling the rounded value\n/// overflows the raw integer range.\n#[must_use]\n#[expect(\n    clippy::cast_precision_loss,\n    clippy::cast_possible_truncation,\n    reason = \"f64 to fixed-point conversion is inherently lossy; callers validate range and finiteness\"\n)]\npub fn f64_to_fixed_i64(value: f64, precision: u8) -> i64 {\n    check_fixed_precision(precision).expect_display(FAILED);\n    let pow1 = 10_i64.pow(u32::from(precision));\n    let pow2 = 10_i64.pow(u32::from(FIXED_PRECISION - precision));\n    let rounded = (value * pow1 as f64).round() as i64;\n    rounded\n        .checked_mul(pow2)\n        .expect(\"Overflow when scaling f64 to fixed-point i64\")\n}\n\n/// Converts an `f64` value to a raw fixed-point `i128` representation with a specified precision.\n///\n/// Callers are expected to validate that `value` is finite and within range; non-finite\n/// values saturate at the integer bounds during the float-to-integer cast.\n///\n/// # Panics\n///\n/// Panics if `precision` exceeds [`FIXED_PRECISION`], or if scaling the rounded value\n/// overflows the raw integer range.\n#[must_use]\n#[expect(\n    clippy::cast_precision_loss,\n    clippy::cast_possible_truncation,\n    reason = \"f64 to fixed-point conversion is inherently lossy; callers validate range and finiteness\"\n)]\npub fn f64_to_fixed_i128(value: f64, precision: u8) -> i128 {","sourceCodeStart":852,"sourceCodeEnd":888,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/types/fixed.rs#L852-L888","documentation":"f64_to_fixed_i64 converts a float to raw fixed-point i64 by first rounding at the requested precision and then multiplying by 10^(FIXED_PRECISION - precision). A checked_mul is used and panics with this message when the scaled value exceeds i64 range. The library prefers a loud panic over silent precision loss.","triggerScenarios":"Calling f64_to_fixed_i64(value, precision) with a value whose magnitude, after scaling to FIXED_PRECISION raw digits, exceeds i64::MAX/i64::MIN — e.g. f64_to_fixed_i64(1e18, 0) or any value near 9.3e18 with positive precision.","commonSituations":"Pricing or sizing data loaded from external feeds with unrealistically large magnitudes; unit tests probing the overflow boundary; precision configuration that leaves too little headroom in i64.","solutions":["Validate |value| * 10^FIXED_PRECISION fits in i64 before calling, or clamp inputs to the representable range.","Use f64_to_fixed_i128 for large magnitudes.","Reduce the value magnitude (e.g. express in different units) or lower precision needs."],"exampleFix":"// before\nlet raw = f64_to_fixed_i64(1e19, 0); // panics\n// after\nlet raw = if value.abs() > f64::from(i64::MAX) / 10f64.powi(FIXED_PRECISION) {\n    return Err(...);\n} else {\n    f64_to_fixed_i64(value, precision)\n};","handlingStrategy":"validation","validationCode":"const MAX: f64 = i64::MAX as f64 / 10f64.powi(FIXED_PRECISION);\nassert!(value.is_finite() && value.abs() <= MAX, \"value out of i64 fixed range\");\nlet raw = f64_to_fixed_i64(value, precision);","typeGuard":"fn fits_i64_fixed(value: f64) -> bool {\n    value.is_finite() && value.abs() <= i64::MAX as f64 / 10f64.powi(FIXED_PRECISION)\n}","tryCatchPattern":null,"preventionTips":["Validate magnitudes at the ingestion boundary (feeds, CSVs, APIs).","Use i128 variants for anything that can approach 1e18.","Add boundary unit tests for the largest values your domain produces."],"tags":["rust","overflow","fixed-point","arithmetic"],"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-14T00:17:10.932Z"}