Analysis¶
- class Alpha¶
Bases:
objectCalculates Jensen’s alpha of portfolio returns relative to a benchmark.
Alpha measures the excess return of a portfolio over the return predicted by its beta exposure to the benchmark (CAPM). The per-period alpha is:
alpha = (mean_portfolio - rf) - beta * (mean_benchmark - rf)
where beta is the sample (ddof = 1) beta of the portfolio against the benchmark. The per-period alpha is then annualized geometrically over period (default 252):
alpha_annual = (1 + alpha)^period - 1
The risk-free rate rf is specified per period (default 0.0).
# References
Jensen, M. C. (1968). “The Performance of Mutual Funds in the Period 1945-1964”. Journal of Finance, 23(2), 389-416.
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- calculate_from_returns_with_benchmark(returns, benchmark)¶
- name¶
- class AvgLoser¶
Bases:
objectCalculates the average losing trade from realized PnLs.
Only negative PnLs count as losers. Returns NaN for an empty series or when there are no losing trades.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
- class AvgWinner¶
Bases:
objectCalculates the average winning trade from realized PnLs.
Only positive PnLs count as winners. Returns NaN for an empty series or when there are no winning trades.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
- class BetaRatio¶
Bases:
objectCalculates the beta of portfolio returns relative to a benchmark.
Beta measures the systematic risk (market sensitivity) of a portfolio and is calculated as the covariance of the portfolio and benchmark returns divided by the variance of the benchmark returns:
Beta = Cov(portfolio, benchmark) / Var(benchmark)
Sample (Bessel-corrected, ddof = 1) covariance and variance are used to match the standard deviation convention elsewhere in this crate. Beta is not annualized.
# References
Sharpe, W. F. (1964). “Capital Asset Prices: A Theory of Market Equilibrium under Conditions of Risk”. Journal of Finance, 19(3), 425-442.
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- calculate_from_returns_with_benchmark(returns, benchmark)¶
- name¶
- class CAGR¶
Bases:
objectCalculates the Compound Annual Growth Rate (CAGR) for returns.
CAGR represents the mean annual growth rate of an investment over a specified period, assuming the profits were reinvested at the end of each period.
Formula: CAGR = (Ending Value / Beginning Value)^(Period/Days) - 1
For returns: CAGR = ((1 + Total Return)^(Period/Days)) - 1
# References
Bacon, C. R. (2008). Practical Portfolio Performance Measurement and Attribution (2nd ed.). Wiley.
CFA Institute Level I Curriculum: Quantitative Methods
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class CalmarRatio¶
Bases:
objectCalculates the Calmar Ratio for returns.
The Calmar Ratio is a function of the fund’s average compounded annual rate of return versus its maximum drawdown. The higher the Calmar ratio, the better it performed on a risk-adjusted basis during the given time frame.
Formula: Calmar Ratio = CAGR / |Max Drawdown|
# References
Young, T. W. (1991). “Calmar Ratio: A Smoother Tool”. Futures, 20(1).
Bacon, C. R. (2008). Practical Portfolio Performance Measurement and Attribution (2nd ed.). Wiley.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class DownCaptureRatio¶
Bases:
objectCalculates the down capture ratio of portfolio returns relative to a benchmark.
The down capture ratio measures how the portfolio performed, on average, during the periods when the benchmark return was negative. It is the ratio of the portfolio’s geometric annualized return to the benchmark’s geometric annualized return, both computed over the down-market subset only:
DownCapture = annualized_return(portfolio | benchmark < 0) / annualized_return(benchmark | benchmark < 0)
where each side’s annualized return is the geometric (CAGR-style) value (prod(1 + x_i))^(period / m) - 1 and m is the number of down-market periods (the size of the filtered subset, not the full aligned length). The period defaults to 252 trading days. A value below 1.0 means the portfolio lost less than the benchmark in down markets (smaller drawdowns), which is desirable.
This is the empyrical.down_capture convention (geometric annualized-return ratio over the benchmark < 0 subset). Note that this differs from the Morningstar definition, which uses a ratio of cumulative (non-annualized) returns; the two coincide only when both subsets contain the same number of periods.
# References
empyrical down_capture / capture / annual_return (<https://github.com/quantopian/empyrical>).
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- calculate_from_returns_with_benchmark(returns, benchmark)¶
- name¶
- class Expectancy¶
Bases:
objectCalculates the expectancy of a trading strategy based on realized PnLs.
Expectancy is defined as: (Average Win × Win Rate) + (Average Loss × Loss Rate) This metric provides insight into the expected profitability per trade and helps evaluate the overall edge of a trading strategy.
A positive expectancy indicates a profitable system over time, while a negative expectancy suggests losses.
# References
Tharp, V. K. (1998). Trade Your Way to Financial Freedom. McGraw-Hill.
Elder, A. (1993). Trading for a Living. John Wiley & Sons.
Vince, R. (1992). The Mathematics of Money Management. John Wiley & Sons.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
- class ExpectedShortfall¶
Bases:
objectCalculates the historical Expected Shortfall (Conditional Value at Risk) of portfolio returns.
Expected Shortfall is the average of the losses that occur beyond the [ValueAtRisk](crate::statistics::value_at_risk::ValueAtRisk) threshold at a given confidence level - the mean of the worst 1 - confidence tail of the return distribution. It is a coherent risk measure and captures tail severity that VaR alone does not.
ES(c) = mean( r | r <= VaR(c) )
confidence defaults to 0.95. The result is expressed as a return (e.g. -0.05 is a 5% expected tail loss); it is always less than or equal to the corresponding VaR. Returns NaN for an empty series.
# References
Acerbi, C., & Tasche, D. (2002). “Expected Shortfall: A Natural Coherent Alternative to Value at Risk”. Economic Notes, 31(2), 379-388.
Rockafellar, R. T., & Uryasev, S. (2000). “Optimization of Conditional Value-at-Risk”. Journal of Risk, 2(3), 21-41.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class InformationRatio¶
Bases:
objectCalculates the information ratio of portfolio returns relative to a benchmark.
The information ratio measures active return per unit of active risk (tracking error):
IR = mean(active) / std(active) * sqrt(period)
where active_i = portfolio_i - benchmark_i, std uses Bessel’s correction (ddof = 1), and the ratio is annualized by the square root of the specified period (default: 252 trading days).
# References
Goodwin, T. H. (1998). “The Information Ratio”. Financial Analysts Journal, 54(4), 34-43.
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- calculate_from_returns_with_benchmark(returns, benchmark)¶
- name¶
- class LongRatio¶
Bases:
objectCalculates the ratio of long positions to total positions.
A position counts as long when its entry (opening order) side is Buy. The result is in [0, 1], rounded to precision decimal places, and is None for an empty position list.
- calculate_from_positions(positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
- class MaxDrawdown¶
Bases:
objectCalculates the Maximum Drawdown for returns.
Maximum Drawdown is the maximum observed loss from a peak to a trough, before a new peak is attained. It is an indicator of downside risk over a specified time period.
Formula: Max((Peak - Trough) / Peak) for all peak-trough sequences
The equity curve compounds returns from a starting value of 1.0, and the result is reported as a negative fraction (e.g. -0.20 is a 20% drawdown).
# References
Bacon, C. R. (2008). Practical Portfolio Performance Measurement and Attribution (2nd ed.). Wiley.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class MaxLoser¶
Bases:
objectCalculates the largest losing trade (most negative PnL) from realized PnLs.
Only negative PnLs count as losers. Returns NaN for an empty series or when there are no losing trades.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
- class MaxWinner¶
Bases:
objectCalculates the largest winning trade from realized PnLs.
Only positive PnLs count as winners. Returns NaN for an empty series or when there are no winning trades.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(returns)¶
- name¶
- class MinLoser¶
Bases:
objectCalculates the smallest losing trade (least negative PnL) from realized PnLs.
Only negative PnLs count as losers. Returns NaN for an empty series or when there are no losing trades.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
- class MinWinner¶
Bases:
objectCalculates the smallest winning trade from realized PnLs.
Only positive PnLs count as winners. Returns NaN for an empty series or when there are no winning trades.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
- class OmegaRatio¶
Bases:
objectCalculates the Omega ratio of portfolio returns.
The Omega ratio is the ratio of probability-weighted gains to losses relative to a return threshold θ. It captures the entire return distribution (all moments), unlike the Sharpe ratio which only uses the first two:
Omega(θ) = sum(max(r - θ, 0)) / sum(max(θ - r, 0))
The threshold θ defaults to 0 (gains vs losses about zero). A value above 1 means gains above the threshold outweigh losses below it. Returns NaN for an empty series, or when there are no returns below the threshold (the ratio is undefined).
# References
Keating, C., & Shadwick, W. F. (2002). “A Universal Performance Measure”. Journal of Performance Measurement, 6(3), 59-84.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class PortfolioAnalyzer¶
Bases:
objectAnalyzes portfolio performance and calculates various statistics.
The PortfolioAnalyzer tracks account balances, positions, and realized PnLs to provide portfolio analysis including returns, PnL calculations, and customizable statistics.
- add_position_return(timestamp, value)¶
Records a position return at a specific timestamp.
- add_positions(positions)¶
Adds new positions for analysis.
- add_return(timestamp, value)¶
Records a return at a specific timestamp.
This is a backward-compatible alias for Self.add_position_return.
- add_trade(position_id, ts_event, realized_pnl)¶
Records a trade’s PnL realized at ts_event.
- currencies()¶
Returns all tracked currencies.
- deregister_statistic(statistic)¶
Removes a specific statistic from calculation.
- deregister_statistics()¶
Removes all registered statistics.
- get_performance_stats_general()¶
Gets general portfolio statistics.
- get_performance_stats_pnls(currency, unrealized_pnl)¶
Gets all PnL-related performance statistics.
# Errors
Returns an error if PnL calculations fail, for example due to:
No currency specified for a multi-currency portfolio.
Unrealized PnL currency not matching the specified currency.
Specified currency not found in account balances.
- get_performance_stats_portfolio_returns()¶
Gets all portfolio-return-based performance statistics.
- get_performance_stats_position_returns()¶
Gets all position-return-based performance statistics.
- get_performance_stats_returns()¶
Gets all return-based performance statistics.
- get_performance_stats_returns_vs_benchmark(benchmark)¶
Gets all benchmark-relative return statistics for the primary returns.
This is stateless: the benchmark series is supplied by the caller rather than stored on the analyzer. Only statistics that override PortfolioStatistic.calculate_from_returns_with_benchmark (the benchmark-relative statistics) contribute values; all others return None and are skipped.
- get_stats_general_formatted()¶
Gets formatted general statistics as strings.
- get_stats_pnls_formatted(currency, unrealized_pnl)¶
Gets formatted PnL statistics as strings.
# Errors
Returns an error if PnL statistics calculation fails.
- get_stats_portfolio_returns_formatted()¶
Gets formatted portfolio-return statistics as strings.
- get_stats_position_returns_formatted()¶
Gets formatted position-return statistics as strings.
- get_stats_returns_formatted()¶
Gets formatted return statistics as strings.
- portfolio_returns()¶
Returns the portfolio calculated returns.
- position_returns()¶
Returns the per-position calculated returns.
- realized_pnls(currency)¶
Retrieves realized PnLs for a specific currency.
Each record is (position_id, ts_event, realized_pnl). Returns None if no PnLs exist, or if multiple currencies exist without an explicit currency specified.
- record_trade(position_id, ts_event, realized_pnl)¶
Records a trade’s PnL realized at ts_event, observed during portfolio processing.
- register_statistic(statistic)¶
Registers a new portfolio statistic for calculation.
- reset()¶
Resets all analysis data to initial state.
- returns()¶
Returns the primary calculated returns.
This returns portfolio returns when available, otherwise it falls back to position returns for backward compatibility.
- statistic(name)¶
Retrieves a specific statistic by name.
- total_pnl(currency, unrealized_pnl)¶
Calculates total PnL including unrealized PnL if provided.
# Errors
Returns an error if: - No currency is specified in a multi-currency portfolio. - The specified currency is not found in account balances. - The unrealized PnL currency does not match the specified currency.
- total_pnl_percentage(currency, unrealized_pnl)¶
Calculates total PnL as a percentage of starting balance.
# Errors
Returns an error if: - No currency is specified in a multi-currency portfolio. - The specified currency is not found in account balances. - The unrealized PnL currency does not match the specified currency.
- class PortfolioStatistics¶
Bases:
objectAn owned snapshot of computed portfolio performance statistics.
pnls is keyed by currency code, each value mapping statistic name to value.
- general¶
- pnls¶
- returns¶
- returns_series¶
- class ProfitFactor¶
Bases:
objectCalculates the profit factor based on portfolio returns.
Profit factor is defined as the ratio of gross profits to gross losses: Sum(Positive Returns) / Abs(Sum(Negative Returns))
A profit factor greater than 1.0 indicates a profitable strategy, while a factor less than 1.0 indicates losses exceed gains.
Generally: - 1.0-1.5: Modest profitability - 1.5-2.0: Good profitability - > 2.0: Excellent profitability
# References
Tharp, V. K. (1998). Trade Your Way to Financial Freedom. McGraw-Hill.
Kaufman, P. J. (2013). Trading Systems and Methods (5th ed.). Wiley.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class ReturnsAverage¶
Bases:
objectCalculates the arithmetic mean of portfolio returns.
All returns are included, so zero returns count toward the average. Returns NaN for an empty series.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class ReturnsAverageLoss¶
Bases:
objectCalculates the arithmetic mean of the negative portfolio returns.
Zero returns are excluded (neither wins nor losses). Returns NaN for an empty series or when there are no negative returns.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class ReturnsAverageWin¶
Bases:
objectCalculates the arithmetic mean of the positive portfolio returns.
Zero returns are excluded (neither wins nor losses). Returns NaN for an empty series or when there are no positive returns.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class ReturnsKurtosis¶
Bases:
objectCalculates the excess kurtosis of portfolio returns.
Kurtosis measures the heaviness of the tails of the return distribution relative to a normal distribution. A positive value indicates fatter tails (more outliers); a negative value indicates thinner tails.
Uses the bias-corrected sample excess kurtosis (adjusted Fisher-Pearson), matching pandas.Series.kurt and Excel KURT. A normal distribution yields 0:
- `G2 = n(n + 1) / ((n - 1)(n - 2)(n - 3)) * sum(((x - mean) / s)^4)
3(n - 1)^2 / ((n - 2)(n - 3))`
where s is the sample standard deviation (Bessel’s correction, ddof=1). Returns NaN for fewer than four returns or zero dispersion.
# References
Joanes, D. N., & Gill, C. A. (1998). Comparing measures of sample skewness and kurtosis. Journal of the Royal Statistical Society: Series D, 47(1), 183-189.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class ReturnsSkewness¶
Bases:
objectCalculates the skewness of portfolio returns.
Skewness measures the asymmetry of the return distribution about its mean. A negative value indicates a longer left tail (downside outliers); a positive value indicates a longer right tail.
Uses the bias-corrected sample skewness (adjusted Fisher-Pearson), matching pandas.Series.skew and Excel SKEW:
G1 = n / ((n - 1)(n - 2)) * sum(((x - mean) / s)^3)
where s is the sample standard deviation (Bessel’s correction, ddof=1). Returns NaN for fewer than three returns or zero dispersion.
# References
Joanes, D. N., & Gill, C. A. (1998). Comparing measures of sample skewness and kurtosis. Journal of the Royal Statistical Society: Series D, 47(1), 183-189.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class ReturnsVolatility¶
Bases:
objectCalculates the annualized volatility (standard deviation) of portfolio returns.
Volatility is calculated as the standard deviation of returns, annualized by multiplying the daily standard deviation by the square root of the period: Standard Deviation * sqrt(period)
Uses Bessel’s correction (ddof=1) for sample standard deviation. This provides a measure of the portfolio’s risk or uncertainty of returns.
# References
CFA Institute Level I Curriculum: Quantitative Methods
Hull, J. C. (2018). Options, Futures, and Other Derivatives (10th ed.). Pearson.
Fabozzi, F. J., et al. (2002). The Handbook of Financial Instruments. Wiley.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class RiskReturnRatio¶
Bases:
objectCalculates the risk-return ratio (mean/std) for portfolio returns.
This is a non-annualized ratio of mean return to standard deviation. For an annualized version, use SharpeRatio.
Downsamples high-frequency returns to daily bins before calculation for consistency with other ratio-based statistics.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class SharpeRatio¶
Bases:
objectCalculates the Sharpe ratio for portfolio returns.
The Sharpe ratio measures risk-adjusted return and is calculated as: (Mean Return - Risk-free Rate) / Standard Deviation of Returns * sqrt(period)
This implementation assumes a risk-free rate of 0 and annualizes the ratio using the square root of the specified period (default: 252 trading days).
# References
Sharpe, W. F. (1966). “Mutual Fund Performance”. Journal of Business, 39(1), 119-138.
Sharpe, W. F. (1994). “The Sharpe Ratio”. Journal of Portfolio Management, 21(1), 49-58.
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class SortinoRatio¶
Bases:
objectCalculates the Sortino ratio for portfolio returns.
The Sortino ratio is a variation of the Sharpe ratio that only penalizes downside volatility, making it more appropriate for strategies with asymmetric return distributions.
Formula: Mean Return / Downside Deviation * sqrt(period)
Where downside deviation is calculated as: sqrt(sum(negative_returns^2) / total_observations)
Note: Uses total observations count (not just negative returns) as per Sortino’s methodology.
# References
Sortino, F. A., & van der Meer, R. (1991). “Downside Risk”. Journal of Portfolio Management, 17(4), 27-31.
Sortino, F. A., & Price, L. N. (1994). “Performance Measurement in a Downside Risk Framework”. Journal of Investing, 3(3), 59-64.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class TailRatio¶
Bases:
objectCalculates the tail ratio of portfolio returns.
The tail ratio compares the magnitude of the right (gain) tail to the left (loss) tail of the return distribution. It is the absolute ratio of the 95th to the 5th percentile of returns:
TailRatio = | percentile(r, 95) / percentile(r, 5) |
Percentiles use linear interpolation between closest ranks, matching numpy.percentile and pandas.Series.quantile with the default linear method (the convention used by the quantstats tail-ratio definition).
A value greater than 1 indicates a heavier upside tail (gains larger in magnitude than losses); a value below 1 indicates a heavier downside tail. Returns NaN for fewer than two returns or when the 5th percentile is zero.
# References
empyrical tail_ratio (<https://github.com/quantopian/empyrical>).
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class TrackingError¶
Bases:
objectCalculates the tracking error of portfolio returns relative to a benchmark.
Tracking error is the volatility of the active return (portfolio minus benchmark):
TE = std(active) * sqrt(period)
where active_i = portfolio_i - benchmark_i, std uses Bessel’s correction (ddof = 1), and the result is annualized by the square root of the specified period (default: 252 trading days).
# References
Roll, R. (1992). “A Mean/Variance Analysis of Tracking Error”. Journal of Portfolio Management, 18(4), 13-22.
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- calculate_from_returns_with_benchmark(returns, benchmark)¶
- name¶
- class TreynorRatio¶
Bases:
objectCalculates the Treynor ratio of portfolio returns relative to a benchmark.
The Treynor ratio measures excess return per unit of systematic risk (beta):
Treynor = (annualized_return - rf_annual) / beta
The portfolio’s annualized return is computed geometrically (CAGR-style) from the aligned returns: annualized_return = (prod(1 + r_i))^(period / n) - 1. The per-period risk-free rate is annualized geometrically as rf_annual = (1 + rf)^period - 1. Beta is the sample (ddof = 1) beta of the portfolio against the benchmark. The period defaults to 252 trading days and rf defaults to 0.0.
# References
Treynor, J. L. (1965). “How to Rate Management of Investment Funds”. Harvard Business Review, 43(1), 63-75.
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- calculate_from_returns_with_benchmark(returns, benchmark)¶
- name¶
- class UlcerIndex¶
Bases:
objectCalculates the Ulcer Index of portfolio returns.
The Ulcer Index measures downside risk as the root-mean-square of the percentage drawdowns of the cumulative-return equity curve. Unlike volatility it only penalizes downside deviations, and unlike maximum drawdown it accounts for both the depth and the duration of drawdowns.
The equity curve compounds returns from a starting value of 1.0, and each drawdown is measured against the running peak (matching the convention used by [MaxDrawdown](super::max_drawdown::MaxDrawdown)):
UI = sqrt( mean( D_i^2 ) ), where D_i = (peak_i - equity_i) / peak_i
Drawdowns are expressed as fractions (0.05 = 5%), so the result is on the same scale as MaxDrawdown (the original definition uses percentage points). Returns 0.0 for an empty series.
# References
Martin, P. G., & McCann, B. B. (1989). The Investor’s Guide to Fidelity Funds. Wiley.
Peter Martin’s Ulcer Index page (<https://www.tangotools.com/ui/ui.htm>).
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class UpCaptureRatio¶
Bases:
objectCalculates the up capture ratio of portfolio returns relative to a benchmark.
The up capture ratio measures how the portfolio performed, on average, during the periods when the benchmark return was positive. It is the ratio of the portfolio’s geometric annualized return to the benchmark’s geometric annualized return, both computed over the up-market subset only:
UpCapture = annualized_return(portfolio | benchmark > 0) / annualized_return(benchmark | benchmark > 0)
where each side’s annualized return is the geometric (CAGR-style) value (prod(1 + x_i))^(period / m) - 1 and m is the number of up-market periods (the size of the filtered subset, not the full aligned length). The period defaults to 252 trading days. A value above 1.0 means the portfolio outperformed the benchmark in up markets.
This is the empyrical.up_capture convention (geometric annualized-return ratio over the benchmark > 0 subset). Note that this differs from the Morningstar definition, which uses a ratio of cumulative (non-annualized) returns; the two coincide only when both subsets contain the same number of periods.
# References
empyrical up_capture / capture / annual_return (<https://github.com/quantopian/empyrical>).
CFA Institute Investment Foundations, 3rd Edition
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(_returns)¶
- calculate_from_returns_with_benchmark(returns, benchmark)¶
- name¶
- class ValueAtRisk¶
Bases:
objectCalculates the historical Value at Risk (VaR) of portfolio returns.
VaR is the loss threshold that returns are not expected to exceed at a given confidence level. This is the non-parametric (historical) estimator: the empirical quantile of the return distribution at 1 - confidence.
VaR(c) = quantile(returns, 1 - c)
The quantile uses linear interpolation between closest ranks (matching numpy.percentile). confidence defaults to 0.95. The result is expressed as a return (e.g. -0.03 is a 3% loss threshold); more negative means greater risk. Returns NaN for an empty series.
# References
Jorion, P. (2007). Value at Risk: The New Benchmark for Managing Financial Risk (3rd ed.). McGraw-Hill.
J.P. Morgan/Reuters (1996). RiskMetrics Technical Document (4th ed.).
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(_realized_pnls)¶
- calculate_from_returns(raw_returns)¶
- name¶
- class WinRate¶
Bases:
objectCalculates the win rate of a trading strategy based on realized PnLs.
Win rate is the percentage of profitable trades out of total trades: Count(Trades with PnL > 0) / Total Trades
Returns a value between 0.0 and 1.0, where 1.0 represents 100% winning trades.
Note: While a high win rate is desirable, it should be considered alongside average win/loss sizes and profit factor for complete system evaluation.
# References
Standard trading performance metric across the industry
Tharp, V. K. (1998). Trade Your Way to Financial Freedom. McGraw-Hill.
Kaufman, P. J. (2013). Trading Systems and Methods (5th ed.). Wiley.
- calculate_from_positions(_positions)¶
- calculate_from_realized_pnls(realized_pnls)¶
- calculate_from_returns(_returns)¶
- name¶
Configuration for tearsheet generation and visualization.
- class TearsheetChart¶
Bases:
objectBase class for tearsheet chart configuration.
Concrete chart classes define which chart to render (via name) and can expose additional arguments (via kwargs) that are passed into the chart renderer.
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetRunInfoChart¶
Bases:
TearsheetChartTearsheetRunInfoChart(*, title: ‘str | None’ = None)
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetStatsTableChart¶
Bases:
TearsheetChartTearsheetStatsTableChart(*, title: ‘str | None’ = None)
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetEquityChart¶
Bases:
TearsheetChartTearsheetEquityChart(*, title: ‘str | None’ = None)
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetDrawdownChart¶
Bases:
TearsheetChartTearsheetDrawdownChart(*, title: ‘str | None’ = None)
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetMonthlyReturnsChart¶
Bases:
TearsheetChartTearsheetMonthlyReturnsChart(*, title: ‘str | None’ = None, compounding: ‘bool’ = True)
- compounding: bool = True¶
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetDistributionChart¶
Bases:
TearsheetChartTearsheetDistributionChart(*, title: ‘str | None’ = None)
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetRollingSharpeChart¶
Bases:
TearsheetChartTearsheetRollingSharpeChart(*, title: ‘str | None’ = None)
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetYearlyReturnsChart¶
Bases:
TearsheetChartTearsheetYearlyReturnsChart(*, title: ‘str | None’ = None, compounding: ‘bool’ = True)
- compounding: bool = True¶
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetBarsWithFillsChart¶
Bases:
TearsheetChartRender bars_with_fills for a specific bar type (string form accepted).
- bar_type: str¶
- property name: str¶
- kwargs() dict[str, Any]¶
- class TearsheetCustomChart¶
Bases:
TearsheetChartConfigure a tearsheet chart by its registered name.
This is intended for charts registered for tearsheet integration (i.e. present in the tearsheet chart spec registry).
- chart: str¶
- args: dict[str, Any]¶
- property name: str¶
- kwargs() dict[str, Any]¶
- class GridLayout¶
Bases:
objectGrid layout specification for tearsheet subplots.
- Parameters:
rows (int, default 4) – Number of rows in the grid.
cols (int, default 2) – Number of columns in the grid.
heights (list[float], default [0.50, 0.22, 0.16, 0.12]) – Relative heights for each row (must sum to 1.0 or be proportional).
vertical_spacing (float, default 0.10) – Vertical spacing between subplots (0.0 to 1.0).
horizontal_spacing (float, default 0.10) – Horizontal spacing between subplots (0.0 to 1.0).
- rows: int = 4¶
- cols: int = 2¶
- heights: list[float]¶
- vertical_spacing: float = 0.1¶
- horizontal_spacing: float = 0.1¶
- class TearsheetConfig¶
Bases:
objectConfiguration for tearsheet generation.
- Parameters:
charts (list[TearsheetChart], default built-ins) – Charts to include in the tearsheet, in order. Example: charts=[TearsheetRunInfoChart(title=”Run Info”)].
theme (str, default "plotly_white") – Theme name for visualization styling. Built-in themes: “plotly_white”, “plotly_dark”, “nautilus”, “nautilus_dark”.
layout (GridLayout | None, default None) – Custom grid layout specification. If None, auto-calculated based on charts.
title (str, default "NautilusTrader Backtest Results") – Title for the tearsheet.
include_benchmark (bool, default True) – Whether to include benchmark comparison in visualizations. Only applies when benchmark_returns data is provided.
benchmark_name (str, default "Benchmark") – Display name for the benchmark in visualizations.
height (int, default 1500) – Total height of the tearsheet in pixels.
show_logo (bool, default True) – Whether to display NautilusTrader logo in the tearsheet.
- charts: list[TearsheetChart]¶
- theme: str = 'plotly_white'¶
- layout: GridLayout | None = None¶
- title: str = 'NautilusTrader Backtest Results'¶
- include_benchmark: bool = True¶
- benchmark_name: str = 'Benchmark'¶
- height: int = 1500¶
- show_logo: bool = True¶
- property chart_names: list[str]¶
Backtest visualization and tearsheet generation using Plotly.
This module provides functions to create interactive tearsheets and plots from backtest results, using backtest result statistics and report DataFrames.
- register_chart(name: str, func: Callable | None = None) Callable | None¶
Register a custom chart function for standalone use.
Registered charts are retrievable via
get_chartandlist_charts. Placing a custom chart in a tearsheet grid uses the separateregister_tearsheet_chartpath (see the visualization guide); a name registered here is not rendered byTearsheetCustomChart.Can be used as a decorator or called directly.
- Parameters:
name (str) – The chart name for later lookup via
get_chart/list_charts.func (Callable, optional) – Chart function that returns a plotly Figure. Should accept (returns: pd.Series, **kwargs) as parameters. If None, returns a decorator.
- Returns:
The decorated function if used as a decorator, otherwise None.
- Return type:
Callable or None
- Raises:
ValueError – If name is empty or func is not callable.
Examples
>>> # As a decorator >>> @register_chart("my_custom_chart") ... def create_custom_chart(returns: pd.Series, **kwargs) -> go.Figure: ... fig = go.Figure() ... # ... custom visualization logic ... return fig >>> >>> # Or called directly >>> register_chart("another_chart", create_custom_chart)
- get_chart(name: str) Callable¶
Get registered chart function by name.
- Parameters:
name (str) – The chart name.
- Returns:
The chart function.
- Return type:
Callable
- Raises:
KeyError – If the chart name is not registered.
- list_charts() list[str]¶
List all registered chart names.
- Returns:
List of available chart names.
- Return type:
list[str]
- create_tearsheet(engine: BacktestEngine | BacktestResult, output_path: str | None = 'tearsheet.html', title: str = 'NautilusTrader Backtest Results', currency=None, config=None, benchmark_returns: pd.Series | None = None, benchmark_name: str = 'Benchmark', node: BacktestNode | None = None, run_config_id: str | None = None) str | None¶
Generate an interactive HTML tearsheet from backtest results.
- Parameters:
engine (BacktestEngine or BacktestResult) – The completed backtest engine or result.
output_path (str, optional) – Path to save the tearsheet. File extension selects the format:
.html(interactive), or.png,.jpg,.webp,.svg,.pdf(static, via Kaleido). If None, returns HTML string.title (str, default "NautilusTrader Backtest Results") – Title for the tearsheet.
currency (Currency, optional) – Currency filter for PnL statistics, account balances, and engine-derived returns. For
BacktestResultinput, the stored return series remains unchanged. If None, includes all available currencies.config (TearsheetConfig, optional) – Configuration for tearsheet customization. If None, uses default configuration.
benchmark_returns (pd.Series, optional) – Benchmark returns series for comparison. If provided, benchmark will be overlaid on visualizations.
benchmark_name (str, default "Benchmark") – Display name for the benchmark.
node (BacktestNode, optional) – The node which produced a
BacktestResult. Provide it for starting balances or charts that read cached data, such asbars_with_fills. The matching run configuration must setdispose_on_completion=False.run_config_id (str, optional) – The run configuration ID. Defaults to
engine.run_config_id.
- Returns:
HTML string if output_path is None, otherwise None.
- Return type:
str or None
- Raises:
ImportError – If plotly is not installed.
ValueError – If
bars_with_fillsis configured without a node, a supplied node has no run configuration ID, or the matching run configuration setsdispose_on_completion=True.
- create_tearsheet_from_stats(stats_pnls: dict[str, Any] | dict[str, dict[str, Any]], stats_returns: dict[str, Any], stats_general: dict[str, Any], returns: Series, output_path: str | None = 'tearsheet.html', title: str = 'NautilusTrader Backtest Results', config=None, benchmark_returns: Series | None = None, benchmark_name: str = 'Benchmark', run_info: dict[str, Any] | None = None, account_info: dict[str, Any] | None = None, engine=None) str | None¶
Generate an interactive HTML tearsheet from precomputed statistics.
This lower-level API is useful for offline analysis when you have precomputed statistics and don’t want to pass an engine.
- Parameters:
stats_pnls (dict[str, Any]) – PnL-based statistics.
stats_returns (dict[str, Any]) – Returns-based statistics.
stats_general (dict[str, Any]) – General statistics.
returns (pd.Series) – Returns series.
output_path (str, optional) – Path to save the tearsheet. File extension selects the format:
.html(interactive), or.png,.jpg,.webp,.svg,.pdf(static, via Kaleido). If None, returns HTML string.title (str, default "NautilusTrader Backtest Results") – Title for the tearsheet.
config (TearsheetConfig, optional) – Configuration for tearsheet customization. If None, uses default configuration.
benchmark_returns (pd.Series, optional) – Benchmark returns series for comparison. If provided, benchmark will be overlaid on visualizations.
benchmark_name (str, default "Benchmark") – Display name for the benchmark.
run_info (dict[str, Any], optional) – Run metadata (run ID, timestamps, backtest period, event counts).
account_info (dict[str, Any], optional) – Account information (starting/ending balances per currency).
engine (BacktestEngine, optional) – The backtest engine. Required for charts that need engine access (e.g., bars_with_fills).
- Returns:
HTML string if output_path is None, otherwise None.
- Return type:
str or None
- Raises:
ImportError – If plotly is not installed.
Examples
>>> # Offline analysis with precomputed stats >>> stats_returns = {"Sharpe Ratio (252 days)": 1.5} >>> stats_general = {"Win Rate": 0.55} >>> stats_pnls = {"PnL (total)": 10000.0} >>> returns = pd.Series([0.01, -0.02]) >>> html = create_tearsheet_from_stats( ... stats_pnls, ... stats_returns, ... stats_general, ... returns, ... output_path=None, # Return HTML instead of saving ... )
- create_equity_curve(returns: Series, output_path: str | None = None, title: str = 'Equity Curve', benchmark_returns: Series | None = None, benchmark_name: str = 'Benchmark') Figure¶
Create an interactive equity curve plot with optional benchmark overlay.
- Parameters:
returns (pd.Series) – Returns series.
output_path (str, optional) – Path to save HTML plot. If None, plot is not saved.
title (str, default "Equity Curve") – Plot title.
benchmark_returns (pd.Series, optional) – Benchmark returns series for comparison. If provided, benchmark equity curve will be overlaid on the chart.
benchmark_name (str, default "Benchmark") – Display name for the benchmark in the legend.
- Returns:
Plotly figure object.
- Return type:
go.Figure
- Raises:
ImportError – If plotly is not installed.
- create_drawdown_chart(returns: Series, output_path: str | None = None, title: str = 'Drawdown', theme: str = 'plotly_white') Figure¶
Create an interactive drawdown chart.
- Parameters:
returns (pd.Series) – Returns series.
output_path (str, optional) – Path to save HTML plot. If None, plot is not saved.
title (str, default "Drawdown") – Plot title.
theme (str, default "plotly_white") – Theme name for styling.
- Returns:
Plotly figure object.
- Return type:
go.Figure
- Raises:
ImportError – If plotly is not installed.
- create_monthly_returns_heatmap(returns: Series, output_path: str | None = None, title: str | None = None, compounding: bool = True) Figure¶
Create an interactive monthly returns heatmap.
- Parameters:
returns (pd.Series) – Returns series.
output_path (str, optional) – Path to save HTML plot. If None, plot is not saved.
title (str, optional) – Plot title. Defaults to a basis-aware title derived from compounding.
compounding (bool, default True) – If True, cells compound against the running start-of-month balance. If False, cells are simple returns on fixed initial capital that sum to the total return (the nominal rate of return).
- Returns:
Plotly figure object.
- Return type:
go.Figure
- Raises:
ImportError – If plotly is not installed.
- create_returns_distribution(returns: Series, output_path: str | None = None, title: str = 'Returns Distribution') Figure¶
Create an interactive returns distribution histogram.
- Parameters:
returns (pd.Series) – Returns series.
output_path (str, optional) – Path to save HTML plot. If None, plot is not saved.
title (str, default "Returns Distribution") – Plot title.
- Returns:
Plotly figure object.
- Return type:
go.Figure
- Raises:
ImportError – If plotly is not installed.
- create_rolling_sharpe(returns: Series, window: int = 60, output_path: str | None = None, title: str = 'Rolling Sharpe Ratio (60-day)') Figure¶
Create an interactive rolling Sharpe ratio chart.
- Parameters:
returns (pd.Series) – Returns series.
window (int, default 60) – Rolling window size in days.
output_path (str, optional) – Path to save HTML plot. If None, plot is not saved.
title (str, default "Rolling Sharpe Ratio (60-day)") – Plot title.
- Returns:
Plotly figure object.
- Return type:
go.Figure
- Raises:
ImportError – If plotly is not installed.
- create_yearly_returns(returns: Series, output_path: str | None = None, title: str | None = None, compounding: bool = True) Figure¶
Create an interactive yearly returns bar chart.
- Parameters:
returns (pd.Series) – Returns series.
output_path (str, optional) – Path to save HTML plot. If None, plot is not saved.
title (str, optional) – Plot title. Defaults to a basis-aware title derived from compounding.
compounding (bool, default True) – If True, bars compound against the running start-of-year balance. If False, bars are simple returns on fixed initial capital that sum to the total return (the nominal rate of return).
- Returns:
Plotly figure object.
- Return type:
go.Figure
- Raises:
ImportError – If plotly is not installed.
- create_bars_with_fills(engine: BacktestEngine, bar_type: BarType, title: str | None = None, theme: str = 'plotly_white', output_path: str | None = None) go.Figure¶
Create a candlestick chart with order fills overlaid as bar charts.
This visualization shows price bars (OHLC) as candlesticks and order fills as vertical bars colored by side (buy/sell).
- Parameters:
engine – The backtest engine with completed run.
bar_type (BarType) – The bar type to visualize.
title (str, optional) – Plot title. If None, uses bar_type string.
theme (str, default "plotly_white") – Theme name for styling.
output_path (str, optional) – Path to save HTML plot. If None, plot is not saved.
- Returns:
Plotly figure object with candlestick and fill bars.
- Return type:
go.Figure
- Raises:
ImportError – If plotly is not installed.
- register_tearsheet_chart(name: str, subplot_type: str, title: str, renderer: Callable) None¶
Register a custom chart renderer for tearsheet integration.
The registered
namecan then be placed in a tearsheet viaTearsheetConfig(charts=[TearsheetCustomChart(chart=name)]). This differs fromregister_chart, which registers standalone chart functions that return their own figure; tearsheet renderers instead draw onto a shared subplot grid cell.- Parameters:
name (str) – Chart name referenced by
TearsheetCustomChart(chart=name).subplot_type (str) – Plotly subplot type (‘scatter’, ‘bar’, ‘table’, ‘heatmap’, ‘histogram’).
title (str) – Display title for the subplot.
renderer (Callable) – Function that adds traces to the figure. Signature: renderer(fig, row, col, returns, stats_pnls, stats_returns, stats_general, theme_config, benchmark_returns, benchmark_name, run_info, account_info, engine, **kwargs)
- Raises:
ValueError – If name is empty or renderer is not callable.
Theme registry and built-in themes for tearsheet visualization.
- get_theme(name: str) dict[str, Any]¶
Get theme configuration by name.
- Parameters:
name (str) – The theme name. Built-in themes: “plotly_white”, “plotly_dark”, “nautilus”, “nautilus_dark”.
- Returns:
Theme configuration dictionary with “template” and “colors” keys.
- Return type:
dict[str, Any]
- Raises:
KeyError – If the theme name is not registered.
- register_theme(name: str, template: str, colors: dict[str, str]) None¶
Register a custom theme.
- Parameters:
name (str) – The theme name for future reference.
template (str) – Plotly template name (e.g., “plotly_white”, “plotly_dark”, “ggplot2”).
colors (dict[str, str]) – Color palette dictionary. Expected keys: “primary”, “positive”, “negative”, “neutral”, “background”, “grid”. All values should be hex color codes.
- Raises:
ValueError – If name is empty or colors dict is missing required keys.
Examples
>>> register_theme( ... "custom", ... "plotly_white", ... { ... "primary": "#ff6600", ... "positive": "#00ff00", ... "negative": "#ff0000", ... "neutral": "#808080", ... "background": "#ffffff", ... "grid": "#dddddd", ... }, ... )
- list_themes() list[str]¶
List all registered theme names.
- Returns:
List of available theme names.
- Return type:
list[str]
Pandas report generation for backtest results.
pandas is an optional dependency (pip install pandas); it is imported lazily so that nautilus_trader.analysis can be imported without it.
- class ReportProvider¶
Bases:
objectProvides various portfolio analysis reports.
- static generate_orders_report(orders: list) pd.DataFrame¶
- static generate_order_fills_report(orders: list) pd.DataFrame¶
- static generate_fills_report(orders: list) pd.DataFrame¶
- static generate_account_report(account) pd.DataFrame¶