Coverage for src/pyhrp/covariance.py: 100%
14 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-17 14:01 +0000
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-17 14:01 +0000
1"""Covariance and correlation estimation from returns.
3This module isolates the second-moment estimators used by the HRP allocation
4entry points:
5- compute_cov: Covariance matrix from a DataFrame of returns
6- compute_corr: Correlation matrix from a DataFrame of returns
7- _returns: Simple returns from a DataFrame of prices
8"""
10from __future__ import annotations
12import numpy as np
13import polars as pl
15__all__ = ["compute_corr", "compute_cov"]
18def compute_cov(df: pl.DataFrame) -> pl.DataFrame:
19 """Compute covariance matrix from a DataFrame of returns."""
20 cols = df.columns
21 cov = np.atleast_2d(np.cov(df.to_numpy().T))
22 return pl.DataFrame(dict(zip(cols, cov, strict=True)))
25def compute_corr(df: pl.DataFrame) -> pl.DataFrame:
26 """Compute correlation matrix from a DataFrame of returns."""
27 cols = df.columns
28 corr = np.atleast_2d(np.corrcoef(df.to_numpy().T))
29 return pl.DataFrame(dict(zip(cols, corr, strict=True)))
32def _returns(prices: pl.DataFrame) -> pl.DataFrame:
33 """Compute simple returns from prices.
35 Drops leading all-null rows produced by pct_change and fills remaining
36 nulls/NaNs (e.g. from missing prices) with zero returns.
37 """
38 return (
39 prices.select(pl.all().pct_change())
40 .filter(pl.any_horizontal(pl.all().is_not_null()))
41 .fill_null(0.0)
42 .fill_nan(0.0)
43 )