Coverage for src/jquantstats/_stats/_stats.py: 100%

34 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-23 06:13 +0000

1"""Statistical analysis tools for financial returns data. 

2 

3This module provides the `Stats` dataclass, which is the public-facing 

4class that combines five mixin classes: 

5 

6- `_BasicStatsMixin` — basic statistics, 

7 volatility, win/loss metrics, and risk metrics (VaR, Sharpe inputs, Kelly). 

8- `_RiskStatsMixin` — Sharpe, 

9 Sortino, benchmark/factor analytics (R², alpha, beta). 

10- `_DrawdownMixin` — cumulative returns, drawdown series, max drawdown, and 

11 per-episode drawdown details. 

12- `_ReportingStatsMixin` — temporal 

13 reporting, Calmar, recovery factor, capture ratios, annual breakdown, and 

14 summary. 

15- `_PeriodicReportingMixin` — period-bucketed tables: monthly-returns pivot, 

16 distribution across calendar frequencies, benchmark comparison, worst-N periods. 

17- `_RollingStatsMixin` — rolling-window 

18 time-series metrics (rolling Sharpe, Sortino, and volatility). 

19- `_MonteCarloStatsMixin` — block-bootstrap Monte Carlo simulation distributions 

20 for total return, Sharpe, max drawdown, and CAGR. 

21 

22Module-level helpers and the ``columnwise_stat`` / ``to_frame`` decorators are 

23defined in `jquantstats._stats._core` and re-exported here for backwards 

24compatibility. 

25""" 

26 

27from __future__ import annotations 

28 

29from typing import TYPE_CHECKING 

30 

31import polars as pl 

32 

33from ._basic import _BasicStatsMixin 

34from ._core import ( 

35 _drawdown_series, 

36 _mean, 

37 _to_float, 

38 columnwise_stat, 

39 to_frame, 

40) 

41from ._drawdown import _DrawdownMixin 

42from ._internals import ( 

43 _annualization_factor, 

44 _comp_return, 

45 _downside_deviation, 

46 _nav_series, 

47) 

48from ._montecarlo import _MonteCarloStatsMixin 

49from ._performance import _RiskStatsMixin 

50from ._periodic import _PeriodicReportingMixin 

51from ._reporting import _ReportingStatsMixin 

52from ._rolling import _RollingStatsMixin 

53 

54if TYPE_CHECKING: 

55 from ..data import Data 

56 

57__all__ = [ 

58 "Stats", 

59 "_annualization_factor", 

60 "_comp_return", 

61 "_downside_deviation", 

62 "_drawdown_series", 

63 "_mean", 

64 "_nav_series", 

65 "_to_float", 

66 "columnwise_stat", 

67 "to_frame", 

68] 

69 

70 

71class Stats( 

72 _BasicStatsMixin, 

73 _RiskStatsMixin, 

74 _DrawdownMixin, 

75 _ReportingStatsMixin, 

76 _PeriodicReportingMixin, 

77 _RollingStatsMixin, 

78 _MonteCarloStatsMixin, 

79): 

80 """Statistical analysis tools for financial returns data. 

81 

82 Provides a comprehensive set of methods for calculating various financial 

83 metrics and statistics on returns data, including: 

84 

85 - Basic statistics (mean, skew, kurtosis) 

86 - Risk metrics (volatility, value-at-risk, drawdown) 

87 - Performance ratios (Sharpe, Sortino, information ratio) 

88 - Win/loss metrics (win rate, profit factor, payoff ratio) 

89 - Rolling calculations (rolling volatility, rolling Sharpe) 

90 - Factor analysis (alpha, beta, R-squared) 

91 - Concentration metrics (``hhi_positive``, ``hhi_negative``) — optional 

92 Herfindahl-Hirschman Index diagnostics that quantify how concentrated 

93 gains and losses are across time periods. These are public API but are 

94 not included in ``summary()`` by default. 

95 

96 Metrics are organised into focused modules: 

97 

98 - `_BasicStatsMixin` 

99 - `_RiskStatsMixin` 

100 - `_DrawdownMixin` 

101 - `_ReportingStatsMixin` 

102 - `_PeriodicReportingMixin` 

103 - `_RollingStatsMixin` 

104 - `_MonteCarloStatsMixin` 

105 

106 Attributes: 

107 all: A DataFrame combining all data (index, returns, benchmark) for 

108 easy column selection. 

109 """ 

110 

111 def __init__(self, data: Data) -> None: 

112 self._data = data 

113 self.all: pl.DataFrame = data.all 

114 

115 def __repr__(self) -> str: 

116 """Return a string representation of the Stats object.""" 

117 return f"Stats(assets={self._data.assets})" 

118 

119 @property 

120 def assets(self) -> list[str]: 

121 """Asset column names (excludes benchmark and date).""" 

122 return self._data.assets 

123 

124 @property 

125 def returns(self) -> pl.DataFrame: 

126 """Returns DataFrame (asset columns only, no benchmark).""" 

127 return self._data.returns 

128 

129 @property 

130 def benchmark(self) -> pl.DataFrame | None: 

131 """Benchmark DataFrame, or None when no benchmark was provided.""" 

132 return self._data.benchmark 

133 

134 @property 

135 def date_col(self) -> list[str]: 

136 """Date column name(s) present in the index, or empty list.""" 

137 return self._data.date_col 

138 

139 @property 

140 def index(self) -> pl.DataFrame: 

141 """Index DataFrame (date or integer range).""" 

142 return self._data.index