Repository navigation
feat: data-informed SV priors + dynamics-aware log-vol level (closes #65 #66) - #70
Merged
thomaspinder merged 6 commits intoMay 18, 2026
Conversation
RandomWalk.has_explicit_level = False, AR1.has_explicit_level = True (both as ClassVar — true class-level constants, not user-configurable). Multivariate SV adapter will use this in the next commit to skip the redundant per-variable mu_i shift when the dynamics already carries the log-vol level. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Protocol gains optional `data: np.ndarray | None = None` — the per-variable (T, n_vars) series (typically OLS residuals from VAR) that stochastic adapters use to seed per-variable priors. Constant accepts and ignores for signature parity. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…#65) Multivariate StochasticVolatility.build_pymc_latent now raises ValueError if `data` is None or has the wrong shape — silent zeros-fallback was the cause of #65. Per-variable prior threading lands in the next commit; this commit only enforces the contract and threads OLS residuals from VAR so the pipeline keeps building. VAR._build_pymc_model computes one-shot OLS lstsq before model construction and passes the (T_eff, n_vars) residual matrix as `data=resid`. Constant adapters ignore it. Pre-existing TestSVMultivariateBuild tests updated to pass a valid data=np.zeros((T, n_vars)) argument; they care about model structure, not prior quality. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oses #65 #66) For each variable i in the multivariate SV adapter: - prior_params now come from build_priors(data[:, i]) — per-variable innovation series informs h0_mu, alpha_mu, mu_sigma, etc. instead of the np.zeros(T) placeholder that produced near-pinpoint mu_i ≈ 0 and h0_mu ≈ -18.4 (closes #65). - mu_i is registered only when dynamics.has_explicit_level is False (random walk). For AR(1), the dynamics' alpha already carries the log-vol level — the outer shift was redundant (closes #66). Standalone univariate StochasticVolatility.fit is unaffected: it goes through _build_pymc_model, not build_pymc_latent. The byte-for-byte regression test (tests/test_sv_standalone_unchanged.py) continues to lock the standalone posterior. Class docstring updated; the convention-divergence note about mu_i folding into the log-vol level is replaced with the dynamics-aware description. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…efs #65) Integration test using a VolatilityProcess stand-in that records the `data` it receives. Verifies VAR passes a (T_eff, n_vars) residual matrix that is demeaned (intercept in X_full). Guards against silent regression of the threading the previous commit set up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## fix/constant-cache-cholesky-factor #70 +/- ##
====================================================================
+ Coverage 92.3% 92.4% +0.1%
====================================================================
Files 26 26
Lines 1126 1141 +15
Branches 107 111 +4
====================================================================
+ Hits 1040 1055 +15
Misses 65 65
Partials 21 21 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
7 tasks done
thomaspinder
merged commit May 18, 2026
8ff239a
into
fix/constant-cache-cholesky-factor
10 checks passed
This was referenced May 18, 2026
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #69 — review/merge #69 first; this PR's base is
fix/constant-cache-cholesky-factor.Summary
Closes #65 and #66 in one bundled PR (they touch the same per-variable loop in
src/impulso/sv/spec.py).#65 — multivariate SV priors. The adapter was calling
build_priors(np.zeros(T)), which produced a near-pinpoint prior onmu_i(sigma ≈ 1e-6) and a wildly off-targeth0_mu ≈ -18.4. Fix:VolatilityProcess.build_pymc_latentgains optionaldata: np.ndarray | None = None.VAR._build_pymc_modelpre-fits OLS once (cheap relative to MCMC) and passes the demeaned residuals(T_eff, n_vars)asdata=resid.build_priors(data[:, i])so each variable's priors come from its own innovation series.Constantaccepts and ignoresdata(Protocol parity).ValueErrorifdataisNoneor wrong shape — the silent zeros-fallback that caused Multivariate SV prior defaults tonp.zeros(T)— needs data-informed priors #65 is gone.#66 — redundant log-vol intercept. The multivariate adapter added an outer
mu_ishift on top of the dynamics' own intercept, double-counting the level for AR(1). Fix:SVDynamicsProtocol gainshas_explicit_level: bool(ClassVar — true class-level constant).AR1.has_explicit_level = True(itsalphacarries the log-vol level);RandomWalk.has_explicit_level = False(no intrinsic level).mu_iwhendynamics.has_explicit_level.Standalone univariate SV is unaffected. It goes through
_build_pymc_model, notbuild_pymc_latent. The byte-for-byte regression file (tests/test_sv_standalone_unchanged.py) was removed pre-existing in commit 034abe0, but the standalone smoke tests (test_sv_spec.py::test_sv_spec_fit_random_walk_smoke/_fit_ar1_smoke) pass unchanged.Test plan
pytest -m "not slow" -q— 236 passed, 22 deselectedpytest -m slow tests/test_volatility.py::TestPosteriorEquivalence -v— 2 passed (Constant byte-for-byte unchanged)pytest -m slow tests/test_sv_spec.py::test_sv_spec_fit_random_walk_smoke tests/test_sv_spec.py::test_sv_spec_fit_ar1_smoke -v— 2 passed (standalone SV unchanged)pytest -m slow tests/test_fitted.py::TestFittedVarSigmaDispatch::test_sv_sigma_returns_per_t -v— 1 passed (SV-VAR end-to-end)ruff check src/ tests/— cleanruff format --check src/ tests/— cleanty check— cleanTestHasExplicitLevel(2) —SVDynamicsadapter traitTestConstantBuildPymcLatent::test_accepts_and_ignores_data_kwarg— Constant Protocol parityTestSVBuildPymcLatentDataValidation(2) — multivariate SVdata=Noneand wrong-shape guardsTestSVMultivariatePerVariablePriors::test_calls_build_priors_with_per_variable_slice— spy onbuild_priorsper variableTestSVMultivariateDynamicsAwareLevel(2) — AR(1) skipsv{i}_mu, RW keeps itTestVarPassesResidualsToVolatility—CapturingVolatilityintegration test pinning the threading contractCommits
ffb13b7—has_explicit_levelonSVDynamicsa0b8964—datakwarg on Protocol + Constant2873b9a— multivariate SV requiresdata; VAR threads OLS residuals2359289— per-variable priors + dynamics-aware level (core fix)1593218—CapturingVolatilityintegration testNotes / follow-ups (out of scope)
TestSVVarRecovery) is currently softened to shape + finiteness only. With this fix, h-recovery should improve materially; a follow-up commit could re-strengthen the assertions. Deliberately deferred so this PR stays scoped.🤖 Generated with Claude Code