Linear algebra utilities for portfolio optimization
Project description
cvx-linalg
Linear algebra utilities for portfolio optimization, part of the jebel-quant ecosystem.
Installation
pip install cvx-linalg
The ewm_covariance function requires the optional Polars dependency:
pip install 'cvx-linalg[ewm]'
Usage
The entire public API is re-exported at the top level, so a flat import is all you ever need:
from cvx.linalg import (
a_norm, cholesky, cholesky_solve, cov_to_corr,
inv, inv_a_norm, is_positive_definite, lstsq, pca, rand_cov, solve, valid,
GramOperator, bordered_solve,
)
from cvx.linalg.covariance.ewm_cov import ewm_covariance # requires the 'ewm' extra (polars)
Internally the package is organized into subpackages (which can also be
imported directly, e.g. from cvx.linalg.decomposition import qr):
| Subpackage | Contents |
|---|---|
cvx.linalg.core |
Type aliases, exceptions/warnings, condition-number helpers, matrix validation |
cvx.linalg.covariance |
Covariance utilities: PCA, random covariance, correlation conversion, EWM covariance |
cvx.linalg.decomposition |
Matrix decompositions: Cholesky, QR, SVD, eigenvalue routines, power iteration |
cvx.linalg.kkt |
Equality-constrained solves: bordered KKT systems, affine projections |
cvx.linalg.norm |
NaN-aware vector and matrix norms, A-norms and their inverses |
cvx.linalg.operators |
Symmetric linear operators (dense, Gram, factor, incremental) for active-set and Krylov solvers |
cvx.linalg.solve |
NaN-aware linear-system solvers: solve, lstsq, inv, det |
The one exception to the flat-import rule is ewm_covariance: it lives in
cvx.linalg.covariance.ewm_cov and is deliberately not re-exported because it
requires the optional polars dependency.
Core (cvx.linalg.core)
valid(matrix)— Return a boolean mask and valid submatrix by removing rows/columns with non-finite diagonal entriescond(matrix, p=None)— Condition number of a matrix (NaN-aware); accepts the samepnorm values asnumpy.linalg.condcheck_and_warn_condition(matrix, threshold)— EmitIllConditionedMatrixWarningwhen the condition number exceeds the thresholdwarn_ill_conditioned(cond_value, threshold)— EmitIllConditionedMatrixWarningfor an already-computed condition numberDEFAULT_COND_THRESHOLD— Default condition-number threshold (1e12) used by the ill-conditioning checks
Types
Matrix— Type alias for a 2-Dnumpy.ndarraywithfloat64dtypeVector— Type alias for a 1-Dnumpy.ndarraywithfloat64dtype
The package ships a py.typed marker; all public signatures are precisely annotated and verified with ty in CI.
Exceptions & Warnings
All exceptions and warnings live in core/exceptions.py:
DimensionMismatchError— Raised when vector length does not match matrix dimensionIllConditionedMatrixWarning— Emitted when the condition number exceeds a configurable thresholdInvalidComponentsError— Raised whenpcais asked for fewer than 1 or more components than the data supportsNegativeWarmupError— Raised when a negative warmup period is passed toewm_covarianceNonIntegerWarmupError— Raised when a non-integer warmup is passed toewm_covarianceNonSquareMatrixError— Raised when a square matrix is required but the input is not squareNotAMatrixError— Raised when a 2-D matrix is required but the input has different dimensionalitySingularMatrixError— Raised when a matrix is numerically singular
Covariance (cvx.linalg.covariance)
cov_to_corr(cov, min_var=1e-14)— Convert a covariance matrix to a correlation matrixewm_covariance(data, assets, index_col, window, is_halflife, warmup)— Exponentially weighted covariance matrices from a Polars DataFrame (requires theewmextra)pca(returns, n_components=10)— Principal Component Analysis via SVDrand_cov(n, seed=None)— Random positive semi-definite covariance matrix
Decompositions (cvx.linalg.decomposition)
cholesky(cov)— Upper triangular Cholesky factor R such that R.T @ R = covcholesky_solve(cov, rhs)— Solve cov @ x = rhs via Cholesky decomposition (falls back to LU for non-positive-definite matrices)is_positive_definite(matrix)— Return True if the matrix is symmetric positive-definiteeigh(matrix)— Eigenvalues/eigenvectors of the valid symmetric/Hermitian submatrix in ascending eigenvalue ordereigvalsh(matrix)— Eigenvalues-only convenience wrapper aroundeigheigvals(matrix)— Eigenvalues of a general square matrix (supports complex output for non-symmetric matrices)power_iteration(matrix, n_iter=1000, tol=1e-9, seed=None)— Estimate the dominant (largest-magnitude) eigenpair of a symmetric matrix via power iterationqr(matrix)— Reduced QR decomposition, matchingnp.linalg.qr(mode='reduced')svd(matrix)— Raw compact singular value decomposition vianp.linalg.svd(full_matrices=False)svd_k(matrix, k)— Exact truncated rank-kSVD (the best rank-kapproximation; leading triplets of the compact SVD)
Norms (cvx.linalg.norm)
norm(x, ord=None)— Norm of a vector or matrix, ignoring non-finite entries; supports allordvalues ofnp.linalg.norma_norm(vector, matrix=None)— Euclidean norm or NaN-aware matrix norminv_a_norm(vector, matrix=None)— Euclidean norm or inverse NaN-aware matrix norm
Solvers (cvx.linalg.solve)
solve(matrix, rhs, cond_threshold=1e12)— Solve a linear system (vector or matrix rhs) restricted to valid rows/columns; NaN entries are returned for invalid positionslstsq(matrix, rhs, cond_threshold=1e12)— Solve a least-squares system with NaN-aware row filtering; returns(x, residuals, rank, sv)consistent withnumpy.linalg.lstsqinv(matrix, cond_threshold=1e12)— Invert a matrix restricted to valid rows/columns; NaN rows/columns are returned for invalid positionsdet(matrix, cond_threshold=1e12)— Determinant of a square matrix with NaN-aware submatrix handling; emitsIllConditionedMatrixWarningwhen near-singular
Operators (cvx.linalg.operators)
Active-set and Krylov solvers never need a symmetric matrix A as an explicit
array — they touch it through a handful of products: a full matrix-vector
product, sub-block products, and a direct solve against a principal ("free")
sub-block. The SymmetricOperator
protocol captures exactly that contract (including rcond_free for detecting
rank-deficient free blocks and restricted(free) for a pre-sliced free-block
view), and the backends implement it at very different cost:
SymmetricOperator— Protocol exposing a symmetric matrix throughmatvec,block_matvec,solve_free,apply_free,rcond_free,restricted, anddiagDenseOperator— Backend wrapping an explicit densen x nmatrixIncrementalDenseOperator—DenseOperatormaintaining the free-block inverse across single-index flips for active-set sweepsGramOperator— Matrix-free backend forA = M.T @ M, represented by its factorM; never forms the Gram matrixFactorOperator— Diagonal-plus-low-rank backendA = diag(d) + U @ Delta @ U.Twith Woodbury free-block solvesSumOperator— Weighted sum of symmetric operators (forward-only; feedapply_freeto a Krylov solver)
Constrained solves (cvx.linalg.kkt)
Building blocks for active-set and path-tracing solvers, built on top of the operator protocol:
bordered_solve(operator, free, c_free, rhs, d)— Range-space (Schur complement) solve of the bordered KKT system[[H_FF, C.T], [C, 0]] @ [x; nu] = [rhs; d], reaching the Hessian block only through aSymmetricOperatorAffineProjection(c, d)— Euclidean projection onto the affine set{x : C x = d}, caching the Gram matrixC C.Tfor repeated use
Stability policy
This package follows semantic versioning. The public API
is everything importable from cvx.linalg (plus cvx.linalg.covariance.ewm_cov):
- Breaking changes only occur in major releases.
- Deprecations are announced at least one minor release before removal and
emit a
DeprecationWarningin the meantime (currently: the two-argumentcholesky(cov, rhs)form — usecholesky_solve— slated for removal in 1.0). - Supported environments: Python 3.11–3.14, NumPy ≥ 2.0. The optional
ewmextra requires Polars ≥ 1.40.
Numerical conventions (NaN handling, condition-number warnings, dtype contract) are documented in Numerical Behavior.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cvx_linalg-1.0.0.tar.gz.
File metadata
- Download URL: cvx_linalg-1.0.0.tar.gz
- Upload date:
- Size: 41.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c3626155679434344bbe1a765db7c16c943f4f424ef1ee34e7b464f32fdb570a
|
|
| MD5 |
83cf34306fd3a39f04958d8031d1228c
|
|
| BLAKE2b-256 |
bb8006c3d348fc0665de348888d14f2134c210b0720fc5d0e24b3da41f5052c7
|
Provenance
The following attestation bundles were made for cvx_linalg-1.0.0.tar.gz:
Publisher:
rhiza_release.yml on Jebel-Quant/linalg
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cvx_linalg-1.0.0.tar.gz -
Subject digest:
c3626155679434344bbe1a765db7c16c943f4f424ef1ee34e7b464f32fdb570a - Sigstore transparency entry: 2094633695
- Sigstore integration time:
-
Permalink:
Jebel-Quant/linalg@f44b245adeeb192486501bb01bd7d325e00e148f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Jebel-Quant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
rhiza_release.yml@f44b245adeeb192486501bb01bd7d325e00e148f -
Trigger Event:
push
-
Statement type:
File details
Details for the file cvx_linalg-1.0.0-py3-none-any.whl.
File metadata
- Download URL: cvx_linalg-1.0.0-py3-none-any.whl
- Upload date:
- Size: 51.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b59231d1bc7db260986e9527e9c2aa2c2f374259f135b8463353c6bd515eecf9
|
|
| MD5 |
5e6e0ace8b426d6be7666384e8c9a0c3
|
|
| BLAKE2b-256 |
2c7fe8ae0b18c421c53ab7c47e982b2aeda8f80844240b82e7118a5d5192f5c0
|
Provenance
The following attestation bundles were made for cvx_linalg-1.0.0-py3-none-any.whl:
Publisher:
rhiza_release.yml on Jebel-Quant/linalg
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cvx_linalg-1.0.0-py3-none-any.whl -
Subject digest:
b59231d1bc7db260986e9527e9c2aa2c2f374259f135b8463353c6bd515eecf9 - Sigstore transparency entry: 2094634082
- Sigstore integration time:
-
Permalink:
Jebel-Quant/linalg@f44b245adeeb192486501bb01bd7d325e00e148f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Jebel-Quant
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
rhiza_release.yml@f44b245adeeb192486501bb01bd7d325e00e148f -
Trigger Event:
push
-
Statement type: