{"record":{"id":"ef8853d2f17a7aaa","repo":"nautechsystems/nautilus_trader","slug":"calculate-from-positions-impl-err","errorCode":null,"errorMessage":"`calculate_from_positions` {IMPL_ERR} `{}`","messagePattern":"`calculate_from_positions` (.+?) `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/analysis/src/statistic.rs","lineNumber":69,"sourceCode":"    /// Calculates the statistic from realized profit and loss values.\n    ///\n    /// # Panics\n    ///\n    /// Panics if this method is not implemented for the specific statistic.\n    fn calculate_from_realized_pnls(&self, realized_pnls: &[f64]) -> Option<Self::Item> {\n        panic!(\n            \"`calculate_from_realized_pnls` {IMPL_ERR} `{}`\",\n            self.name()\n        );\n    }\n\n    /// Calculates the statistic from position data.\n    ///\n    /// # Panics\n    ///\n    /// Panics if this method is not implemented for the specific statistic.\n    fn calculate_from_positions(&self, positions: &[Position]) -> Option<Self::Item> {\n        panic!(\"`calculate_from_positions` {IMPL_ERR} `{}`\", self.name());\n    }\n\n    /// Calculates the statistic from time-indexed strategy returns relative to a benchmark.\n    ///\n    /// Defaults to `None`; only benchmark-relative statistics (beta, alpha, information\n    /// ratio, tracking error, Treynor ratio) override this method. The `None` default\n    /// lets analyzer loops filter results by `Option` - non-benchmark statistics are\n    /// simply skipped, as `get_performance_stats_general` already does with\n    /// `calculate_from_positions` results - rather than panicking.\n    fn calculate_from_returns_with_benchmark(\n        &self,\n        returns: &Returns,\n        benchmark: &Returns,\n    ) -> Option<Self::Item> {\n        None\n    }\n\n    /// Aligns two returns series onto a common daily grid.","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/analysis/src/statistic.rs#L51-L87","documentation":"The default `calculate_from_positions` on the statistic trait panics when a statistic that does not implement it is called with position data. It marks the statistic as unsupported for position-based calculation.","triggerScenarios":"Analyzer computing statistics from `&[Position]` for a statistic that only implements returns- or realized-PnL-based calculation.","commonSituations":"Returns-based statistics (Sharpe, Sortino) registered into position-based portfolio analysis; custom trait impls missing the positions method.","solutions":["Implement `calculate_from_positions` on the statistic.","Or compute the statistic from the input it supports.","Or remove the statistic from position-based analysis registration."],"exampleFix":"// before\nimpl PerformanceStatistic for SharpeRatio {\n    fn calculate_from_returns(&self, r: &Returns) -> Option<f64> { Some(calc(r)) }\n}\nanalyzer.calculate_from_positions(&positions); // panic\n// after\nimpl PerformanceStatistic for SharpeRatio {\n    fn calculate_from_returns(&self, r: &Returns) -> Option<f64> { Some(calc(r)) }\n    fn calculate_from_positions(&self, _: &[Position]) -> Option<f64> { None }\n}","handlingStrategy":"type-guard","validationCode":"// only feed position-capable statistics\nlet stats = stats.into_iter().filter(|s| s.supports_positions()).collect::<Vec<_>>();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Return None (not panic) from unsupported methods by implementing them explicitly","Keep returns-based and position-based statistics in separate analyzer registrations","Add tests that call each calculate_from_* method for custom statistics"],"tags":["analysis","statistics","rust","trait"],"backgroundTag":"method-not-implemented","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"}