Skip to content

Add ex-ante tracking error to Portfolio#89

Open
gyx09212214-prog wants to merge 2 commits into
mbk-dev:masterfrom
gyx09212214-prog:add-ex-ante-tracking-error
Open

Add ex-ante tracking error to Portfolio#89
gyx09212214-prog wants to merge 2 commits into
mbk-dev:masterfrom
gyx09212214-prog:add-ex-ante-tracking-error

Conversation

@gyx09212214-prog

@gyx09212214-prog gyx09212214-prog commented Jun 9, 2026

Copy link
Copy Markdown

Summary

  • add Portfolio.get_ex_ante_tracking_error(benchmark) for annualized ex-ante Tracking Error
  • estimate annualized sample covariance from overlapping monthly asset returns and planned active weights
  • validate benchmark asset universe and base currency, with regression coverage for reordered benchmark assets

Closes #88

Tests

  • .\.venv\Scripts\python -m pytest tests\portfolio\test_portfolio.py -q
  • $env:RUFF_CACHE_DIR = $env:TEMP\okama-ruff-cache; .\.venv\Scripts\python -m ruff check .
  • $env:JOBLIB_MULTIPROCESSING='0'; .\.venv\Scripts\python -m pytest -q -n 0358 passed, 3 skipped

Summary by Sourcery

Add support for computing annualized ex-ante tracking error for portfolios relative to a benchmark with validation of compatibility.

New Features:

  • Introduce Portfolio.get_ex_ante_tracking_error to compute annualized ex-ante tracking error against a benchmark portfolio based on active weights and historical covariance.

Tests:

  • Add unit tests covering ex-ante tracking error calculation, covariance scaling, and validation of benchmark asset universe compatibility.

@sourcery-ai

sourcery-ai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds an ex-ante tracking error API to Portfolio that validates benchmark compatibility, computes annualized tracking error from active weights and overlapping monthly asset returns, and introduces regression tests to lock in behavior and input validation.

File-Level Changes

Change Details Files
Add ex-ante tracking error computation on Portfolio using active weights and annualized covariance of overlapping monthly asset returns.
  • Introduce Portfolio.get_ex_ante_tracking_error(benchmark) method with docstring describing formula, assumptions, and return value.
  • Validate that the benchmark is a Portfolio, shares the same asset universe (by symbols set), and uses the same base currency as the portfolio.
  • Align historical data by intersecting monthly return indices and enforce a minimum of two overlapping observations before computation.
  • Compute active weights from portfolio and benchmark weights (reindexed to portfolio symbols), estimate annualized covariance from asset returns, and derive tracking error as the square root of the active-weight portfolio variance with numerical safety for small negatives.
okama/portfolios/core.py
Add regression tests for ex-ante tracking error calculation and benchmark validation.
  • Test that ex-ante tracking error matches the analytical value derived from active weights and the annualized covariance matrix and is invariant to benchmark asset order.
  • Test that calling ex-ante tracking error with a benchmark that does not share the same asset universe raises a ValueError with the expected message.
tests/portfolio/test_portfolio.py

Assessment against linked issues

Issue Objective Addressed Explanation
#88 Add a Portfolio method to compute annualized ex-ante tracking error using planned active weights and the annualized sample covariance matrix of historical monthly asset returns, per TE = sqrt((a - b)' Σ (a - b)).
#88 Ensure the ex-ante tracking error method uses a benchmark expressed as portfolio weights over the same asset universe (and compatible data), rather than just benchmark returns.
#88 Document in the method’s docstring that ex-ante tracking error can systematically underestimate ex-post tracking error because realized portfolio weights drift between rebalancings, referencing Hwang & Satchell (2001).

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In test_ex_ante_tracking_error_uses_annualized_active_weight_covariance, use the same annualization constant as the implementation (e.g., settings._MONTHS_PER_YEAR instead of hardcoding 12) so the test doesn’t drift if the configured period changes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `test_ex_ante_tracking_error_uses_annualized_active_weight_covariance`, use the same annualization constant as the implementation (e.g., `settings._MONTHS_PER_YEAR` instead of hardcoding `12`) so the test doesn’t drift if the configured period changes.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@gyx09212214-prog

Copy link
Copy Markdown
Author

Reviewed Sourcery feedback.

The current PR head already uses settings._MONTHS_PER_YEAR in test_ex_ante_tracking_error_uses_annualized_active_weight_covariance, matching the implementation. No code change was needed.

Validation:

  • python -m py_compile okama/portfolios/core.py tests/portfolio/test_portfolio.py
  • python -m pytest tests/portfolio/test_portfolio.py::test_ex_ante_tracking_error_uses_annualized_active_weight_covariance tests/portfolio/test_portfolio.py::test_ex_ante_tracking_error_requires_same_asset_universe -q (2 passed)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add ex-ante Tracking Error method to Portfolio

1 participant