Coverage for src/jquantstats/_portfolio_base.py: 100%
4 statements
« prev ^ index » next coverage.py v7.17.1, created at 2026-11-03 15:52 +0000
« prev ^ index » next coverage.py v7.17.1, created at 2026-11-03 15:52 +0000
1"""Shared type-only declarations for the Portfolio mixins.
3The four Portfolio mixins (`PortfolioNavMixin`, `PortfolioAttributionMixin`,
4`PortfolioTurnoverMixin`, `PortfolioCostMixin`) each consume attributes and
5properties that are actually defined on *sibling* mixins or on the composed
6`Portfolio` dataclass itself. So that every mixin type-checks in isolation under
7``mypy --strict``, they all inherit this base, which declares that shared
8surface once under ``TYPE_CHECKING``.
10At runtime the body is skipped entirely, so `_PortfolioMembers` is an empty
11class: it adds nothing to instance layout (the mixins are slot-free already) and
12nothing to behaviour — it exists purely to give the type checker a single source
13of truth for the cross-mixin surface instead of repeating the stubs in every
14mixin module.
15"""
17from __future__ import annotations
19from typing import TYPE_CHECKING
21import polars as pl
23if TYPE_CHECKING:
24 from .data import Data
27class _PortfolioMembers:
28 """Type-only declaration of the cross-mixin Portfolio surface (see module docstring)."""
30 if TYPE_CHECKING:
31 # Raw inputs — real ``Portfolio`` dataclass fields.
32 cashposition: pl.DataFrame
33 prices: pl.DataFrame
34 aum: float
35 cost_per_unit: float
36 cost_bps: float
37 annual_fee: float
38 compounding: bool
39 realized_costs: pl.DataFrame | None
41 # Derived series / accessors defined on sibling mixins or ``Portfolio``.
42 @property
43 def data(self) -> Data:
44 """Bridge to the legacy `Data` object (defined on `Portfolio`)."""
46 @property
47 def assets(self) -> list[str]:
48 """Asset column names (defined on `Portfolio`)."""
50 @property
51 def returns(self) -> pl.DataFrame:
52 """Daily returns (defined on `PortfolioNavMixin`)."""
54 @property
55 def profit(self) -> pl.DataFrame:
56 """Aggregate daily portfolio profit (defined on `PortfolioNavMixin`)."""
58 @property
59 def nav_accumulated(self) -> pl.DataFrame:
60 """Cumulative additive NAV (defined on `PortfolioNavMixin`)."""
62 @property
63 def _return_base(self) -> pl.Series:
64 """Per-row capital that returns are measured against (defined on `PortfolioNavMixin`)."""
66 @property
67 def units(self) -> pl.DataFrame:
68 """Units held per asset (defined on `PortfolioUnitsMixin`)."""
70 @property
71 def turnover(self) -> pl.DataFrame:
72 """Turnover frame (defined on `PortfolioTurnoverMixin`)."""