跳转至

Metrics Reference

Return, risk, drawdown, trade, and factor evaluation metrics.

Back to API Reference

Portfolio and factor metrics.

autocorrelation

autocorrelation(factor: Series, lag: int = 1, nan_policy: NanPolicy = 'drop') -> pd.Series

Compute lagged factor rank autocorrelation by date.

Parameters

factor : pandas.Series Factor values indexed by (date, symbol). lag : int, default 1 Number of date observations to lag. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing rows are handled.

Returns

pandas.Series Cross-sectional rank autocorrelation by date.

Examples

import pandas as pd idx = pd.MultiIndex.from_product( ... [pd.to_datetime(["2024-01-01", "2024-01-02"]), ["A", "B"]], ... names=["date", "symbol"], ... ) autocorrelation(pd.Series([1, 2, 1, 2], idx)).round(4).tolist() [1.0]

factor_returns

factor_returns(factor: Series, prices: Series, quantiles: int = 5, nan_policy: NanPolicy = 'drop') -> pd.DataFrame

Compute quantile forward returns from prices.

Parameters

factor : pandas.Series Factor values indexed by (date, symbol). prices : pandas.Series Prices indexed by (date, symbol). quantiles : int, default 5 Number of date-level factor quantiles. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing aligned rows are handled.

Returns

pandas.DataFrame Mean next-period returns by date and factor quantile.

Examples

import pandas as pd idx = pd.MultiIndex.from_product( ... [pd.to_datetime(["2024-01-01", "2024-01-02"]), ["A", "B"]], ... names=["date", "symbol"], ... ) out = factor_returns(pd.Series([1, 2], idx[:2]), pd.Series([100, 100, 110, 90], idx), 2) out.round(4).to_dict("list")

ic

ic(factor: Series, forward_returns: Series, nan_policy: NanPolicy = 'drop', groupby: Series | None = None, by_group: bool = False) -> pd.Series

Compute per-date Pearson information coefficient.

Parameters

factor : pandas.Series Factor values indexed by (date, symbol). forward_returns : pandas.Series Forward returns indexed by (date, symbol). nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing aligned rows are handled.

Returns

pandas.Series Pearson correlation by date.

Examples

import pandas as pd idx = pd.MultiIndex.from_product( ... [pd.to_datetime(["2024-01-01"]), ["A", "B", "C"]], ... names=["date", "symbol"], ... ) ic(pd.Series([1, 2, 3], idx), pd.Series([0.1, 0.2, 0.3], idx)).tolist() [1.0]

ic_ir

ic_ir(ic_series: Series, periods: int, nan_policy: NanPolicy = 'drop') -> float

Annualized information coefficient information ratio.

Parameters

ic_series : pandas.Series Information coefficient values through time. periods : int Periods per year. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing IC values are handled.

Returns

float Annualized IC mean divided by sample standard deviation.

Examples

import pandas as pd round(ic_ir(pd.Series([0.10, 0.20, -0.05, 0.15]), periods=12), 4) 3.2071

quantile_returns

quantile_returns(factor: Series, forward_returns: Series, quantiles: int = 5, nan_policy: NanPolicy = 'drop', groupby: Series | None = None, group_neutral: bool = False) -> pd.DataFrame

Compute mean forward returns by factor quantile.

Parameters

factor : pandas.Series Factor values indexed by (date, symbol). forward_returns : pandas.Series Forward returns indexed by (date, symbol). quantiles : int, default 5 Number of date-level factor quantiles. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing aligned rows are handled.

Returns

pandas.DataFrame Mean forward return by date and quantile. Quantiles are 1-based.

Examples

import pandas as pd idx = pd.MultiIndex.from_product( ... [pd.to_datetime(["2024-01-01"]), ["A", "B"]], ... names=["date", "symbol"], ... ) out = quantile_returns(pd.Series([1, 2], idx), pd.Series([0.1, -0.1], idx), 2) out.to_dict("list")

rank_ic

rank_ic(factor: Series, forward_returns: Series, nan_policy: NanPolicy = 'drop', groupby: Series | None = None, by_group: bool = False) -> pd.Series

Compute per-date Spearman rank information coefficient.

Parameters

factor : pandas.Series Factor values indexed by (date, symbol). forward_returns : pandas.Series Forward returns indexed by (date, symbol). nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing aligned rows are handled.

Returns

pandas.Series Spearman rank correlation by date.

Examples

