{"record":{"id":"2578eccc59684375","repo":"nautechsystems/nautilus_trader","slug":"interest-rate-for-location-at-must-be-fi","errorCode":null,"errorMessage":"Interest rate for location '{}' at '{}' must be finite, was {}","messagePattern":"Interest rate for location '(.+?)' at '(.+?)' must be finite, was (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/backtest/src/modules/fx_rollover.rs","lineNumber":91,"sourceCode":"    pyo3::pyclass(module = \"nautilus_trader.backtest\", from_py_object)\n)]\n#[cfg_attr(\n    feature = \"python\",\n    pyo3_stub_gen::derive::gen_stub_pyclass(module = \"nautilus_trader.backtest\")\n)]\npub struct InterestRateRecord {\n    /// OECD location code using ISO 3166 alpha-3 (e.g., \"AUS\", \"USA\") or \"EA19\".\n    /// Records with unsupported codes are ignored.\n    pub location: String,\n    /// Time period key (e.g., \"2024-01\" for monthly, \"2024-Q1\" for quarterly).\n    pub time: String,\n    /// Interest rate value as a percentage (e.g., 5.25 means 5.25%). Must be finite.\n    pub value: f64,\n}\n\nimpl InterestRateRecord {\n    pub(crate) fn validate(&self) -> anyhow::Result<()> {\n        anyhow::ensure!(\n            self.value.is_finite(),\n            \"Interest rate for location '{}' at '{}' must be finite, was {}\",\n            self.location,\n            self.time,\n            self.value\n        );\n        Ok(())\n    }\n}\n\n/// Calculates overnight rollover interest rates for FX currency pairs.\n///\n/// Uses short-term interest rate data (OECD format) to compute the daily\n/// differential between base and quote currency rates.\n#[derive(Debug, Clone)]\npub struct RolloverInterestCalculator {\n    // currency code -> {time_key -> rate_percentage}\n    rates: AHashMap<String, AHashMap<String, f64>>,","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/backtest/src/modules/fx_rollover.rs#L73-L109","documentation":"Validation error thrown by `InterestRateRecord::validate` when an interest-rate record's `value` is not finite (NaN or infinity). FX rollover rate data must contain well-formed finite percentages; the module rejects such records before use rather than producing NaN downstream calculations.","triggerScenarios":"Loading an FX/interest-rate data file containing NaN, Infinity, or a parse that yields non-finite floats (empty fields coerced to NaN, scientific overflow like 1e400).","commonSituations":"Malformed CSV/parquet rate files with blank values; data exported from spreadsheets with #DIV/0! or overflowed cells; hand-edited rate tables with typos.","solutions":["Inspect the rate data file at the reported location/time and fix or remove the non-finite value.","Add pre-load validation that parses each value with strict parsing (reject empty/NaN/inf) before building InterestRateRecords.","Fill missing rate entries with a defined fallback (e.g. previous value or zero) via your data pipeline, not NaN.","Re-export the data source avoiding formulas that can yield errors or infinities."],"exampleFix":"// before\nlet value: f64 = row.get(\"rate\").unwrap().parse().unwrap_or(f64::NAN);\n\n// after\nlet raw = row.get(\"rate\").ok_or(\"missing rate\")?;\nlet value: f64 = raw.trim().parse()?;\nanyhow::ensure!(value.is_finite(), \"non-finite rate {raw}\");","handlingStrategy":"validation","validationCode":"let value: f64 = raw.trim().parse()?;\nif !value.is_finite() {\n    return Err(anyhow::anyhow!(\"non-finite interest rate for {} at {}: {raw}\", location, time));\n}","typeGuard":"fn is_valid_rate(v: f64) -> bool { v.is_finite() && v.abs() < 1000.0 }","tryCatchPattern":"let records: Vec<InterestRateRecord> = load_records(path)?;\nfor r in &records {\n    if let Err(e) = r.validate() {\n        log::error!(\"bad rate record: {e}\");\n        return Err(e);\n    }\n}","preventionTips":["Validate all rate records at load time, before the backtest starts","Use strict CSV/parquet parsing that errors on empty numeric fields","Clean spreadsheet exports of formula errors (#DIV/0!, overflow cells)"],"tags":["fx","validation","nan","input-data"],"backgroundTag":"schema-validation-failed","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"}