Coverage for src/jquantstats/_portfolio_base.py: 100%
4 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-23 06:13 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-23 06:13 +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
38 # Derived series / accessors defined on sibling mixins or ``Portfolio``.
39 @property
40 def data(self) -> Data:
41 """Bridge to the legacy `Data` object (defined on `Portfolio`)."""
43 @property
44 def assets(self) -> list[str]:
45 """Asset column names (defined on `Portfolio`)."""
47 @property
48 def returns(self) -> pl.DataFrame:
49 """Daily returns (defined on `PortfolioNavMixin`)."""
51 @property
52 def profit(self) -> pl.DataFrame:
53 """Aggregate daily portfolio profit (defined on `PortfolioNavMixin`)."""
55 @property
56 def nav_accumulated(self) -> pl.DataFrame:
57 """Cumulative additive NAV (defined on `PortfolioNavMixin`)."""
59 @property
60 def turnover(self) -> pl.DataFrame:
61 """Turnover frame (defined on `PortfolioTurnoverMixin`)."""