import pandas as pd idx = pd.MultiIndex.from_product( ... [pd.to_datetime(["2024-01-01"]), ["A", "B", "C"]], ... names=["date", "symbol"], ... ) rank_ic(pd.Series([1, 2, 3], idx), pd.Series([0.3, 0.2, 0.1], idx)).tolist() [-1.0]

turnover

turnover(factor: Series, lag: int = 1, nan_policy: NanPolicy = 'drop') -> pd.Series

Compute factor rank turnover.

Parameters

factor : pandas.Series Factor values indexed by (date, symbol). lag : int, default 1 Date lag used for rank autocorrelation. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing rows are handled.

Returns

pandas.Series 1 - autocorrelation by date.

Examples

import pandas as pd idx = pd.MultiIndex.from_product( ... [pd.to_datetime(["2024-01-01", "2024-01-02"]), ["A", "B"]], ... names=["date", "symbol"], ... ) turnover(pd.Series([1, 2, 2, 1], idx)).tolist() [2.0]

annual_return

annual_return(returns: Series | DataFrame, periods: int, nan_policy: NanPolicy = 'drop') -> float | pd.Series

Compute compound annual growth rate from periodic simple returns.

Parameters

returns : pandas.Series or pandas.DataFrame Periodic simple returns. periods : int Periods per year. For example, 252 for daily stock returns. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled before calculation.

Returns

float or pandas.Series Annualized compound return.

Examples

import pandas as pd round(annual_return(pd.Series([0.01, 0.02, -0.005, 0.004]), periods=252), 4) 5.1113

cum_returns

cum_returns(returns: Series | DataFrame, starting_value: float = 0.0, nan_policy: NanPolicy = 'zero') -> pd.Series | pd.DataFrame

Compute cumulative returns from simple returns.

Parameters

returns : pandas.Series or pandas.DataFrame Periodic simple returns. starting_value : float, default 0.0 If zero, return cumulative return. Otherwise return an equity curve starting from this value. nan_policy : {"drop", "zero", "propagate", "raise"}, default "zero" How missing returns are handled before compounding.

Returns

pandas.Series or pandas.DataFrame Cumulative returns or equity curve.

Examples

import pandas as pd cum_returns(pd.Series([0.10, -0.05, 0.02])).round(4).tolist() [0.1, 0.045, 0.0659]

excess_returns

excess_returns(returns: Series | DataFrame, rf: float, periods: int) -> pd.Series | pd.DataFrame

Subtract per-period risk-free return from simple returns.

Parameters

returns : pandas.Series or pandas.DataFrame Periodic simple returns. rf : float Annualized risk-free rate. periods : int Periods per year.

Returns

pandas.Series or pandas.DataFrame Excess returns.

Examples

import pandas as pd excess_returns(pd.Series([0.01, 0.02]), rf=0.024, periods=12).round(4).tolist() [0.008, 0.018]

log_to_simple

log_to_simple(log_returns: Series | DataFrame) -> pd.Series | pd.DataFrame

Convert log returns to simple returns.

Parameters

log_returns : pandas.Series or pandas.DataFrame Log returns.

Returns

pandas.Series or pandas.DataFrame Simple returns.

Examples

import math, pandas as pd log_to_simple(pd.Series([0.0, math.log(1.05)])).round(4).tolist() [0.0, 0.05]

simple_returns

simple_returns(prices: Series | DataFrame) -> pd.Series | pd.DataFrame

Compute simple returns from prices.

Parameters

prices : pandas.Series or pandas.DataFrame Price series or wide price frame.

Returns

pandas.Series or pandas.DataFrame Periodic simple returns with the first missing period removed.

Examples

import pandas as pd simple_returns(pd.Series([100.0, 105.0, 102.9])).round(4).tolist() [0.05, -0.02]

alpha

alpha(returns: Series, benchmark: Series, periods: int, rf: float = 0.0, nan_policy: NanPolicy = 'drop') -> float

Annualized alpha to a benchmark.

Parameters

returns : pandas.Series Asset or strategy returns. benchmark : pandas.Series Benchmark returns. periods : int Periods per year. rf : float, default 0.0 Annualized risk-free rate. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing aligned rows are handled.

Returns

float Annualized intercept.

Examples

import pandas as pd round(alpha(pd.Series([0.01, 0.02, 0.03]), pd.Series([0.02, 0.03, 0.04]), 252), 4) -0.9206

beta

beta(returns: Series, benchmark: Series, nan_policy: NanPolicy = 'drop') -> float

Beta to a benchmark.

Parameters

returns : pandas.Series Asset or strategy returns. benchmark : pandas.Series Benchmark returns. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing aligned rows are handled.

