Skip to content

[BUG] CLA crashes with LinAlgError on singular covariance matrices instead of raising a user-facing validation error #737

@ayushraj09

Description

@ayushraj09

Description

CLA.max_sharpe() crashes with a low-level numpy.linalg.LinAlgError when the covariance matrix is singular (for example, when assets are perfectly correlated).
From a user's perspective, this input is mathematically valid: covariance matrices are allowed to be positive semidefinite (PSD). However, the current CLA implementation internally requires covariance submatrices to be invertible (positive definite) and currently does not validate this assumption before attempting inversion.
As a result, users receive a cryptic NumPy exception originating from a private method rather than a clear explanation of the actual issue.

Possible approaches to address this issue:

  • Raise a clear, user-facing validation error before optimization begins in the current CLA implementation.
  • Replace direct matrix inversion with a pseudo-inverse (np.linalg.pinv) to handle singular covariance matrices more gracefully.
  • Use the cvxcla implementation, which solves the optimization problem via Ax = b formulation and does not require explicit matrix inversion.

Support for cvxcla has already been introduced in PR #700

Code sample for reproducing this error

import numpy as np
from pypfopt.cla import CLA

mu = np.array([0.1, 0.2])

# perfectly correlated assets → singular covariance
S = np.array([
    [0.01, 0.01],
    [0.01, 0.01],
])

cla = CLA(mu, S)
cla.max_sharpe()

Operating system, python version, PyPortfolioOpt version
PyPortfolioOpt version: 1.6.0, Python version: 3.12, NumPy version: 1.26, OS: macOS (reproducible cross-platform)

Additional context
This issue surfaced during test coverage review.
The inversion line is exercised by existing tests (line coverage), but singular covariance inputs are currently untested (case coverage), allowing this failure mode to reach users.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions