Coverage for src/jquantstats/_reports/_protocol.py: 100%
5 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-23 04:11 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-23 04:11 +0000
1"""Protocols describing the minimal interfaces required by the _reports subpackage."""
3from __future__ import annotations
5from typing import TYPE_CHECKING, Protocol, runtime_checkable
7import polars as pl
9from jquantstats._protocol import DataLike, StatsLike
11if TYPE_CHECKING:
12 import plotly.graph_objects as go
14__all__ = ["DataLike", "PlotsLike", "PortfolioLike", "StatsLike"]
17@runtime_checkable
18class PlotsLike(Protocol): # pragma: no cover
19 """Structural interface for the portfolio plots facade used by `Report`."""
21 def snapshot(self) -> go.Figure:
22 """NAV + drawdown snapshot figure."""
23 ...
25 def rolling_sharpe_plot(self) -> go.Figure:
26 """Rolling Sharpe figure."""
27 ...
29 def rolling_volatility_plot(self) -> go.Figure:
30 """Rolling volatility figure."""
31 ...
33 def annual_sharpe_plot(self) -> go.Figure:
34 """Annual Sharpe figure."""
35 ...
37 def monthly_returns_heatmap(self) -> go.Figure:
38 """Monthly returns heatmap figure."""
39 ...
41 def correlation_heatmap(self) -> go.Figure:
42 """Correlation heatmap figure."""
43 ...
45 def lead_lag_ir_plot(self) -> go.Figure:
46 """Lead/lag IR figure."""
47 ...
49 def trading_cost_impact_plot(self) -> go.Figure:
50 """Trading cost impact figure."""
51 ...
54@runtime_checkable
55class PortfolioLike(Protocol): # pragma: no cover
56 """Structural interface required by the `Report` class.
58 Any object satisfying this protocol can be passed as ``portfolio`` without a
59 concrete dependency on `Portfolio`.
60 """
62 @property
63 def prices(self) -> pl.DataFrame:
64 """Price (holding) DataFrame."""
65 ...
67 @property
68 def aum(self) -> float:
69 """Assets under management."""
70 ...
72 @property
73 def assets(self) -> list[str]:
74 """Asset names."""
75 ...
77 @property
78 def plots(self) -> PlotsLike:
79 """Portfolio plots facade."""
80 ...
82 @property
83 def stats(self) -> StatsLike:
84 """Statistics facade."""
85 ...
87 def turnover_summary(self) -> pl.DataFrame:
88 """Turnover summary DataFrame."""
89 ...