Coverage for src/jquantstats/_plots/_portfolio/_nav.py: 100%
13 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"""Accumulated-NAV charts for a portfolio.
3Split out of the former single-module `_plots/_portfolio.py`; composed into
4:class:`PortfolioPlots` by `_core.py`.
5"""
7from __future__ import annotations
9from typing import TYPE_CHECKING, Literal, overload
11from .._render import render
12from .._specs import (
13 lagged_performance_spec,
14 portfolio_snapshot_spec,
15 smoothed_holdings_performance_spec,
16)
18if TYPE_CHECKING:
19 from matplotlib.figure import Figure as MplFigure
20 from plotly.graph_objects import Figure as PlotlyFigure
22 from .._backend import Backend
23 from .._protocol import PortfolioLike
24 from .._render import Figure
27class _NavPlotsMixin:
28 """Accumulated-NAV charts for :class:`PortfolioPlots`."""
30 __slots__ = ()
32 _portfolio: PortfolioLike
34 @overload
35 def snapshot(self, log_scale: bool = ..., *, backend: Literal["plotly"] | None = ...) -> PlotlyFigure: ...
37 @overload
38 def snapshot(self, log_scale: bool = ..., *, backend: Literal["matplotlib"]) -> MplFigure: ...
40 def snapshot(self, log_scale: bool = False, *, backend: Backend | None = None) -> Figure:
41 """Return a snapshot dashboard of NAV and drawdown.
43 When the portfolio has a non-zero ``cost_model.cost_per_unit``, an additional
44 ``"Net-of-Cost NAV"`` trace is overlaid on the NAV panel showing the
45 realised NAV path after deducting position-delta trading costs.
47 Args:
48 log_scale: If True, display NAV on a log scale. Defaults to False.
49 backend: Renderer to use. Defaults to the ambient selection.
51 Returns:
52 Figure: Accumulated NAV (including tilt/timing) over a shaded
53 drawdown panel.
55 """
56 return render(portfolio_snapshot_spec(self._portfolio, log_scale=log_scale), backend)
58 @overload
59 def lagged_performance_plot(
60 self,
61 lags: list[int] | None = ...,
62 log_scale: bool = ...,
63 *,
64 backend: Literal["plotly"] | None = ...,
65 ) -> PlotlyFigure: ...
67 @overload
68 def lagged_performance_plot(
69 self,
70 lags: list[int] | None = ...,
71 log_scale: bool = ...,
72 *,
73 backend: Literal["matplotlib"],
74 ) -> MplFigure: ...
76 def lagged_performance_plot(
77 self,
78 lags: list[int] | None = None,
79 log_scale: bool = False,
80 *,
81 backend: Backend | None = None,
82 ) -> Figure:
83 """Plot NAV_accumulated for multiple lagged portfolios.
85 Creates a figure with one line per lag value showing the accumulated
86 NAV series for the portfolio with cash positions shifted by that lag.
87 By default, lags [0, 1, 2, 3, 4] are used.
89 Args:
90 lags: A list of integer lags to apply; defaults to [0, 1, 2, 3, 4].
91 log_scale: If True, set the primary y-axis to logarithmic scale.
92 backend: Renderer to use. Defaults to the ambient selection.
94 Returns:
95 Figure: One trace per requested lag.
97 Raises:
98 TypeError: If ``lags`` is not a list of integers.
100 """
101 return render(lagged_performance_spec(self._portfolio, lags, log_scale), backend)
103 @overload
104 def smoothed_holdings_performance_plot(
105 self,
106 windows: list[int] | None = ...,
107 log_scale: bool = ...,
108 *,
109 backend: Literal["plotly"] | None = ...,
110 ) -> PlotlyFigure: ...
112 @overload
113 def smoothed_holdings_performance_plot(
114 self,
115 windows: list[int] | None = ...,
116 log_scale: bool = ...,
117 *,
118 backend: Literal["matplotlib"],
119 ) -> MplFigure: ...
121 def smoothed_holdings_performance_plot(
122 self,
123 windows: list[int] | None = None,
124 log_scale: bool = False,
125 *,
126 backend: Backend | None = None,
127 ) -> Figure:
128 """Plot NAV_accumulated for smoothed-holding portfolios.
130 Builds portfolios with cash positions smoothed by a trailing rolling
131 mean over the previous ``n`` steps (window size n+1) for n in
132 ``windows`` (defaults to [0, 1, 2, 3, 4]) and plots their
133 accumulated NAV curves.
135 Args:
136 windows: List of non-negative integers specifying smoothing steps
137 to include; defaults to [0, 1, 2, 3, 4].
138 log_scale: If True, set the primary y-axis to logarithmic scale.
139 backend: Renderer to use. Defaults to the ambient selection.
141 Returns:
142 Figure: One line per requested smoothing level.
144 Raises:
145 TypeError: If ``windows`` is not a list of non-negative integers.
147 """
148 return render(smoothed_holdings_performance_spec(self._portfolio, windows, log_scale), backend)