quantlab.runs.backtest_stats.win_rates#

quantlab.runs.backtest_stats.win_rates(returns, rebalances, *, ranges, benchmark_returns=None)[source]#

Return the share of holding periods and of months the strategy won, in percent.

A holding period runs from the fill bar of one decided rebalance (the bar after it) up to the bar before the next one’s, whether or not its orders filled; a delisting settlement or a held bar starts none, and the bars before the first fill bar hold nothing and are left out. A month is a calendar month of the bar labels. Each period’s per-bar returns inside ranges are compounded; the strategy wins a period when its return beats the benchmark’s, or, without a benchmark, when it is positive. A bar where either return is NaN, or at or below -100% (a value that reached zero, whose log return does not exist), is left out, and a slice with no period gives NaN.

Parameters:
returnsxarray.DataArray

The strategy’s per-bar returns on a timestamp axis.

rebalancesarray_like of datetime64

The bars of the decided rebalances (the rebalance record’s decided bars); each starts a period on the bar after it.

rangessequence of (str, str)

Inclusive bar-label ranges of the slice; bars outside them are left out.

benchmark_returnsxarray.DataArray, optional

The benchmark’s per-bar returns on the same bars. Without it a period is won when its return is positive.

Returns:
dict

Rebalance Win Rate [%] and Monthly Win Rate [%], with `` vs Benchmark`` before `` [%]`` when benchmark_returns is given.

Examples

Decided on bars 0 and 2, so the periods are bars 1 to 2 (lost) and bars 3 to 4 (won):

>>> bars = pd.bdate_range("2024-01-01", periods=5)
>>> returns = xr.DataArray([0.0, 0.01, -0.02, 0.01, 0.01], dims="timestamp", coords={"timestamp": bars})
>>> win_rates(returns, bars[[0, 2]].values, ranges=[("2024-01-01", "2024-01-05")])
{'Rebalance Win Rate [%]': 50.0, 'Monthly Win Rate [%]': 100.0}