squeeze-kernel 3.1.0__tar.gz → 3.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/PKG-INFO +2 -1
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/README.md +1 -0
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/pyproject.toml +1 -1
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/pyproject.toml.orig +1 -1
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/src/squeeze_kernel/__init__.py +1 -1
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/src/squeeze_kernel/estimator.py +35 -15
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/src/squeeze_kernel/batch.py +0 -0
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/src/squeeze_kernel/core.py +0 -0
- {squeeze_kernel-3.1.0 → squeeze_kernel-3.1.1}/src/squeeze_kernel/kernels.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: squeeze-kernel
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.1
|
|
4
4
|
Summary: Streaming, PSD-by-construction covariance estimator with Fisher-kernel weighting and adaptive shrinkage
|
|
5
5
|
Keywords: covariance,correlation,ewma,kernel,risk,streaming
|
|
6
6
|
Author: Robert Kende
|
|
@@ -35,6 +35,7 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
[](https://pypi.org/project/squeeze-kernel/)
|
|
36
36
|
[](https://pypi.org/project/squeeze-kernel/)
|
|
37
37
|
[](LICENSE)
|
|
38
|
+
[](https://doi.org/10.5281/zenodo.19170801)
|
|
38
39
|
|
|
39
40
|
A **streaming covariance estimator for panels of financial returns** whose entire public surface is **one number** — the decay `lam` of the anchor correlation timescale. Every other quantity is derived from it, fixed by a structural argument, or computed online from the estimator's own state. An `O(Kn²)` state update per day, positive semi-definite **by construction**, missing values handled **natively**, no tuning, no refits. Only dependency: NumPy.
|
|
40
41
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://pypi.org/project/squeeze-kernel/)
|
|
5
5
|
[](https://pypi.org/project/squeeze-kernel/)
|
|
6
6
|
[](LICENSE)
|
|
7
|
+
[](https://doi.org/10.5281/zenodo.19170801)
|
|
7
8
|
|
|
8
9
|
A **streaming covariance estimator for panels of financial returns** whose entire public surface is **one number** — the decay `lam` of the anchor correlation timescale. Every other quantity is derived from it, fixed by a structural argument, or computed online from the estimator's own state. An `O(Kn²)` state update per day, positive semi-definite **by construction**, missing values handled **natively**, no tuning, no refits. Only dependency: NumPy.
|
|
9
10
|
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "squeeze-kernel"
|
|
7
|
-
version = "3.1.
|
|
7
|
+
version = "3.1.1"
|
|
8
8
|
description = "Streaming, PSD-by-construction covariance estimator with Fisher-kernel weighting and adaptive shrinkage"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -4,7 +4,7 @@ build-backend = "uv_build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "squeeze-kernel"
|
|
7
|
-
version = "3.1.
|
|
7
|
+
version = "3.1.1"
|
|
8
8
|
description = "Streaming, PSD-by-construction covariance estimator with Fisher-kernel weighting and adaptive shrinkage"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -153,6 +153,18 @@ class _BlendGradient:
|
|
|
153
153
|
"""
|
|
154
154
|
|
|
155
155
|
_JITTER = 1e-12
|
|
156
|
+
_FLOOR = 1e-8 # spectral floor of the scored blend
|
|
157
|
+
_CERT = 10.0 # certify lambda_min >= _CERT * _FLOOR before skipping the floor
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def _solve(sig: np.ndarray, r: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
|
161
|
+
"""(sig^-1 r, sig^-1) from one Cholesky factorisation."""
|
|
162
|
+
if _cho_factor is not None:
|
|
163
|
+
cf = _cho_factor(sig, lower=True, check_finite=False)
|
|
164
|
+
return (_cho_solve(cf, r, check_finite=False),
|
|
165
|
+
_cho_solve(cf, np.eye(sig.shape[0]), check_finite=False))
|
|
166
|
+
sinv = np.linalg.inv(sig)
|
|
167
|
+
return sinv @ r, sinv
|
|
156
168
|
|
|
157
169
|
def __init__(self, half_lives: np.ndarray, prior: np.ndarray,
|
|
158
170
|
split: bool = False, n_experts: int = 3) -> None:
|
|
@@ -224,23 +236,31 @@ class _BlendGradient:
|
|
|
224
236
|
for k in range(K):
|
|
225
237
|
sig += self.prev_w[k] * self.prev_sig[k][np.ix_(idx, idx)]
|
|
226
238
|
sig = 0.5 * (sig + sig.T)
|
|
227
|
-
#
|
|
228
|
-
# engine's scoring path does: a near-singular early
|
|
229
|
-
# otherwise hand the running scale one enormous
|
|
230
|
-
# silence the mixer for years.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
239
|
+
# The spectrum is floored at _FLOOR before factorising, exactly as
|
|
240
|
+
# the research engine's scoring path does: a near-singular early
|
|
241
|
+
# blend would otherwise hand the running scale one enormous
|
|
242
|
+
# gradient and silence the mixer for years. The floor acts only
|
|
243
|
+
# when lambda_min < _FLOOR, so factorise first and certify: the
|
|
244
|
+
# inverse gives lambda_min >= 1/||sig^-1||_F, and a certified day
|
|
245
|
+
# is bit-identical to the floored path (no floor, same factor).
|
|
246
|
+
# Uncertified or failed days take the eigenvalue floor as before.
|
|
247
|
+
sol: tuple[np.ndarray, np.ndarray] | None = None
|
|
234
248
|
try:
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
else:
|
|
240
|
-
sinv = np.linalg.inv(sig)
|
|
241
|
-
u = sinv @ r_t[idx]
|
|
249
|
+
sol = self._solve(sig, r_t[idx])
|
|
250
|
+
fro = float(np.linalg.norm(sol[1]))
|
|
251
|
+
if not (np.isfinite(fro) and fro * self._CERT * self._FLOOR <= 1.0):
|
|
252
|
+
sol = None
|
|
242
253
|
except (np.linalg.LinAlgError, ValueError):
|
|
243
|
-
|
|
254
|
+
sol = None
|
|
255
|
+
if sol is None:
|
|
256
|
+
min_eig = float(np.linalg.eigvalsh(sig).min())
|
|
257
|
+
if min_eig < self._FLOOR:
|
|
258
|
+
sig = sig + np.eye(idx.size) * (self._FLOOR - min_eig)
|
|
259
|
+
try:
|
|
260
|
+
sol = self._solve(sig, r_t[idx])
|
|
261
|
+
except (np.linalg.LinAlgError, ValueError):
|
|
262
|
+
return None
|
|
263
|
+
u, sinv = sol
|
|
244
264
|
g = np.empty(K)
|
|
245
265
|
self._gc = None
|
|
246
266
|
if self.split and self.prev_comps is not None:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|