Coverage for src/jquantstats/_plots/_data/_distribution.py: 100%

11 statements  

« prev     ^ index     » next       coverage.py v7.16.1, created at 2026-09-23 04:11 +0000

1"""Return-distribution charts (overlaid histograms and by-period box plots).""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING, Literal, overload 

6 

7from .._render import render 

8from .._specs import distribution_spec, histogram_spec 

9 

10if TYPE_CHECKING: 

11 from matplotlib.figure import Figure as MplFigure 

12 from plotly.graph_objects import Figure as PlotlyFigure 

13 

14 from jquantstats._protocol import DataLike 

15 

16 from .._backend import Backend 

17 from .._render import Figure 

18 

19 

20class _DistributionPlotsMixin: 

21 """Return-distribution plots for :class:`DataPlots`.""" 

22 

23 __slots__ = () 

24 

25 _data: DataLike 

26 

27 @overload 

28 def histogram( 

29 self, title: str = ..., bins: int = ..., *, backend: Literal["plotly"] | None = ... 

30 ) -> PlotlyFigure: ... 

31 

32 @overload 

33 def histogram(self, title: str = ..., bins: int = ..., *, backend: Literal["matplotlib"]) -> MplFigure: ... 

34 

35 def histogram( 

36 self, 

37 title: str = "Returns Distribution", 

38 bins: int = 50, 

39 *, 

40 backend: Backend | None = None, 

41 ) -> Figure: 

42 """Overlaid return histograms, one per series. 

43 

44 Each asset (and the benchmark, when present) is drawn as a 

45 semi-transparent histogram on shared axes, so the distributions can be 

46 compared directly — a fat-tailed asset against a tightly peaked 

47 benchmark, for instance. 

48 

49 Args: 

50 title: Chart title. Defaults to ``"Returns Distribution"``. 

51 bins: Number of histogram bins. Defaults to 50. 

52 backend: Renderer to use. Defaults to the ambient selection. 

53 

54 Returns: 

55 Figure: A histogram figure. 

56 

57 """ 

58 return render(histogram_spec(self._data, title=title, bins=bins), backend) 

59 

60 @overload 

61 def distribution( 

62 self, title: str = ..., compounded: bool = ..., *, backend: Literal["plotly"] | None = ... 

63 ) -> PlotlyFigure: ... 

64 

65 @overload 

66 def distribution( 

67 self, title: str = ..., compounded: bool = ..., *, backend: Literal["matplotlib"] 

68 ) -> MplFigure: ... 

69 

70 def distribution( 

71 self, 

72 title: str = "Return Distribution by Period", 

73 compounded: bool = True, 

74 *, 

75 backend: Backend | None = None, 

76 ) -> Figure: 

77 """Return distributions across daily, weekly, monthly, quarterly and yearly periods. 

78 

79 Renders a box plot for each aggregation period so the user can compare 

80 how the distribution widens as the holding period lengthens. One 

81 subplot column is produced per asset. 

82 

83 Args: 

84 title: Chart title. Defaults to ``"Return Distribution by Period"``. 

85 compounded: Compound returns within each period. Defaults to True. 

86 backend: Renderer to use. Defaults to the ambient selection. 

87 

88 Returns: 

89 Figure: A figure with one panel per asset. 

90 

91 """ 

92 return render(distribution_spec(self._data, title=title, compounded=compounded), backend)