quantlab.runs.backtest_stats.return_stats#
- quantlab.runs.backtest_stats.return_stats(returns, *, bar_interval, year_freq, ranges=None)[source]#
Return the return statistics of a per-bar return series, keyed by row name.
These are the rows of the
in_sample,out_of_sampleandbenchmarkblocks ofmetrics.json, equal to the bit to vectorbt’sReturnsAccessor.statswithfreq=bar_intervalandyear_freq.annbelow isyear_freq / bar_interval, the bars per year, and a NaN return is skipped by every row exceptPeriodand the annualization exponent, which count every bar.Start,End: the first and last bar label (pd.Timestamp);Period: the number of bars timesbar_interval.Total Return [%]: compounded return;Annualized Return [%]:(1 + total) ** (ann / bars) - 1;Annualized Volatility [%]: standard deviation (ddof 1) timessqrt(ann).Max Drawdown [%]: the deepest drawdown of the compounded curve, a positive percentage, NaN without any drawdown;Max Drawdown Duration: the longest one in bars timesbar_interval(NaTwithout any).Sharpe Ratio(mean over standard deviation timessqrt(ann)),Calmar Ratio,Omega RatioandSortino Ratiowith a zero risk-free rate and required return;infwhen the denominator is 0.SkewandKurtosis(pandas, bias-corrected),Tail Ratio(95th over 5th percentile, absolute),Common Sense Ratio(tail ratio times one plus the annualized return) andValue at Risk(the 5th percentile return, a fraction).
- Parameters:
- returnsxarray.DataArray
Per-bar returns on a sorted
timestampaxis.- bar_interval
The bar spacing, anything
pd.Timedeltaaccepts.- year_freqpd.Timedelta
One year, as
year_freqreturns it.- rangessequence of (str, str), optional
Inclusive bar-label ranges to cut the series to, concatenated in order; the whole series when omitted.
- Returns:
- dict
Seventeen rows, in the order listed above.
- Raises:
- ValueError
If no return falls inside
ranges.
Examples
>>> returns = xr.DataArray( ... [0.01, -0.02, 0.015, 0.005], dims=("timestamp",), ... coords={"timestamp": pd.bdate_range("2024-01-01", periods=4)}, ... ) >>> stats = return_stats( ... returns, bar_interval="1D", year_freq=year_freq("1D", 252, 390) ... ) >>> round(stats["Total Return [%]"], 6), stats["Period"] (0.967023, Timedelta('4 days 00:00:00')) >>> round(stats["Max Drawdown [%]"], 6), stats["Max Drawdown Duration"] (2.0, Timedelta('3 days 00:00:00')) >>> sliced = return_stats( ... returns, bar_interval="1D", year_freq=year_freq("1D", 252, 390), ... ranges=[("2024-01-02", "2024-01-03")], ... ) >>> round(sliced["Total Return [%]"], 6), sliced["Period"] (-0.53, Timedelta('2 days 00:00:00'))