{"record":{"id":"9f2047f8002a6848","repo":"nautechsystems/nautilus_trader","slug":"python-on-historical-quotes-failed-e-9f2047","errorCode":null,"errorMessage":"Python on_historical_quotes failed: {e}","messagePattern":"Python on_historical_quotes failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/trading/src/python/strategy.rs","lineNumber":1234,"sourceCode":"            };\n            self.dispatch_on_historical_data(py_data)\n                .map_err(|e| anyhow::anyhow!(\"Python on_historical_data failed: {e}\"))\n        })\n    }\n\n    fn on_historical_book_deltas(&mut self, deltas: &[OrderBookDelta]) -> anyhow::Result<()> {\n        self.dispatch_on_historical_book_deltas(deltas.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_book_deltas failed: {e}\"))\n    }\n\n    fn on_historical_book_depth(&mut self, depths: &[OrderBookDepth10]) -> anyhow::Result<()> {\n        self.dispatch_on_historical_book_depth(depths.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_book_depth failed: {e}\"))\n    }\n\n    fn on_historical_quotes(&mut self, quotes: &[QuoteTick]) -> anyhow::Result<()> {\n        self.dispatch_on_historical_quotes(quotes.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_quotes failed: {e}\"))\n    }\n\n    fn on_historical_trades(&mut self, trades: &[TradeTick]) -> anyhow::Result<()> {\n        self.dispatch_on_historical_trades(trades.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_trades failed: {e}\"))\n    }\n\n    fn on_historical_funding_rates(\n        &mut self,\n        funding_rates: &[FundingRateUpdate],\n    ) -> anyhow::Result<()> {\n        self.dispatch_on_historical_funding_rates(funding_rates.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_funding_rates failed: {e}\"))\n    }\n\n    fn on_historical_bars(&mut self, bars: &[Bar]) -> anyhow::Result<()> {\n        self.dispatch_on_historical_bars(bars.to_vec())\n            .map_err(|e| anyhow::anyhow!(\"Python on_historical_bars failed: {e}\"))","sourceCodeStart":1216,"sourceCodeEnd":1252,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/trading/src/python/strategy.rs#L1216-L1252","documentation":"Raised when the strategy's Python `on_historical_quotes` handler throws while processing historical QuoteTicks. The Rust bridge clones the quote slice, dispatches via PyO3, and wraps any error with this anyhow message. The underlying failure is an unhandled exception in the user's Python handler.","triggerScenarios":"Historical quote data loads (backtest warm-up or data request) and `on_historical_quotes(self, quotes)` raises — e.g. computing spreads on empty lists, dividing by zero bid/ask, or wrong attribute usage.","commonSituations":"Handlers computing rolling stats during warm-up with empty windows; division by zero when ask is 0/None; handlers written for bars mistakenly wired to quotes.","solutions":["Read the Python traceback in `e` and fix `on_historical_quotes`","Guard against empty quote lists and zero/None bid-ask values before computing","Verify signature `on_historical_quotes(self, quotes: list[QuoteTick])`","Test warm-up with an empty-quote scenario"],"exampleFix":"// before (Python)\ndef on_historical_quotes(self, quotes):\n    spread = quotes[-1].ask_price - quotes[-1].bid_price  # IndexError when empty\n// after\ndef on_historical_quotes(self, quotes):\n    if not quotes:\n        return\n    spread = quotes[-1].ask_price - quotes[-1].bid_price","handlingStrategy":"validation","validationCode":"def quotes_ok(quotes):\n    return bool(quotes) and all(q.ask_price > 0 and q.bid_price > 0 for q in quotes)","typeGuard":"def quotes_usable(quotes):\n    return quotes is not None and len(quotes) > 0 and quotes[-1].ask_price is not None and quotes[-1].bid_price is not None","tryCatchPattern":"try:\n    strategy.on_historical_quotes(quotes)\nexcept Exception as e:\n    strategy.log.error(f\"on_historical_quotes failed: {e}\", exc_info=True)","preventionTips":["Return early on empty quote lists","Guard zero/negative bid-ask before spread math","Warm-up code must tolerate insufficient history windows","Match handler to data type — don't wire bar logic to quote callbacks"],"tags":["rust","python","nautilustrader","callback","historical-data"],"backgroundTag":"python-callback-exception","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"}