{"record":{"id":"e338666a1fadf2f9","repo":"nautechsystems/nautilus_trader","slug":"calculate-from-returns-impl-err","errorCode":null,"errorMessage":"`calculate_from_returns` {IMPL_ERR} `{}`","messagePattern":"`calculate_from_returns` (.+?) `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/analysis/src/statistic.rs","lineNumber":48,"sourceCode":"///\n/// The analyzer calls `calculate_from_returns`, `calculate_from_realized_pnls`, and\n/// `calculate_from_positions` on every registered statistic, and their defaults panic, so an\n/// implementation must override all three and return `None` for a category it does not support.\n/// `calculate_from_returns_with_benchmark` defaults to `None` and is optional.\n#[allow(unused_variables)]\npub trait PortfolioStatistic: Debug {\n    type Item;\n\n    /// Returns the name of this statistic for display and identification purposes.\n    fn name(&self) -> String;\n\n    /// Calculates the statistic from time-indexed returns data.\n    ///\n    /// # Panics\n    ///\n    /// Panics if this method is not implemented for the specific statistic.\n    fn calculate_from_returns(&self, returns: &Returns) -> Option<Self::Item> {\n        panic!(\"`calculate_from_returns` {IMPL_ERR} `{}`\", self.name());\n    }\n\n    /// 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    ///","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/analysis/src/statistic.rs#L30-L66","documentation":"`PortfolioAnalyzer`/statistic trait's default `calculate_from_returns` panics because the concrete statistic did not override it. Statistics must implement the calculation method for the input type the analyzer will feed them; calling the unimplemented default is a programming error.","triggerScenarios":"Registering a statistic with the portfolio analyzer and computing performance from `Returns` while that statistic only implements `calculate_from_positions` or `calculate_from_realized_pnls`.","commonSituations":"Custom `PerformanceStatistic` implementations that only override one calculation method; using a position-based statistic (e.g. certain expectancy variants) in a returns-based analysis path.","solutions":["Implement `calculate_from_returns` for the statistic type.","Or compute that statistic from the input type it supports (positions or realized PnLs) instead.","If the statistic genuinely cannot be returns-based, guard the analysis path to skip it for returns input."],"exampleFix":"// before\nimpl PerformanceStatistic for MyStat {\n    fn calculate_from_positions(&self, _: &[Position]) -> Option<f64> { Some(0.0) }\n}\nanalyzer.calculate_from_returns(&returns); // panic\n// after\nimpl PerformanceStatistic for MyStat {\n    fn calculate_from_returns(&self, returns: &Returns) -> Option<f64> {\n        Some(my_stat_from_returns(returns))\n    }\n    fn calculate_from_positions(&self, _: &[Position]) -> Option<f64> { Some(0.0) }\n}","handlingStrategy":"type-guard","validationCode":"// pick statistics that support returns input\nlet stats: Vec<Box<dyn PerformanceStatistic>> = vec![Box::new(SharpeRatio::new(...))];\nassert!(stats.iter().all(|s| s.supports_returns()), \"statistic does not support returns input\");","typeGuard":"fn is_returns_compatible(stat: &dyn PerformanceStatistic) -> bool {\n    // a statistic supports returns if it overrides calculate_from_returns\n    stat.calculate_from_returns(&Returns::default()).is_some() || stat.is_returns_based()\n}","tryCatchPattern":null,"preventionTips":["Implement all trait methods (returning None where unsupported) in custom statistics","Register each statistic only into analysis paths matching its implemented methods","Document which input type each custom statistic supports"],"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-14T00:17:10.932Z"}