Skip to content

Add assume_PSD=True to ex_ante_tracking_error's quad_form - #757

Open
shlokkvaishnav wants to merge 1 commit into
PyPortfolio:mainfrom
shlokkvaishnav:fix/ex-ante-tracking-error-assume-psd
Open

Add assume_PSD=True to ex_ante_tracking_error's quad_form#757
shlokkvaishnav wants to merge 1 commit into
PyPortfolio:mainfrom
shlokkvaishnav:fix/ex-ante-tracking-error-assume-psd

Conversation

@shlokkvaishnav

Copy link
Copy Markdown

What this fixes

objective_functions.py has four cp.quad_form(...) call sites over a covariance matrix. Three of them (portfolio_variance, sharpe_ratio, quadratic_utility) pass assume_PSD=True, which skips cvxpy's own numerical PSD-certification check on the matrix — the right call, since cov_matrix is PSD by construction even when it's numerically ill-conditioned (small sample size relative to number of assets, near-duplicate assets, etc.).

ex_ante_tracking_error was the one outlier missing it, despite taking the same kind of cov_matrix argument used the same way. This is the exact failure class reported in #631 (cvxpy note: ... trying to certify that a matrix is positive semi-definite ... replace the matrix A by cvxpy.psd_wrap(A)), for a user's own quad_form-based objective modeled on this codebase's pattern.

Honesty about verification

I was not able to force this exact PSD-certification error against the current cvxpy (1.9.2) with any covariance matrix I constructed (including exactly-singular, ill-conditioned, and rank-deficient ones) — cvxpy appears to have become more lenient about this over time. So this isn't a "fails on main, passes with fix" reproduction; it's a defensive consistency fix that matches the established pattern used by the sibling objective functions in this same file, and directly addresses the failure mode described in #631.

Test log

$ pytest tests/test_objective_functions.py -v
...
12 passed in 6.30s

$ pytest tests/test_efficient_frontier.py -q
75 passed, 6 warnings in 39.46s

$ black --check pypfopt/objective_functions.py tests/test_objective_functions.py
All done! ✨ 🍰 ✨
2 files would be left unchanged.

Added test_ex_ante_tracking_error_assumes_psd confirming the numeric output is unchanged for a well-conditioned matrix (i.e. the fix is behavior-preserving in the normal case), alongside the existing test_ex_ante_tracking_error / test_ex_ante_tracking_error_dummy tests which both still pass unmodified.

portfolio_variance, sharpe_ratio and quadratic_utility all call
cp.quad_form(..., assume_PSD=True), skipping cvxpy's numerical
PSD-certification check for the covariance matrix. This is the
right call since these objectives always receive a covariance
matrix, which is PSD by construction even when it's numerically
ill-conditioned.

ex_ante_tracking_error was the one quad_form-based objective
missing this, despite taking the same kind of cov_matrix
argument -- an inconsistency, and the same class of failure
reported in PyPortfolio#631 for a user's custom quad_form-based objective
("failure ... trying to certify that a matrix is positive
semi-definite").
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.

1 participant