Coverage for src/jquantstats/_plots/_portfolio/_rolling.py: 100%

13 statements  

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

1"""Rolling-window and per-year risk charts for a portfolio. 

2 

3Split out of the former single-module `_plots/_portfolio.py`; composed into 

4:class:`PortfolioPlots` by `_core.py`. 

5""" 

6 

7from __future__ import annotations 

8 

9from typing import TYPE_CHECKING, Literal, overload 

10 

11from .._render import render 

12from .._specs import ( 

13 annual_sharpe_spec, 

14 portfolio_rolling_sharpe_spec, 

15 portfolio_rolling_volatility_spec, 

16) 

17 

18if TYPE_CHECKING: 

19 from matplotlib.figure import Figure as MplFigure 

20 from plotly.graph_objects import Figure as PlotlyFigure 

21 

22 from .._backend import Backend 

23 from .._protocol import PortfolioLike 

24 from .._render import Figure 

25 

26 

27class _RollingPortfolioPlotsMixin: 

28 """Rolling-window and annual risk charts for :class:`PortfolioPlots`.""" 

29 

30 __slots__ = () 

31 

32 _portfolio: PortfolioLike 

33 

34 @overload 

35 def rolling_sharpe_plot(self, window: int = ..., *, backend: Literal["plotly"] | None = ...) -> PlotlyFigure: ... 

36 

37 @overload 

38 def rolling_sharpe_plot(self, window: int = ..., *, backend: Literal["matplotlib"]) -> MplFigure: ... 

39 

40 def rolling_sharpe_plot(self, window: int = 63, *, backend: Backend | None = None) -> Figure: 

41 """Plot rolling annualised Sharpe ratio over time. 

42 

43 Computes the rolling Sharpe for each asset column using the given 

44 window and renders one line per asset. 

45 

46 Args: 

47 window: Rolling-window size in periods. Defaults to 63. 

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

49 

50 Returns: 

51 Figure: A chart with one line per asset. 

52 

53 Raises: 

54 ValueError: If ``window`` is not a positive integer. 

55 

56 """ 

57 return render(portfolio_rolling_sharpe_spec(self._portfolio, window), backend) 

58 

59 @overload 

60 def rolling_volatility_plot( 

61 self, window: int = ..., *, backend: Literal["plotly"] | None = ... 

62 ) -> PlotlyFigure: ... 

63 

64 @overload 

65 def rolling_volatility_plot(self, window: int = ..., *, backend: Literal["matplotlib"]) -> MplFigure: ... 

66 

67 def rolling_volatility_plot(self, window: int = 63, *, backend: Backend | None = None) -> Figure: 

68 """Plot rolling annualised volatility over time. 

69 

70 Computes the rolling volatility for each asset column using the given 

71 window and renders one line per asset. 

72 

73 Args: 

74 window: Rolling-window size in periods. Defaults to 63. 

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

76 

77 Returns: 

78 Figure: A chart with one line per asset. 

79 

80 Raises: 

81 ValueError: If ``window`` is not a positive integer. 

82 

83 """ 

84 return render(portfolio_rolling_volatility_spec(self._portfolio, window), backend) 

85 

86 @overload 

87 def annual_sharpe_plot(self, *, backend: Literal["plotly"] | None = ...) -> PlotlyFigure: ... 

88 

89 @overload 

90 def annual_sharpe_plot(self, *, backend: Literal["matplotlib"]) -> MplFigure: ... 

91 

92 def annual_sharpe_plot(self, *, backend: Backend | None = None) -> Figure: 

93 """Plot annualised Sharpe ratio broken down by calendar year. 

94 

95 Computes the Sharpe ratio for each calendar year from the portfolio 

96 returns and renders a grouped bar chart with one bar per year per 

97 asset. 

98 

99 Args: 

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

101 

102 Returns: 

103 Figure: A grouped bar chart, one bar group per asset. 

104 

105 """ 

106 return render(annual_sharpe_spec(self._portfolio), backend)