Coverage for src/jquantstats/_reports/_protocol.py: 100%

6 statements  

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

1"""Protocols describing the minimal interfaces required by the _reports subpackage.""" 

2 

3from __future__ import annotations 

4 

5from typing import Protocol, runtime_checkable 

6 

7import plotly.graph_objects as go 

8import polars as pl 

9 

10from jquantstats._protocol import DataLike, StatsLike 

11 

12__all__ = ["DataLike", "PlotsLike", "PortfolioLike", "StatsLike"] 

13 

14 

15@runtime_checkable 

16class PlotsLike(Protocol): # pragma: no cover 

17 """Structural interface for the portfolio plots facade used by `Report`.""" 

18 

19 def snapshot(self) -> go.Figure: 

20 """NAV + drawdown snapshot figure.""" 

21 ... 

22 

23 def rolling_sharpe_plot(self) -> go.Figure: 

24 """Rolling Sharpe figure.""" 

25 ... 

26 

27 def rolling_volatility_plot(self) -> go.Figure: 

28 """Rolling volatility figure.""" 

29 ... 

30 

31 def annual_sharpe_plot(self) -> go.Figure: 

32 """Annual Sharpe figure.""" 

33 ... 

34 

35 def monthly_returns_heatmap(self) -> go.Figure: 

36 """Monthly returns heatmap figure.""" 

37 ... 

38 

39 def correlation_heatmap(self) -> go.Figure: 

40 """Correlation heatmap figure.""" 

41 ... 

42 

43 def lead_lag_ir_plot(self) -> go.Figure: 

44 """Lead/lag IR figure.""" 

45 ... 

46 

47 def trading_cost_impact_plot(self) -> go.Figure: 

48 """Trading cost impact figure.""" 

49 ... 

50 

51 

52@runtime_checkable 

53class PortfolioLike(Protocol): # pragma: no cover 

54 """Structural interface required by the `Report` class. 

55 

56 Any object satisfying this protocol can be passed as ``portfolio`` without a 

57 concrete dependency on `Portfolio`. 

58 """ 

59 

60 @property 

61 def prices(self) -> pl.DataFrame: 

62 """Price (holding) DataFrame.""" 

63 ... 

64 

65 @property 

66 def aum(self) -> float: 

67 """Assets under management.""" 

68 ... 

69 

70 @property 

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

72 """Asset names.""" 

73 ... 

74 

75 @property 

76 def plots(self) -> PlotsLike: 

77 """Portfolio plots facade.""" 

78 ... 

79 

80 @property 

81 def stats(self) -> StatsLike: 

82 """Statistics facade.""" 

83 ... 

84 

85 def turnover_summary(self) -> pl.DataFrame: 

86 """Turnover summary DataFrame.""" 

87 ...