nautechsystems/nautilus_trader · error
`calculate_from_returns` {IMPL_ERR} `{}`
Error message
`calculate_from_returns` {IMPL_ERR} `{}` What it means
`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.
Source
Thrown at crates/analysis/src/statistic.rs:48
///
/// The analyzer calls `calculate_from_returns`, `calculate_from_realized_pnls`, and
/// `calculate_from_positions` on every registered statistic, and their defaults panic, so an
/// implementation must override all three and return `None` for a category it does not support.
/// `calculate_from_returns_with_benchmark` defaults to `None` and is optional.
#[allow(unused_variables)]
pub trait PortfolioStatistic: Debug {
type Item;
/// Returns the name of this statistic for display and identification purposes.
fn name(&self) -> String;
/// Calculates the statistic from time-indexed returns data.
///
/// # Panics
///
/// Panics if this method is not implemented for the specific statistic.
fn calculate_from_returns(&self, returns: &Returns) -> Option<Self::Item> {
panic!("`calculate_from_returns` {IMPL_ERR} `{}`", self.name());
}
/// Calculates the statistic from realized profit and loss values.
///
/// # Panics
///
/// Panics if this method is not implemented for the specific statistic.
fn calculate_from_realized_pnls(&self, realized_pnls: &[f64]) -> Option<Self::Item> {
panic!(
"`calculate_from_realized_pnls` {IMPL_ERR} `{}`",
self.name()
);
}
/// Calculates the statistic from position data.
///
/// # Panics
///View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before
impl PerformanceStatistic for MyStat {
fn calculate_from_positions(&self, _: &[Position]) -> Option<f64> { Some(0.0) }
}
analyzer.calculate_from_returns(&returns); // panic
// after
impl PerformanceStatistic for MyStat {
fn calculate_from_returns(&self, returns: &Returns) -> Option<f64> {
Some(my_stat_from_returns(returns))
}
fn calculate_from_positions(&self, _: &[Position]) -> Option<f64> { Some(0.0) }
} Defensive patterns
Strategy: type-guard
Validate before calling
// pick statistics that support returns input let stats: Vec<Box<dyn PerformanceStatistic>> = vec![Box::new(SharpeRatio::new(...))]; assert!(stats.iter().all(|s| s.supports_returns()), "statistic does not support returns input");
Type guard
fn is_returns_compatible(stat: &dyn PerformanceStatistic) -> bool {
// a statistic supports returns if it overrides calculate_from_returns
stat.calculate_from_returns(&Returns::default()).is_some() || stat.is_returns_based()
} Prevention
- 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
When it happens
Trigger: 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`.
Common situations: 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.
Related errors
- `calculate_from_realized_pnls` {IMPL_ERR} `{}`
- `calculate_from_positions` {IMPL_ERR} `{}`
- `handle_quote_tick` {IMPL_ERR} `{}`
- Warning: Column name '{column_name}' is not of type i64.
- Warning: Statistics not available for column '{column_name}'
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e338666a1fadf2f9.
Report an issue: GitHub.