Metadata-Version: 2.4
Name: psd-covariance
Version: 1.1.0
Summary: Covariance estimators based on spectral regularization (PM, ridge, clipping, shrinkage).
Author: Jesper Cremers
Author-email: Jesper.Cremers@vub.be
License: MIT
Keywords: covariance estimation,shrinkage,regularization,statistics,finance
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Intended Audience :: Science/Research
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy
Requires-Dist: scipy
Requires-Dist: joblib
Requires-Dist: scikit-learn
Requires-Dist: pandas
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# psd-covariance: Positive Definite Covariance Matrix Estimation

[![PyPI](https://img.shields.io/pypi/v/psd-covariance.svg)](https://pypi.org/project/psd-covariance/)
![Python versions](https://img.shields.io/pypi/pyversions/psd-covariance.svg)
![License](https://img.shields.io/pypi/l/psd-covariance.svg)
[![Downloads](https://pepy.tech/badge/psd-covariance)](https://pepy.tech/project/psd-covariance)

## Introduction

psd-covariance` provides tools for covariance matrix estimation and regularization in settings where the sample covariance matrix may be ill-conditioned or fail to be positive definite. The package implements spectral methods that improve numerical stability while preserving a clear eigenvalue-based interpretation.

Its main component is the `PosteriorMeanEstimator`, which implements Bayesian eigenvalue regularization. The package also includes eigenvalue clipping, ridge regularization, and classical shrinkage estimators.

The package contains four main modules:

- `PosteriorMeanEstimator`: posterior mean covariance estimation (PM and PM-FT)
- `EigenvalueClippingEstimator`: eigenvalue thresholding
- `RidgeEstimator`: ridge-type covariance regularization
- `ShrinkageMethods`: linear shrinkage and quadratic inverse shrinkage (QIS)

---

## Installation

```bash
pip install psd-covariance
```

---

## Imports

```python
import numpy as np
import pandas as pd

from psd_covariance.posterior_mean import PosteriorMeanEstimator
from psd_covariance.eigenvalue_clipping import EigenvalueClippingEstimator
from psd_covariance.ridge_regularization import RidgeEstimator
from psd_covariance.shrinkage_methods import ShrinkageMethods
from psd_covariance.utils import sample_cov
```

---

## Quick Start

### Example 1: Transforming a non-PSD matrix

```python
import numpy as np
from psd_covariance.posterior_mean import PosteriorMeanEstimator

eigvals = np.array([-0.50, -0.48, 0.59, 0.70, 0.83,
                    0.89, 1.01, 1.39, 1.67, 1.96])

d = len(eigvals)
A = np.random.randn(d, d)
Q, _ = np.linalg.qr(A)
Sigma_tilde = Q @ np.diag(eigvals) @ Q.T

pm = PosteriorMeanEstimator(fixed_trace=False)
pm_result = pm.fit(Sigma_tilde, sigma=0.5)

pmft = PosteriorMeanEstimator(fixed_trace=True)
pmft_result = pmft.fit(Sigma_tilde, sigma=0.5)

print("PM eigenvalues:", np.linalg.eigvalsh(pm_result.cov))
print("PM-FT eigenvalues:", np.linalg.eigvalsh(pmft_result.cov))
```

---

### Example 2: Cross-validation

```python
import numpy as np
from psd_covariance.posterior_mean import PosteriorMeanEstimator
from psd_covariance.utils import sample_cov

np.random.seed(0)

d, n = 10, 20
rho = 0.8
cov = np.fromfunction(lambda i, j: rho ** np.abs(i - j), (d, d))
X = np.random.multivariate_normal(np.zeros(d), cov, size=n)

S = sample_cov(X)
sigma_range = np.linspace(0.01, 2.0, 150)

pm = PosteriorMeanEstimator()
sigma_pm = pm.cross_validate_sigma(X, sigma_range)

pmft = PosteriorMeanEstimator(fixed_trace=True)
sigma_pmft = pmft.cross_validate_sigma(X, sigma_range)

print("PM sigma:", sigma_pm)
print("PM-FT sigma:", sigma_pmft)
```

---

### Example 3: Clipping and Ridge

```python
import numpy as np
from psd_covariance.eigenvalue_clipping import EigenvalueClippingEstimator
from psd_covariance.ridge_regularization import RidgeEstimator

Sigma_tilde = np.array([
    [1.0, 0.4, 0.3],
    [0.4, 0.2, 0.5],
    [0.3, 0.5, -0.1]
])

clip = EigenvalueClippingEstimator()
tau = clip.threshold_for_min_eigenvalue(Sigma_tilde, target_min=0.1)
clip_result = clip.fit(Sigma_tilde, tau)

ridge = RidgeEstimator()
alpha = ridge.alpha_for_min_eigenvalue(Sigma_tilde, target_min=0.1)
ridge_result = ridge.fit(Sigma_tilde, alpha)

print("Clipping threshold:", tau)
print("Ridge alpha:", alpha)
```

---

### Example 4: Shrinkage

```python
import numpy as np
import pandas as pd
from psd_covariance.shrinkage_methods import ShrinkageMethods

np.random.seed(1)
X = pd.DataFrame(np.random.randn(100, 5))

linear = ShrinkageMethods.linear_shrinkage(X)
qis = ShrinkageMethods.quadratic_inverse_shrinkage(X)

print("Shrinkage intensity:", linear.shrinkage)
print("QIS covariance shape:", qis.cov.shape)
```

---

## Main Classes

### PosteriorMeanEstimator
- `fit(Sigma_tilde, sigma)`
- `cross_validate_sigma(X, sigma_range)`
- `sigma_for_min_eigenvalue(Sigma_tilde, target_min)`

### EigenvalueClippingEstimator
- `fit(Sigma_tilde, threshold)`
- `cross_validate_threshold(X, threshold_range)`
- `threshold_for_min_eigenvalue(Sigma_tilde, target_min)`

### RidgeEstimator
- `fit(Sigma_tilde, alpha)`
- `cross_validate_alpha(X, alpha_range)`
- `alpha_for_min_eigenvalue(Sigma_tilde, target_min)`

### ShrinkageMethods
- `linear_shrinkage(X)`
- `quadratic_inverse_shrinkage(X)`

---

## Authors

Based on:

*Boudt, K., J. Cremers, K. Dragun, and S. Vanduffel (2025). Well-conditioned covariance estimation via bayesian eigenvalue regularization. Working paper.*

Maintained by Jesper Cremers.
---

## References 
- Boudt, K., J. Cremers, K. Dragun, and S. Vanduffel (2025). Well-conditioned covariance estimation via bayesian eigenvalue regularization. *Working paper.* 
- Ledoit, O. and M. Wolf (2004). Honey, I shrunk the sample covariance matrix. *The Journal of Portfolio Management 30 (4), 110-119.* 
- Ledoit, O. and M. Wolf (2022). Quadratic shrinkage for large covariance matrices. *Bernoulli 28 (3), 1519-1547.* 
- Rousseeuw, P. J. and G. Molenberghs (1993). Transformation of non positive semidefinite correlation matrices. *Communications in Statistics - Theory and Methods 22 (4), 965-984.*

---

## Notes

Parts of the shrinkage implementation are adapted from:
https://github.com/pald22/covShrinkage
