feat(portfolio): add deduct_management_fee for flat annual fee deduction - #901
Merged
Merged
Conversation
Copilot
AI
changed the title
[WIP] Add management fee deduction utility
feat(portfolio): add deduct_management_fee for flat annual fee deduction
Jul 29, 2026
tschm
marked this pull request as ready for review
July 29, 2026 12:24
Replace the ambiguous en dash and arrow in a comment with ASCII (RUF003) and let ruff format normalise the inline weekday comments. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/jquantstats/_portfolio_cost.py:213
deduct_management_feeaccepts an arbitrarybaseframe but doesn't validate it has a'returns'column and builds the undateddays_elapsedvia a Python list sized frombase.height. This can fail with confusing errors (e.g., ColumnNotFound for missing'returns') and will produce a length mismatch whenbase.height == 0(creating a 1-element Series for a 0-row frame). Adding lightweight validation and generating the undateddays_elapsedwithpl.arange(...).clip(...)avoids both issues and keeps the operation in Polars.
if base is None:
base = self.returns
if "date" in base.columns and base["date"].dtype.is_temporal():
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
Portfolio.deduct_management_feeto subtract a flat annual management fee from a returns series, accruing pro-rata per calendar day (annual_fee × days_elapsed / 365). Weekends and holidays are charged to the next trading day; the first row always accrues nothing.Changes
exceptions.py— newNegativeAnnualFeeError(mirrorsNegativeCostBpsError)_portfolio_base.py— addsannual_fee: floatto_PortfolioMembersTYPE_CHECKING stubsportfolio.py— addsannual_fee: float = 0.0dataclass field; updates cost-model docstring section; updatesfrom_cash_positionto accept and forwardannual_fee_portfolio_constructors.py—from_positionandfrom_risk_positionaccept and forwardannual_fee_portfolio_cost.py— implementsdeduct_management_fee(annual_fee, base):datecolumn is present; falls back to 1 day/period otherwisebasedefaults toself.returns; accepts any same-schema DataFrame so it composes withcost_adjusted_returnstest_costs.py— 16 new tests (zero-fee identity, per-period analytical values, full-year sum, weekend accumulation, composition, validation errors, factory forwarding)Testing
make testpasses locallymake fmthas been runChecklist
CHANGELOG.mdentry added (or not needed for this change)make deptrypasses (no unused or missing dependencies)