Skip to content

Releases: QuantClimate/Impulso

v0.1.3

Choose a tag to compare

@thomaspinder thomaspinder released this 30 Sep 18:47
1c6ced6

Fix

  • A VAR embedded with build_in_model and a latent series no longer sets a redundant initial value on B, so the host PyMC model can be cloned again: Model.copy(), pm.do and pm.observe work (#369). The initial value is still set when a latent own-lag prior mean lies outside the stationary region, the default of 1 included, and such a model stays unclonable; the build_in_model docstring and ADR-0016 say so.

What's Changed

🐛 Bug Fixes

  • fix: leave the host model clonable when the latent start is the prior mean by @thomaspinder in #369

📖 Documentation

  • docs: housekeeping for the support link, badges and tutorial kernel paths by @thomaspinder in #366

🧩 Other

Full Changelog: v0.1.2...v0.1.3

v0.1.2

Choose a tag to compare

@thomaspinder thomaspinder released this 29 Sep 07:36
933148a

Fix

  • adf_test, kpss_test and integration_order no longer emit statsmodels 0.15's FutureWarning about result_object (#364). statsmodels 0.14.6 and later remain supported.

The dependency updates below change the development lock file only; the published dependency ranges are unchanged.

What's Changed

🐛 Bug Fixes

  • fix: stop leaking statsmodels 0.15's result_object FutureWarning by @thomaspinder in #364

🧩 Other

  • build(deps): Bump the python group across 1 directory with 5 updates by @dependabot[bot] in #311
  • build(deps-dev): Bump the linters group across 1 directory with 3 updates by @dependabot[bot] in #358

Full Changelog: v0.1.1...v0.1.2

v0.1.1

Choose a tag to compare

@thomaspinder thomaspinder released this 28 Sep 22:10
ee87fa0

Impulso has moved

No API or behaviour changes. This release updates the package metadata, so PyPI's Homepage, Repository and Documentation links point at the new locations. The only source change is the issue link in LongRunRestriction's error message.

What's Changed

📖 Documentation

Full Changelog: v0.1.0...v0.1.1

v0.1.0

Choose a tag to compare

@thomaspinder thomaspinder released this 28 Sep 07:13
4b282ce

Highlights

Impulso 0.1.0 makes a VAR embeddable in a PyMC model you already own, alongside the standalone VAR.fit workflow.

  • VAR.build_in_model: registers a VAR into the active PyMC model and returns handles to its variables. fit and prior_predictive now go through the same code path. Namespacing works through a nested named pm.Model.
  • Symbolic data: the observed block can be a PyTensor tensor, e.g. pm.Data. Its likelihood is then a pm.Potential.
  • Latent endogenous series: latent_names generates unobserved series inside the model from standard-normal innovations (non-centred). The observed likelihood is conditional on the innovations, and a stationarity constraint on the latent block keeps sampling stable.
  • MinnesotaPrior(own_lag_mean=...): the textbook per-variable own-lag mean. Use 0 for stationary series.
  • FittedVAR.from_posterior: validated construction of a FittedVAR from a posterior you produced elsewhere.
  • VAR specs round-trip through model_dump and model_validate, in python and JSON mode.

The design and its evidence are recorded in ADR-0016.

Upgrading from 0.0.14

There are no breaking changes to released APIs. The breaking changes of this development cycle (Minnesota cross-lag scaling in ADR-0015, the required sigma argument to Prior.build_priors, ErrorDistribution.logp, and rejection of constant endogenous columns) shipped in 0.0.14.

Known limits:

  • Latent series support Gaussian errors only.
  • A ConjugateVolatility subclass (e.g. PandemicBreak) does not round-trip through model_dump.
  • The latent stationarity constraint's eig is untested on the JAX backend.

What's Changed

🚀 Features

  • feat: accept a symbolic observed endog in build_in_model by @thomaspinder in #342
  • feat: generate latent series non-centred in build_in_model by @thomaspinder in #344
  • feat: latent own-lag mean, stationary init and stationarity constraint by @thomaspinder in #346
  • feat: reject embedded-path options build_in_model can't support by @thomaspinder in #348

🐛 Bug Fixes

  • fix: name the actual source in endog_scales validation errors by @thomaspinder in #340
  • fix: make VAR specs round-trip through model_dump/model_validate by @thomaspinder in #354

💥 Breaking Changes

📖 Documentation

Full Changelog: v0.0.14...v0.1.0

v0.0.14

Choose a tag to compare

@thomaspinder thomaspinder released this 25 Sep 07:26
65d626b

What's Changed

🚀 Features

🐛 Bug Fixes

  • fix(docs): re-tone theme accent to oxblood and fix dark-mode notebook cells by @thomaspinder in #302

💥 Breaking Changes

🧩 Other

  • docs: adopt qc-core plotting style by @thomaspinder in #295
  • fix(deps): align ArviZ floors with Matplotlib 3.11 by @thomaspinder in #297
  • docs(context): audit the glossary against code, then compress it by @thomaspinder in #298
  • fix(typing): make SVDynamics members read-only; unblock linter bumps by @thomaspinder in #299
  • build(deps): Bump the python group across 1 directory with 13 updates by @dependabot[bot] in #300
  • build(deps-dev): Bump the linters group with 3 updates by @dependabot[bot] in #301
  • build(deps-dev): Bump the linters group with 3 updates by @dependabot[bot] in #305
  • build(deps-dev): Bump ipywidgets from 8.1.8 to 8.1.9 in the python group by @dependabot[bot] in #306
  • build(deps-dev): Bump the linters group with 3 updates by @dependabot[bot] in #307
  • build(deps-dev): Bump the linters group with 3 updates by @dependabot[bot] in #310

Full Changelog: v0.0.13...v0.0.14

v0.0.13

Choose a tag to compare

@thomaspinder thomaspinder released this 05 Aug 20:19

What's Changed

🧩 Other

  • fix(sampling): reject interrupted NaN-padded posteriors; fit proxy-svar SV cell to the CI budget by @thomaspinder in #285
  • refactor(identification): declare last_diagnostics as the scheme seam's diagnostics capability by @thomaspinder in #286
  • refactor(scenario): one forecast-side solve engine; propagate() owns the lag recursion by @thomaspinder in #288
  • refactor(identification): one module per scheme by @thomaspinder in #290
  • refactor(posterior): one owner for the posterior schema by @thomaspinder in #291
  • refactor(results): deepen the result base; plotting consumes the result interface by @thomaspinder in #292
  • test: guard the FittedVAR->IdentifiedVAR field carry; drop the MCMC fit from the dispatch test by @thomaspinder in #293

Full Changelog: v0.0.12...v0.0.13

v0.0.12

Choose a tag to compare

@thomaspinder thomaspinder released this 04 Aug 21:47

What's Changed

🧩 Other

New Contributors

Full Changelog: v0.0.11...v0.0.12

v0.0.11

Choose a tag to compare

@thomaspinder thomaspinder released this 03 Aug 21:54

New tutorial: Checking a VAR Before You Trust It

A full model-checking walkthrough on real U.S. monetary policy data (1965–2007): stationarity and cointegration pretests (adf_test, kpss_test, integration_order, johansen_test), prior predictive checks, MCMC diagnostics in ArviZ (divergences, rank-normalised R-hat, bulk/tail ESS, trace, rank, and energy plots — including a real slow-mixing failure and its low-rank mass-matrix fix), and posterior predictive checks with quantile coverage. Fully cited, and rendered as part of the docs.

Bug fix

FittedVAR.posterior_predictive with named DataFrame indexes. Data built via VARData.from_df from a DataFrame whose index carries a name (e.g. "date") crashed with CoordinateValidationError: xarray adopted the index name as the coordinate's dimension, clashing with the explicit time dim. The time coordinate is now pinned with the explicit-dimension form, matching identified.py. Regression test included.

v0.0.10

Choose a tag to compare

@thomaspinder thomaspinder released this 30 Jul 21:15
b79c7dd

Dependency floors

pandas>=3.0 → >=2.3.3. The pandas 3.0 requirement was never needed — pandas is a pure I/O boundary in Impulso, and every numeric path crosses via .to_numpy(dtype=np.float64). Installing Impulso no longer forces a pandas major-version upgrade. Verified against pandas 2.3.3 across the full fast and MCMC suites.

matplotlib>=3.7 → >=3.9. This is a tightening, and consumer-visible. matplotlib 3.7 and 3.8 are built against the NumPy 1.x C ABI and cannot import under numpy>=2.0, which Impulso already required — so that combination never actually worked. If you are pinned to matplotlib 3.7 or 3.8, this release will no longer resolve for you.

CI

New lowest-direct-deps job resolves every declared dependency to its minimum and runs the test suite there, on Python 3.11. Previously the lockfile pinned current versions, so the floors in pyproject.toml were declared but never exercised — the matplotlib problem above is what that job found on its first run.

Full changelog: v0.0.9...v0.0.10

v0.0.9

Choose a tag to compare

@thomaspinder thomaspinder released this 30 Jul 09:07
2fd92a7

Structural identification, forecast diagnostics and stationarity testing land together in this release, alongside several fixes to inference that was previously silently wrong.

Before you upgrade

Three fixes change numbers you may already have published. None of them raise an error — the old results simply looked fine.

If you… …then What to do
use a custom Cholesky(ordering=...) your IRFs, FEVDs and historical decompositions were mislabelled — rows came back in ordering order while being reported as data order (#208) re-run; identity orderings are byte-identical and unaffected
fit with exog on the NUTS path the B_exog prior was pinned at Normal(0, 1) regardless of regressor scale, crushing coefficients on small-scale regressors — a true coefficient of 50 on a N(0, 0.01²) regressor recovered ≈1 (#237) re-fit; the prior now scales as exog_prior_scale · σᵢ / sd(xⱼ), default 100
forecast with multivariate stochastic volatility every forecast standard deviation sat at exp(-mu_i/2) times the correct scale — the in-sample fit was unaffected, so nothing looked wrong (#241) re-run; affects density, conditional and scenario forecasts. AR(1) log-vol dynamics were never affected

Three further changes reject input that used to be accepted silently: duplicate or overlapping variable names (#206), StudentT.prior_alpha ≤ 1 (#211), and ConjugateVolatility adapters declaring no hyperparameters (#233).

Highlights

  • ZeroSignRestriction — combined zero-and-sign identification via the Arias–Rubio-Ramírez–Waggoner recursive null-space construction (#218).

  • LongRunRestriction — Blanchard–Quah identification on cumulative long-run effects (#183).

  • FittedVAR.granger_causality() — reports the posterior of the coefficient norm as a magnitude, not a test statistic, so a small effect stays distinguishable from an imprecise one. toda_yamamoto() covers the lag-augmented procedure when integration orders are uncertain (#226).

  • Predictive checks — VAR.prior_predictive() and FittedVAR.posterior_predictive() (#230).

  • Stationarity diagnostics — adf_test, kpss_test, johansen_test, integration_order, behind a new extra (#197):

    pip install "impulso[diagnostics]==0.0.9"
  • Student-t observation errors (#168) and model evidence / Bayes factors on conjugate fits (#160).

Impulso is pre-v0.1 and the public API is still moving; breaking changes ship in minor releases with the rationale recorded in docs/adr/.


What's Changed

🚀 Features

  • feat(sv): align SVForecastResult index to calendar dates by @thomaspinder in #158
  • feat(conjugate): stamp the Metropolis acceptance rate on the posterior attrs by @thomaspinder in #210
  • feat(conjugate): expose model evidence and Bayes-factor comparison by @thomaspinder in #160
  • feat(spec): Student-t observation errors and predictive draws by @thomaspinder in #168
  • feat(identification): long-run (Blanchard-Quah) structural restrictions by @thomaspinder in #183
  • feat(stationarity): ADF, KPSS and Johansen diagnostics with integration-order bookkeeping by @thomaspinder in #197
  • feat(identification): combined zero-and-sign restrictions (ARW construction) by @thomaspinder in #218
  • feat(predictive): prior_predictive on VAR, posterior_predictive on FittedVAR by @thomaspinder in #230
  • feat(granger): Bayesian Granger causality with Toda-Yamamoto robustness by @thomaspinder in #226

🐛 Bug Fixes

  • fix(init): module-level lazy-import table and dir by @thomaspinder in #156
  • fix(spec): safe default sampler with cores=1 in VAR.fit by @thomaspinder in #157
  • fix(identification): weakref-validated posterior cache for ProxySVAR by @thomaspinder in #234
  • fix(scenario): finite shock-matrix guard; infer shock order in from_zero_restrictions by @thomaspinder in #223
  • fix(stationarity): re-emit non-target KPSS warnings; define p in the Johansen snippet by @thomaspinder in #212

💥 Breaking Changes

  • fix(data): reject duplicate and overlapping variable names in VARData by @thomaspinder in #206
  • fix(identification): return the ordered Cholesky factor in data row order by @thomaspinder in #208
  • fix(conjugate): reject volatility adapters with no hyperparameters to estimate by @thomaspinder in #233
  • fix(spec): scale the B_exog prior to the data instead of pinning sigma=1 by @thomaspinder in #237
  • fix(observation): prior_alpha > 1 guard and 5-dim innovation-covariance coverage by @thomaspinder in #211
  • fix(sv): re-apply the per-variable log-vol level in the SV forecast (#241) by @thomaspinder in #268

📖 Documentation

Full Changelog: v0.0.8...v0.0.9