Returns

float OLS slope using sample covariance and variance.

Examples

import pandas as pd round(beta(pd.Series([0.01, 0.02, 0.03]), pd.Series([0.02, 0.03, 0.04])), 4) 1.0

calmar

calmar(returns: Series, periods: int, nan_policy: NanPolicy = 'drop') -> float

Calmar ratio.

Parameters

returns : pandas.Series Periodic simple returns. periods : int Periods per year. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Annual return divided by absolute maximum drawdown.

Examples

import pandas as pd round(calmar(pd.Series([0.10, -0.20, 0.05, -0.10]), periods=12), 4) -1.7414

cvar

cvar(returns: Series, cutoff: float = 0.05, nan_policy: NanPolicy = 'drop') -> float

Conditional value at risk.

Parameters

returns : pandas.Series Periodic simple returns. cutoff : float, default 0.05 Lower-tail percentile expressed as a fraction. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Mean return at or below the historical VaR threshold.

Examples

import pandas as pd round(cvar(pd.Series([-0.10, -0.04, -0.01, 0.02, 0.05, 0.09])), 4) -0.1

downside_risk

downside_risk(returns: Series, periods: int, required: float = 0.0, nan_policy: NanPolicy = 'drop') -> float

Annualized downside risk.

Parameters

returns : pandas.Series Periodic simple returns. periods : int Periods per year. required : float, default 0.0 Per-period required return threshold. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Annualized downside deviation.

Examples

import pandas as pd round(downside_risk(pd.Series([0.02, -0.01, -0.03, 0.01]), periods=12), 4) 0.0548

drawdown_series

drawdown_series(returns: Series, nan_policy: NanPolicy = 'zero') -> pd.Series

Compute drawdown at each point in a return series.

Parameters

returns : pandas.Series Periodic simple returns. nan_policy : {"drop", "zero", "propagate", "raise"}, default "zero" How missing returns are handled.

Returns

pandas.Series Drawdown series, where zero means no drawdown.

Examples

import pandas as pd drawdown_series(pd.Series([0.10, -0.20, 0.05])).round(2).tolist() [0.0, -0.2, -0.16]

information_ratio

information_ratio(returns: Series, benchmark: Series, periods: int, nan_policy: NanPolicy = 'drop') -> float

Annualized information ratio.

Parameters

returns : pandas.Series Asset or strategy returns. benchmark : pandas.Series Benchmark returns. periods : int Periods per year. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing aligned rows are handled.

Returns

float Active return divided by tracking error.

Examples

import pandas as pd r = pd.Series([0.01, 0.03, 0.02]) b = pd.Series([0.02, 0.01, 0.02]) round(information_ratio(r, b, 252), 4) 3.4641

max_drawdown

max_drawdown(returns: Series, nan_policy: NanPolicy = 'zero') -> float

Maximum drawdown.

Parameters

returns : pandas.Series Periodic simple returns. nan_policy : {"drop", "zero", "propagate", "raise"}, default "zero" How missing returns are handled.

Returns

float Most negative drawdown.

Examples

import pandas as pd round(max_drawdown(pd.Series([0.10, -0.20, 0.05, -0.10])), 4) -0.244

omega

omega(returns: Series, threshold: float = 0.0, periods: int = 252, nan_policy: NanPolicy = 'drop') -> float

Omega gain/loss ratio.

Parameters

returns : pandas.Series Periodic simple returns. threshold : float, default 0.0 Annualized return threshold. periods : int, default 252 Periods per year. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Sum of gains divided by absolute sum of losses.

Examples

import pandas as pd round(omega(pd.Series([0.03, 0.01, -0.02, -0.01]), threshold=0.12, periods=12), 4) 0.4

sharpe

sharpe(returns: Series, periods: int, rf: float = 0.0, nan_policy: NanPolicy = 'drop') -> float

Annualized Sharpe ratio.

Parameters

returns : pandas.Series Periodic simple returns. periods : int Periods per year. rf : float, default 0.0 Annualized risk-free rate. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Annualized Sharpe ratio.

Examples

import pandas as pd round(sharpe(pd.Series([0.01, 0.02, -0.01, 0.0]), periods=252), 4) 6.1482

sortino

sortino(returns: Series, periods: int, rf: float = 0.0, required: float = 0.0, nan_policy: NanPolicy = 'drop') -> float

Annualized Sortino ratio.

Parameters

returns : pandas.Series Periodic simple returns. periods : int Periods per year. rf : float, default 0.0 Annualized risk-free rate. required : float, default 0.0 Per-period downside threshold. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Annualized Sortino ratio.

Examples

import pandas as pd round(sortino(pd.Series([0.02, -0.01, -0.03, 0.01]), periods=12), 4) -0.5477

tail_ratio

tail_ratio(returns: Series, cutoff: float = 0.05, nan_policy: NanPolicy = 'drop') -> float

Right-tail to left-tail ratio.

Parameters

returns : pandas.Series Periodic simple returns. cutoff : float, default 0.05 Tail percentile expressed as a fraction. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Absolute ratio of upper and lower percentiles.

Examples

import pandas as pd round(tail_ratio(pd.Series([-0.10, -0.04, -0.01, 0.02, 0.05, 0.09])), 4) 0.9412

var

var(returns: Series, cutoff: float = 0.05, nan_policy: NanPolicy = 'drop') -> float

Historical value at risk percentile.

Parameters

returns : pandas.Series Periodic simple returns. cutoff : float, default 0.05 Lower-tail percentile expressed as a fraction. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Historical lower-tail percentile.

Examples

import pandas as pd round(var(pd.Series([-0.10, -0.04, -0.01, 0.02, 0.05, 0.09])), 4) -0.085

volatility

volatility(returns: Series, periods: int, nan_policy: NanPolicy = 'drop') -> float

Annualized volatility.

Parameters

returns : pandas.Series Periodic simple returns. periods : int Periods per year. nan_policy : {"drop", "zero", "propagate", "raise"}, default "drop" How missing returns are handled.

Returns

float Sample standard deviation annualized by sqrt(periods).

Examples

import pandas as pd round(volatility(pd.Series([0.01, 0.02, -0.01, 0.0]), periods=252), 4) 0.2049

avg_loss

avg_loss(trades: Series | DataFrame) -> float

Compute average losing trade PnL.

Parameters

trades : pandas.Series or pandas.DataFrame Trade PnL values, or a frame containing a pnl column.

Returns

float Mean PnL for negative trades.

Examples

import pandas as pd avg_loss(pd.Series([100.0, -50.0, 0.0, -25.0])) -37.5

avg_win

avg_win(trades: Series | DataFrame) -> float

Compute average profitable trade PnL.

Parameters

trades : pandas.Series or pandas.DataFrame Trade PnL values, or a frame containing a pnl column.

Returns

float Mean PnL for positive trades.

Examples

import pandas as pd avg_win(pd.Series([100.0, -50.0, 0.0, 25.0])) 62.5

expectancy

expectancy(trades: Series | DataFrame) -> float

Compute expected PnL per trade.

Parameters

trades : pandas.Series or pandas.DataFrame Trade PnL values, or a frame containing a pnl column.

Returns

float win_rate * avg_win - loss_rate * abs(avg_loss).

Examples

import pandas as pd expectancy(pd.Series([100.0, -50.0, -25.0, 25.0])) 12.5

max_consecutive_losses

max_consecutive_losses(trades: Series | DataFrame) -> int

Compute the longest run of losing trades.

Parameters

trades : pandas.Series or pandas.DataFrame Trade PnL values, or a frame containing a pnl column.

Returns

int Longest consecutive negative-PnL streak.

Examples

import pandas as pd max_consecutive_losses(pd.Series([100.0, -25.0, -10.0, 50.0])) 2

max_consecutive_wins

max_consecutive_wins(trades: Series | DataFrame) -> int

Compute the longest run of profitable trades.

Parameters

trades : pandas.Series or pandas.DataFrame Trade PnL values, or a frame containing a pnl column.

Returns

int Longest consecutive positive-PnL streak.

Examples

import pandas as pd max_consecutive_wins(pd.Series([100.0, 25.0, -10.0, 50.0])) 2

profit_factor

profit_factor(trades: Series | DataFrame) -> float

Compute gross profit divided by absolute gross loss.

Parameters

trades : pandas.Series or pandas.DataFrame Trade PnL values, or a frame containing a pnl column.

Returns

float Sum of wins divided by the absolute sum of losses.

Examples

import pandas as pd round(profit_factor(pd.Series([100.0, -50.0, -25.0, 25.0])), 4) 1.6667

win_rate

win_rate(trades: Series | DataFrame) -> float

Compute the fraction of profitable trades.

Parameters

trades : pandas.Series or pandas.DataFrame Trade PnL values, or a frame containing a pnl column.

Returns

float Positive trade count divided by total trade count.

Examples

import pandas as pd win_rate(pd.Series([100.0, -50.0, 0.0, 25.0])) 0.5