API reference¶
The complete callable surface of tsecon, generated from the type stub (bindings/python/python/tsecon/__init__.pyi). Array arguments are float64 NumPy arrays (_ArrayLike = npt.NDArray[np.float64]; strided views are fine, plain lists and other dtypes are rejected at the boundary). Every function returns plain NumPy arrays and dictionaries — no framework objects. For the why and when of each method, see the model cards and the guide.
126 functions.
diagnostics¶
acf¶
Autocorrelation function with Bartlett standard errors.
pacf¶
Partial autocorrelation function; method is "yw" or "ols".
ljung_box¶
Ljung-Box and Box-Pierce portmanteau tests for lags 1..=nlags.
jarque_bera¶
Jarque-Bera normality test (statistic, p_value, skewness, kurtosis, n).
arch_lm¶
Engle's ARCH-LM test for conditional heteroskedasticity.
unit roots / workflow¶
adf¶
def adf(
y: _ArrayLike,
regression: str = ...,
autolag: str | None = ...,
maxlag: int | None = ...,
) -> dict[str, Any]:
Augmented Dickey-Fuller test with MacKinnon p-values.
kpss¶
KPSS stationarity test (null: stationary).
check_stationarity¶
The ADF + KPSS confirmatory-quadrant workflow with a recommendation.
phillips_perron¶
def phillips_perron(
y: _ArrayLike,
regression: str = ...,
test_type: str = ...,
lags: int | None = ...,
) -> dict[str, Any]:
Phillips-Perron unit-root test (Z-tau/Z-alpha) with MacKinnon p-values.
phillips_ouliaris¶
def phillips_ouliaris(
y: _ArrayLike,
x: _ArrayLike,
trend: str = ...,
test_type: str = ...,
bandwidth: int | None = ...,
) -> dict[str, Any]:
Phillips-Ouliaris residual cointegration test (Zt/Za) with MacKinnon N-surfaces.
ndiffs¶
def ndiffs(
y: _ArrayLike, test: str = ..., alpha: float = ..., max_d: int = ...
) -> dict[str, Any]:
How many differences a series needs, with the per-order test evidence.
box_cox_lambda¶
def box_cox_lambda(
y: _ArrayLike,
method: str = ...,
bounds: tuple[float, float] = ...,
period: int | None = ...,
) -> dict[str, Any]:
Variance-stabilising Box-Cox lambda (MLE or Guerrero) with its objective.
check_series¶
def check_series(
data: npt.ArrayLike,
seasonal_period: int | None = ...,
lags: int | None = ...,
alpha: float = ...,
max_breaks: int = ...,
trim: float = ...,
) -> dict[str, Any]:
One-call diagnostic battery with model recommendations (the Module 01 flagship).
Pure Python over the compiled tests, so plain lists are coerced. 1D input
runs descriptives, outliers, the ADF+KPSS quadrant, Ljung-Box/ACF/PACF,
ARCH-LM, Jarque-Bera, a sup-F/Bai-Perron mean-shift scan, GPH long memory,
and seasonality evidence; 2D (n, k) input runs per-series integration,
Johansen, and VAR lag selection with a stability check. Evidence is
reported in families with the multiple-testing arithmetic shown — never
silently corrected — and the report ends in an ordered `recommendations`
list routing to concrete tsecon calls. JSON-serializable throughout.
`lags` is shape-dependent: the Ljung-Box horizon for 1D input (default
min(10, n//5)), the VAR lag-search cap for 2D input (default 8). `alpha`
must lie in (0.01, 0.10] — the compiled KPSS p-value is clamped to that
range. `seasonal_period` must be an integer >= 2 with at least two full
cycles in sample.
summarize¶
Render any tsecon output as a readable results object (opt-in).
`print(tsecon.summarize(tsecon.adf(y)))` works for every function: a plain
dict becomes a generic `tsecon.results.Result` with an aligned `.summary()`,
while a bespoke `tsecon.results.*` object is returned unchanged. Additive —
the returned object is a `dict` subclass, so the plain-dict contract holds.
`wrap="generic"` forces the structural dump even on a bespoke object.
robust inference¶
long_run_variance¶
Kernel long-run variance of a series (demeaned internally).
ols¶
def ols(
y: _ArrayLike,
x: _ArrayLike,
se_type: str = ...,
maxlags: int | None = ...,
use_correction: bool = ...,
) -> dict[str, Any]:
OLS with nonrobust / HC0 / HC1 / HAC standard errors.
bootstrap¶
bootstrap_indices¶
def bootstrap_indices(
n: int,
scheme: str = ...,
seed: int = ...,
block_length: int | None = ...,
p: float | None = ...,
) -> npt.NDArray[np.uint64]:
Bootstrap resampling indices (iid/moving/circular/stationary).
optimal_block_length¶
Politis-White (2004) automatic block length (stationary, circular).
philox_uniforms¶
Uniform draws from the Philox stream; bit-identical to NumPy.
state space¶
local_level_smooth¶
Exact-diffuse local-level Kalman filter + smoother (NaN = missing).
ar_loglik¶
def ar_loglik(
y: _ArrayLike, coeffs: Sequence[float], sigma2: float, intercept: float = ...
) -> float:
Exact Gaussian log-likelihood of an AR(p) at fixed parameters.
ARIMA¶
arima_fit¶
def arima_fit(
y: _ArrayLike,
p: int = ...,
d: int = ...,
q: int = ...,
constant: bool = ...,
forecast_steps: int = ...,
conf_alpha: float | None = ...,
) -> dict[str, Any]:
Exact-MLE ARIMA(p,d,q) fit, with optional forecast + conf_alpha bands.
GARCH¶
garch_fit¶
def garch_fit(
y: _ArrayLike,
vol: str = ...,
mean: str = ...,
dist: str = ...,
p: int = ...,
o: int = ...,
q: int = ...,
forecast_horizon: int = ...,
) -> dict[str, Any]:
GARCH/GJR/EGARCH QMLE with MLE and Bollerslev-Wooldridge robust SEs.
VAR¶
var_fit¶
Fit a VAR(p) by OLS; params, sigma_u, ICs, and stability.
Read `is_stable` for the stability verdict. `min_root`/`max_root` are the
smallest/largest moduli of the reciprocal characteristic roots — stable iff
`min_root > 1`, so `max_root` alone is not a verdict.
var_irf¶
def var_irf(
data: _ArrayLike,
lags: int = ...,
horizon: int = ...,
orth: bool = ...,
trend: str = ...,
cumulative: bool = ...,
) -> list[list[list[float]]]:
Impulse responses [h][response][shock]; cumulative gives running sums.
Point path only. For frequentist confidence bands use `var_irf_bands`.
var_irf_bands¶
def var_irf_bands(
data: _ArrayLike,
lags: int = ...,
horizon: int = ...,
orth: bool = ...,
method: str = ...,
alpha: float = ...,
cumulative: bool = ...,
n_boot: int = ...,
seed: int = ...,
trend: str = ...,
bias_correct: bool = ...,
) -> dict[str, Any]:
Frequentist confidence bands on VAR impulse responses — the banded companion to var_irf.
Returns a dict with `point`/`se`/`lower`/`upper`, each `[h][response][shock]`
(same layout as `var_irf`), plus echoed `method`/`alpha`/`n_boot`. `method`:
"asymptotic" (Lütkepohl 1990 delta-method SEs, Wald bands
`point ± z_{1-alpha/2}·se`; `n_boot` is `None`) or "bootstrap" (residual
Efron/Kilian bootstrap, percentile bands, optional Kilian 1998
`bias_correct`). `orth` and `cumulative` behave exactly as in `var_irf`.
var_fevd¶
def var_fevd(
data: _ArrayLike, lags: int = ..., horizon: int = ..., trend: str = ...
) -> list[list[list[float]]]:
Forecast-error variance decomposition [h][variable][shock].
var_forecast¶
def var_forecast(
data: _ArrayLike,
lags: int = ...,
steps: int = ...,
alpha: float = ...,
trend: str = ...,
) -> dict[str, Any]:
Iterated VAR point forecasts with (1-alpha) intervals.
var_granger¶
def var_granger(
data: _ArrayLike,
caused: Sequence[int],
causing: Sequence[int],
lags: int = ...,
trend: str = ...,
) -> dict[str, Any]:
Granger-causality F test (matches statsmodels test_causality).
Bayesian VAR¶
bvar_fit¶
def bvar_fit(
data: _ArrayLike,
lags: int = ...,
lambda0: float = ...,
lambda1: float = ...,
lambda3: float = ...,
delta: float = ...,
) -> dict[str, Any]:
Minnesota-NIW conjugate BVAR posterior + log marginal likelihood.
bvar_irf_draws¶
def bvar_irf_draws(
data: _ArrayLike,
lags: int = ...,
horizon: int = ...,
n_draws: int = ...,
seed: int = ...,
lambda0: float = ...,
lambda1: float = ...,
lambda3: float = ...,
delta: float = ...,
cumulative: bool = ...,
) -> list[list[list[list[float]]]]:
Posterior Cholesky-IRF draws [draw][h][variable][shock] for credible bands.
bvar_hierarchical¶
def bvar_hierarchical(
data: _ArrayLike,
lags: int = ...,
delta: float = ...,
lambda0: float = ...,
lambda3: float = ...,
lambda1_init: float = ...,
lambda1_lo: float = ...,
lambda1_hi: float = ...,
optimize: str = ...,
hyperprior: str = ...,
n_grid: int = ...,
max_iter: int = ...,
tol: float = ...,
) -> dict[str, Any]:
Empirical-Bayes Minnesota-BVAR: pick lambda1 by maximizing the marginal likelihood (Giannone-Lenza-Primiceri 2015).
bvar_ssvs¶
def bvar_ssvs(
data: _ArrayLike,
lags: int = ...,
n_draws: int = ...,
burn: int = ...,
seed: int = ...,
c0: float = ...,
c1: float = ...,
prior_inclusion: float = ...,
ssvs_cov: bool = ...,
kappa0: float = ...,
kappa1: float = ...,
prior_inclusion_cov: float = ...,
gamma_a: float = ...,
gamma_b: float = ...,
horizon: int = ...,
thin: int = ...,
n_chains: int = ...,
) -> dict[str, Any]:
SSVS-BVAR (George-Sun-Ni 2008): spike-and-slab stochastic-search selection of VAR (and error-precision) restrictions by Gibbs; posterior inclusion probabilities, coef/Sigma means, and orthogonalized IRF draws.
mcmc_diagnostics¶
Rank-normalized split R-hat and bulk/tail ESS (ArviZ-exact).
filters¶
hp_filter¶
Hodrick-Prescott filter (O(n)); one_sided=True for the real-time variant.
bk_filter¶
def bk_filter(
y: _ArrayLike, low: float = ..., high: float = ..., k: int = ...
) -> dict[str, Any]:
Baxter-King band-pass filter (loses k observations at each end).
cf_filter¶
def cf_filter(
y: _ArrayLike, low: float = ..., high: float = ..., drift: bool = ...
) -> dict[str, Any]:
Christiano-Fitzgerald asymmetric band-pass filter.
hamilton_filter¶
Hamilton (2018) regression filter — the modern HP alternative.
forecasting / evaluation¶
dm_test¶
Diebold-Mariano test with the Harvey-Leybourne-Newbold correction.
accuracy¶
def accuracy(
actual: _ArrayLike,
forecast: _ArrayLike,
insample: _ArrayLike | None = ...,
period: int = ...,
) -> dict[str, float]:
Forecast accuracy measures (ME/RMSE/MAE/MAPE/sMAPE/MASE/RMSSE).
theta_forecast¶
The Theta method (Assimakopoulos-Nikolopoulos 2000).
local projections¶
lp¶
def lp(
y: _ArrayLike,
shock: _ArrayLike,
horizons: int = ...,
n_lag_controls: int = ...,
se: str = ...,
maxlags: int | None = ...,
cumulative: bool | str | None = ...,
) -> dict[str, Any]:
Local projection IRFs; se is "lag_augmented" (default) or "hac".
`cumulative`: False/"none" (level), True/"outcome" (cumulated outcome on
the contemporaneous impulse — a cumulative IRF, NOT a multiplier), or
"both" (cumulated outcome on cumulated impulse). For an identified
multiplier use `lp_multiplier`.
lp_iv¶
def lp_iv(
y: _ArrayLike,
impulse: _ArrayLike,
instrument: _ArrayLike,
horizons: int = ...,
n_lag_controls: int = ...,
cumulative: bool | str | None = ...,
) -> dict[str, Any]:
LP-IV: instrumented local projections with a first-stage F diagnostic.
`cumulative` takes False/"none", True/"outcome" or "both". True/"outcome"
cumulates only the OUTCOME, giving cumulated response per unit of
*contemporaneous* impulse — that grows without bound in the horizon and is
not a multiplier. Use `lp_multiplier` for the Ramey-Zubairy integral
multiplier.
lp_multiplier¶
def lp_multiplier(
y: _ArrayLike,
impulse: _ArrayLike,
instrument: _ArrayLike,
horizons: int = ...,
n_lag_controls: int = ...,
maxlags: int | None = ...,
) -> dict[str, Any]:
Ramey-Zubairy (2018) integral multiplier by one-step LP-IV.
Regresses the cumulated outcome on the cumulated impulse, instrumented by
the contemporaneous instrument, controlling for lags of both series. Both
sides accumulate over the same window, so the coefficient is a multiplier
rather than a cumulative impulse response. `se` is the kernel-HAC standard
error of that single 2SLS coefficient — inference on the multiplier
itself, not a delta-method ratio and not a leg's SE relabelled.
penalized regression¶
ridge¶
Ridge regression (closed form); scikit-learn Ridge objective.
elastic_net¶
def elastic_net(
x: _ArrayLike,
y: _ArrayLike,
alpha: float,
l1_ratio: float = ...,
tol: float = ...,
max_iter: int = ...,
) -> dict[str, Any]:
Elastic-net via coordinate descent; scikit-learn objective.
lasso¶
def lasso(
x: _ArrayLike,
y: _ArrayLike,
alpha: float,
tol: float = ...,
max_iter: int = ...,
) -> dict[str, Any]:
Lasso (elastic net with l1_ratio = 1.0).
structural identification¶
sign_restricted_svar¶
def sign_restricted_svar(
data: _ArrayLike,
restrictions: Sequence[tuple[int, int, int, str]],
lags: int = ...,
horizon: int = ...,
n_draws: int = ...,
max_tries: int = ...,
seed: int = ...,
lambda1: float = ...,
) -> dict[str, Any]:
Sign-restricted Bayesian SVAR: identified-set bands + acceptance diagnostics.
`restrictions` are (variable, shock, horizon, sign) tuples with sign in
{"+", "-"}. Returns per-(horizon, variable, shock) `quantiles` at
`probs=[0.05,0.16,0.50,0.84,0.95]`, the identified-set envelope
(`set_min`/`set_max`), and `diagnostics`.
zero_sign_svar¶
def zero_sign_svar(
data: _ArrayLike,
sign_restrictions: Sequence[tuple[int, int, int, str]],
zero_restrictions: Sequence[tuple[int, int, int]],
lags: int = ...,
horizon: int = ...,
n_draws: int = ...,
max_tries: int = ...,
seed: int = ...,
lambda1: float = ...,
weighted: bool = ...,
) -> dict[str, Any]:
Zero + sign restricted Bayesian SVAR: exact zeros by construction + sign rejection.
`sign_restrictions` are (variable, shock, horizon, sign) tuples with sign in
{"+", "-"} (may be empty); `zero_restrictions` are (variable, shock, horizon)
tuples imposing an exact zero on `Theta_h[variable, shock]` (horizon 0 =
impact). At least one list must be non-empty. Returns per-(horizon, variable,
shock) `quantiles` at `probs=[0.05,0.16,0.50,0.84,0.95]` (ARW-2018 importance-
weighted when `weighted=True`), the weight-invariant identified-set envelope
(`set_min`/`set_max`), per-accepted-draw `weights` (normalized to sum to 1) and
their effective sample size `ess`, and the acceptance `diagnostics`. With
strict-upper-triangle impact zeros and no sign restrictions the rotation at
every draw is pinned to Q=I, so each posterior draw's structural IRF equals
that draw's recursive Cholesky IRF (a per-draw identity checked to ~1e-10 in
the crate golden); the posterior of the bands therefore coincides with the
recursive-Cholesky posterior, and the reported `set_min`/`set_max` span
reflects posterior (not identified-set) uncertainty since the rotation is
fixed. The ARW weight is exactly 1 for impact-only zero patterns.
structural_fevd¶
def structural_fevd(
data: _ArrayLike,
lags: int = ...,
horizon: int = ...,
trend: str = ...,
impact: _ArrayLike | None = ...,
sigma: str = ...,
) -> dict[str, Any]:
Structural FEVD for an arbitrary structural impact matrix A0 (the gap var_fevd, recursive-Cholesky only, leaves).
`impact` is an optional (n, n) structural impact A0 (columns = one-SD
structural shocks, A0 A0' = Sigma; from any identification scheme). If None,
A0 is the lower Cholesky of the innovation covariance and the result equals
`var_fevd` exactly. `sigma` ("dfadj"|"mle") sets the default Cholesky's df
scaling; the FEVD shares are invariant to it (it only rescales the reported
`impact`). Returns `fevd` [horizon+1][variable][shock] (each row sums to 1)
and `impact` [n][n] (the A0 used).
historical_decomposition¶
def historical_decomposition(
data: _ArrayLike,
restrictions: Sequence[tuple[int, int, int, str]] = ...,
lags: int = ...,
horizon: int | None = ...,
identification: str = ...,
n_draws: int = ...,
max_tries: int = ...,
seed: int = ...,
lambda1: float = ...,
narrative_restrictions: list[dict] | None = ...,
n_weight_draws: int = ...,
) -> dict[str, Any]:
Historical decomposition: per-(time, variable, shock) structural-shock contributions.
Splits each variable into a deterministic/initial-condition `baseline` plus the
cumulated contribution `hd[time][variable][shock]` of each structural shock,
obeying the exact adding-up identity y = baseline + sum_j hd (validated to ~1e-10
against a NumPy reference). `times` are 0-based effective-sample indices
(= data_row - lags).
identification="cholesky" (default): a point decomposition at the OLS VAR with
Q=I; returns `times`, `baseline` [T_eff][n], `hd` [T_eff][n][n] indexed
[time][variable][shock], and the structural `shocks` [T_eff][n].
identification="sign": the importance-weighted SET decomposition over sign- (and
optionally narrative-) restricted rotations; returns `times`, `baseline`
(posterior-mean), `probs`, `hd_quantiles` [T_eff][n][n][len(probs)] (weighted
type-7), the weight-free identified-set envelope `hd_set_min`/`hd_set_max`,
per-draw `weights`, and `diagnostics`.
`narrative_restrictions` (sign mode) is a list of dicts with 0-based effective
indices:
{"type":"shock_sign","shock":int,"period":int,"sign":"+"|"-"}
{"type":"contribution","variable":int,"shock":int,"start":int,"end":int,
"rule":"most"|"least","strong":bool}
{"type":"contribution_sign","variable":int,"shock":int,"start":int,"end":int,
"sign":"+"|"-"}
narrative_svar¶
def narrative_svar(
data: _ArrayLike,
sign_restrictions: Sequence[tuple[int, int, int, str]] = ...,
narrative_restrictions: list[dict] | None = ...,
lags: int = ...,
horizon: int = ...,
n_draws: int = ...,
max_tries: int = ...,
seed: int = ...,
lambda1: float = ...,
n_weight_draws: int = ...,
) -> dict[str, Any]:
Narrative sign-restricted Bayesian SVAR (Antolín-Díaz & Rubio-Ramírez 2018).
Augments traditional sign restrictions with restrictions on named historical
episodes — shock signs and "most/least important contributor" statements (see
`historical_decomposition` for the `narrative_restrictions` dict schema) —
imposed by importance-reweighting the accepted rotations with weight = 1/P̂(N|S).
Returns per-(horizon, variable, shock) `quantiles` (weighted type-7) at
`probs=[0.05,0.16,0.50,0.84,0.95]`, the weight-free identified-set envelope
`set_min`/`set_max`, per-draw `weights` (mean 1), and `diagnostics` (with `ess`,
`narrative_acceptance_rate`, `min_ptilde`). With no narrative restrictions every
weight is 1 and it reproduces `sign_restricted_svar` bit-for-bit.
fry_pagan_svar¶
def fry_pagan_svar(
data: _ArrayLike,
restrictions: Sequence[tuple[int, int, int, str]],
lags: int = ...,
horizon: int = ...,
n_draws: int = ...,
max_tries: int = ...,
seed: int = ...,
lambda1: float = ...,
target: str = ...,
) -> dict[str, Any]:
Fry-Pagan (2011) median-target SVAR: the single coherent draw closest to the median band.
Sign restrictions set-identify a *set* of structural models; the pointwise
median band mixes responses from mutually inconsistent draws and is not
itself a model. This returns instead the single accepted, sign-normalized
draw whose structural IRFs jointly minimize the Fry-Pagan criterion -- the
sum, over the target cells, of squared deviations from the pointwise median,
each standardized by that cell's across-draw dispersion. `restrictions` are
(variable, shock, horizon, sign) tuples with sign in {"+", "-"}; `target` is
"restricted" (response cells of the sign-restricted shocks; default) or
"all". Returns the coherent `median_target_irf` [horizon+1][n][n], the
incoherent pointwise `median_irf` (for comparison), the selected `mt_index`
(0-based into the accepted set), its `mt_statistic`, `n_accepted`, and the
acceptance `diagnostics`. Reproducible at a fixed `seed` (substream
contract). The selected draw is a descriptive summary -- one interior point
of the identified set, dependent on the informative Haar prior -- not a
prior-free point estimate.
robust_svar_bounds¶
def robust_svar_bounds(
data: _ArrayLike,
restrictions: Sequence[tuple[int, int, int, str]],
lags: int = ...,
horizon: int = ...,
n_draws: int = ...,
seed: int = ...,
lambda1: float = ...,
alpha: float = ...,
) -> dict[str, Any]:
Giacomini-Kitagawa prior-robust identified-set bounds for a sign-restricted SVAR.
`restrictions` are (variable, shock, horizon, sign) tuples with sign in
{"+", "-"}. For each restricted shock, the per-draw identified set of the
structural IRF is computed exactly over the admissible rotation set and
summarized over the reduced-form posterior, removing the informative-Haar-
prior artifact that pointwise `sign_restricted_svar` bands carry. Returns
per (horizon, variable, shock): `set_lower_mean`/`set_upper_mean` (posterior-
mean identified-set edges), `robust_ci_lower`/`robust_ci_upper` (the level-
`alpha` robust credible region), and `lower_quantiles`/`upper_quantiles` at
`probs=[0.05,0.16,0.50,0.84,0.95]`. Unrestricted shocks are NaN;
`restricted_shocks` lists the valid shock indices; `diagnostics` reports
`empty_set_rate` (the share of draws whose restrictions were mutually
infeasible). Exact for a single restricted shock (Gafarov-Meier-Montiel-Olea
2018 closed form); with multiple jointly-restricted shocks each bound is that
shock's marginal identified set — a conservative outer approximation of the
joint set, since the cross-shock orthogonality coupling is not imposed.
long_run_svar¶
def long_run_svar(
data: _ArrayLike,
lags: int = ...,
horizon: int = ...,
trend: str = ...,
restrictions: Sequence[tuple[int, int]] | None = ...,
normalize: str = ...,
) -> dict[str, Any]:
Blanchard-Quah long-run SVAR: closed-form structural IRFs under frequency-zero restrictions.
`restrictions` is a list of (variable, shock) long-run zero pairs (None =>
classic recursive BQ); `normalize` is "long_run" (positive LR diagonal;
default) or "impact" (positive B diagonal). Returns `impact` (B),
`long_run` (LR = C(1) B), `long_run_multiplier` (C(1)), `irf`
[horizon+1][i][j], `cumulative_irf`, and `fevd`. Point estimate, no RNG.
max_share_svar¶
def max_share_svar(
data: _ArrayLike,
lags: int = ...,
target: int = ...,
h0: int = ...,
h1: int = ...,
horizon: int = ...,
trend: str = ...,
exclude_impact: bool = ...,
weighting: str = ...,
sign: str = ...,
) -> dict[str, Any]:
Max-share / maximum-FEV structural shock (Uhlig 2004; Francis et al 2014; Barsky-Sims 2011 news).
Identifies the single UNIT-VARIANCE structural shock maximizing the `target`
variable's forecast-error variance accumulated over the window `[h0, h1]`.
`weighting="window"` selects the Uhlig/Francis objective (incremental
windowed FEV; `share_window` is an exact accumulated-FEV fraction),
`"cumulative"` the Barsky-Sims objective (window-mean cumulative FEV share).
`exclude_impact=True` imposes zero impact on the target (Barsky-Sims news
shock). `sign` pins the identified sign ("cumsum"|"impact"|"none").
Returns `irf` [horizon+1][k], `impact` [k], `q` [k], `share_window` (float),
`fev_share` [horizon+1], and `eigenvalues` (ascending; length k, or k-1 when
`exclude_impact`).
proxy_svar¶
def proxy_svar(
data: _ArrayLike,
proxy: _ArrayLike,
lags: int = ...,
horizon: int = ...,
norm_var: int = ...,
unit: float = ...,
trend: str = ...,
robust_f: bool = ...,
) -> dict[str, Any]:
Proxy SVAR (external-instrument SVAR-IV): one shock from one instrument.
The residual-instrument covariance identifies the target shock's impact
column up to scale; the unit-effect normalization sets its impact on
`norm_var` to `unit` (sign pinned). `proxy` aligns to `data` rows (NaN
outside the instrument window is dropped). Returns `irf` (horizon+1, n),
`impact`, `relative_impact`, `cov_um`, `first_stage_f` (weak below 10),
`reliability` = Corr(m, u_norm)^2, `n_proxy`, and the estimated `shock`
(length T). Point estimate only -- no bands (v2: Jentsch-Lunsford MBB).
nongaussian_svar¶
def nongaussian_svar(
data: _ArrayLike,
lags: int = ...,
horizon: int = ...,
trend: str = ...,
contrast: str = ...,
max_iter: int = ...,
tol: float = ...,
order_by: str = ...,
) -> dict[str, Any]:
Non-Gaussian / independent-component SVAR identification (Lanne-Meitz-Saikkonen 2017; Gourieroux-Monfort-Renne 2017; FastICA).
Point-identifies the structural impact matrix B in u_t = B eps_t from the
reduced-form residuals ALONE -- no sign, zero, long-run, or proxy
restriction -- by exploiting the statistical INDEPENDENCE and NON-GAUSSIANITY
of the structural shocks (at most one Gaussian). Whitens by Sigma_u^{-1/2},
finds the orthogonal rotation maximizing non-Gaussianity via a deterministic
symmetric FastICA fixed point (log-cosh contrast, identity init -- bit-
reproducible), then B = Sigma_u^{1/2} Q. Columns are ordered by `order_by`
("kurtosis" = descending |excess kurtosis|, or "colnorm") and signed max-abs-
positive; both are CONVENTIONS, not economics. This is STATISTICAL
identification: it FAILS if the shocks are Gaussian, and a `shock_kurtosis`
near zero flags a weakly identified (near-Gaussian) column. Returns `impact`
(B, [var][shock]), `irf` ([horizon+1][var][shock], Theta_h = Psi_h B),
`rotation` (Q, [whitened][shock]), `shock_kurtosis` [k] (identified order),
`converged` (bool), `n_iter` (int), and `order` [k] (raw FastICA index per
identified position).
hetero_svar¶
def hetero_svar(
data: _ArrayLike,
regime_labels: npt.NDArray[np.integer] | Sequence[int],
lags: int = ...,
horizon: int = ...,
trend: str = ...,
base_regime: int | None = ...,
sign_normalization: str = ...,
) -> dict[str, Any]:
SVAR identification through heteroskedasticity (Rigobon 2003; Lanne-Lutkepohl 2008), two known variance regimes.
`data` is (T, n); `regime_labels` is an array-like of length T with EXACTLY
two distinct integer values (labels align to observations; the first `lags`
are dropped to match residuals). `base_regime` is the label normalized to
Lambda=I (default: the smaller label); the other regime's shock-variance
ratios are reported. `sign_normalization`: "max" (largest-|entry| per B
column made positive; default) or "diag" (B[j,j] >= 0).
Returns a dict with `B` (n x n impact matrix = Theta_0, columns in
ascending variance-ratio order), `variance_ratios` (the n generalized
eigenvalues, ascending), `structural_irf` ([h][i][j] = Theta_h = Psi_h B),
`min_ratio_gap` and `ratio_dist_from_unity` (identification margins),
`identified` (bool heuristic), `covariance_equality` (Bartlett-corrected
Box's M: statistic/dof/pvalue/distinct_regimes), `sigma_regime1`,
`sigma_regime2`, `regime1_label`, `regime2_label`, `regime_sizes`,
`n_vars`, `horizon`, `lags`, `sign_convention`.
Point-identified IF AND ONLY IF the variance ratios are pairwise distinct
(min_ratio_gap > 0); the shocks come out ordered by variance ratio and
carry no economic labels. Standard errors on B/Theta_h are not provided in
this closed-form build. The >2-regime and Markov-switching/GARCH variants
are deferred.
panel¶
panel_fe¶
def panel_fe(
outcome: _ArrayLike,
regressors: _ArrayLike,
se_type: str = ...,
bandwidth: float = ...,
) -> dict[str, Any]:
Fixed-effects panel OLS; outcome is N x T, regressors is k x N x T.
`se_type`: "nonrobust", "cluster" (by entity), or "driscoll_kraay".
panel_lp¶
def panel_lp(
outcome: _ArrayLike,
shock: _ArrayLike,
horizon: int = ...,
n_lag_controls: int = ...,
se_type: str = ...,
bandwidth: float = ...,
cumulative: bool = ...,
jackknife: bool = ...,
) -> dict[str, Any]:
Panel local projection of a common shock with fixed effects.
forecast comparison¶
cw_test¶
def cw_test(
e_small: _ArrayLike,
e_large: _ArrayLike,
yhat_small: _ArrayLike,
yhat_large: _ArrayLike,
lrv_lags: int = ...,
) -> dict[str, float]:
Clark-West test for nested-model equal predictive accuracy.
gw_test¶
Giacomini-White unconditional test of equal predictive ability.
spectral analysis¶
periodogram¶
def periodogram(
x: _ArrayLike, fs: float = ..., window: str = ..., detrend: str = ...
) -> dict[str, _F64]:
Periodogram PSD (freqs, psd); matches scipy.signal.periodogram.
welch¶
def welch(
x: _ArrayLike,
nperseg: int = ...,
fs: float = ...,
noverlap: int | None = ...,
window: str = ...,
detrend: str = ...,
) -> dict[str, _F64]:
Welch averaged-periodogram PSD; matches scipy.signal.welch.
coherence¶
def coherence(
x: _ArrayLike,
y: _ArrayLike,
nperseg: int = ...,
fs: float = ...,
noverlap: int | None = ...,
window: str = ...,
detrend: str = ...,
) -> dict[str, _F64]:
Magnitude-squared coherence in [0,1]; matches scipy.signal.coherence.
cointegration¶
johansen¶
Johansen cointegration test (data is T x k); trace + max-eig + rank.
engle_granger¶
def engle_granger(
data: _ArrayLike,
trend: str = ...,
autolag: str | None = ...,
maxlag: int | None = ...,
) -> dict[str, Any]:
Engle-Granger two-step cointegration test: stat + MacKinnon p-value/crit (statsmodels coint).
vecm¶
VECM ML estimation: alpha, beta, gamma, sigma_u, llf (statsmodels-exact).
regime switching¶
markov_switching_ar¶
def markov_switching_ar(
y: _ArrayLike,
k_regimes: int = ...,
order: int = ...,
switching_variance: bool = ...,
max_iter: int = ...,
tol: float = ...,
) -> dict[str, Any]:
Markov-switching AR fitted by EM (Hamilton 1989); regimes + durations.
MIDAS¶
midas_weights¶
MIDAS weights (sum to 1); scheme "exp_almon" or "beta".
umidas¶
def umidas(
y: _ArrayLike, hf_lags: _ArrayLike, se_type: str = ..., maxlags: int | None = ...
) -> dict[str, Any]:
U-MIDAS: unrestricted mixed-frequency regression (hf_lags is nobs x K).
multivariate GARCH¶
ccc_garch¶
CCC-GARCH (Bollerslev 1990); returns is T x k. Correlation + loglik.
dcc_garch¶
DCC-GARCH (Engle 2002); a, b, qbar, loglik, last correlation matrix.
realized volatility / HAR¶
realized_measures¶
Realized variance, bipower variation, and jump component (BNS 2004).
har_rv¶
def har_rv(
rv: _ArrayLike,
start: int = ...,
variant: str = ...,
hac_maxlags: int = ...,
use_correction: bool = ...,
) -> dict[str, Any]:
HAR-RV (Corsi 2009): RV_t on [const, daily, weekly, monthly], HAC SEs.
variant is "level", "log", or "sqrt".
connectedness¶
connectedness¶
def connectedness(
data: _ArrayLike, lags: int = ..., horizon: int = ..., trend: str = ...
) -> dict[str, Any]:
Diebold-Yilmaz connectedness (percent) from a VAR's GFEVD.
total, to_others, from_others, net, gfevd, pairwise_net (data is T x k).
factor model¶
factor_model¶
PCA factor model (T x N) + Bai-Ng (2002) factor selection.
factors, loadings, eigenvalues, icp1/icp2/pcp1/pcp2 and Ahn-Horenstein
eigenvalue-ratio (er) factor counts.
term structure¶
nelson_siegel¶
def nelson_siegel(
maturities: _ArrayLike,
yields: _ArrayLike,
decay: float = ...,
optimal_lambda: bool = ...,
) -> dict[str, Any]:
Nelson-Siegel yield-curve fit (Diebold-Li 2006).
level/slope/curvature factors, lambda, residuals, rsquared.
optimal_lambda=True estimates the decay by NLS.
svensson¶
def svensson(
maturities: _ArrayLike, yields: _ArrayLike, lambda1: float, lambda2: float
) -> dict[str, Any]:
Svensson (1994) four-factor yield-curve fit; nests Nelson-Siegel.
GMM / IV-GMM¶
iv_gmm¶
def iv_gmm(
x: _ArrayLike,
z: _ArrayLike,
y: _ArrayLike,
method: str = ...,
weight: str = ...,
bandwidth: float = ...,
tol: float = ...,
max_iter: int = ...,
) -> dict[str, Any]:
Linear IV-GMM (Hansen 1982) with robust or HAC weighting.
method is "2sls", "2step", or "iterated"; weight is "robust" or "hac".
Z must include the exogenous regressor columns. Returns params, bse,
residuals, and (over-identified) the Hansen j_stat/j_dof/j_pval.
leakage-safe time-series CV¶
cv_splits¶
def cv_splits(
n: int,
scheme: str = ...,
train: int = ...,
horizon: int = ...,
step: int = ...,
k: int = ...,
purge: int = ...,
embargo: int = ...,
) -> list[dict[str, list[int]]]:
Leakage-safe CV split indices for sequential data.
scheme is "expanding", "rolling", or "purged_kfold". Returns a list of
{"train": [...], "test": [...]} index dicts.
penalized ML (paths)¶
adaptive_lasso¶
def adaptive_lasso(
x: _ArrayLike,
y: _ArrayLike,
alpha: float,
l1_ratio: float = ...,
gamma: float = ...,
tol: float = ...,
max_iter: int = ...,
) -> dict[str, Any]:
Adaptive LASSO (Zou 2006): oracle-property weighted-L1 penalty.
coef, n_iter, max_change.
lasso_path¶
def lasso_path(
x: _ArrayLike,
y: _ArrayLike,
l1_ratio: float = ...,
n_lambdas: int = ...,
eps: float = ...,
tol: float = ...,
max_iter: int = ...,
) -> dict[str, Any]:
Elastic-net regularization path with AIC/BIC selection.
lambdas, coefs, rss, df, aic, bic, aic_best, bic_best.
forecast backtest¶
backtest¶
def backtest(
y: _ArrayLike,
window: str = ...,
train: int = ...,
horizon: int = ...,
refit_every: int = ...,
forecaster: str = ...,
period: int = ...,
insample_period: int = ...,
) -> dict[str, Any]:
Rolling/expanding pseudo-out-of-sample backtest.
window is "expanding" or "rolling"; forecaster is one of naive, drift,
mean, seasonal_naive, theta. Returns origins, per-horizon forecasts and
targets, and a per-horizon accuracy table.
nonlinear GMM (callback)¶
gmm_nonlinear¶
def gmm_nonlinear(
moments_fn: Callable[[_F64], _ArrayLike],
initial: _ArrayLike,
weight: _ArrayLike | None = ...,
) -> dict[str, Any]:
Nonlinear GMM (Hansen 1982) via Nelder-Mead over a Python moment function.
moments_fn maps a parameter vector (a 1-D float64 array) to an n-by-m matrix
of per-observation moment contributions (rows = observations, cols = moments),
returned as a NumPy array or list of lists. weight is the flattened m*m
weighting matrix (row-major) or None for the identity. Returns params,
objective, gbar, converged, iterations, fevals, nmoments, nparams.
weighted MIDAS¶
weighted_midas¶
def weighted_midas(
y: _ArrayLike,
hf_lags: _ArrayLike,
scheme: str = ...,
weight_start: tuple[float, float] | None = ...,
) -> dict[str, Any]:
Weighted MIDAS by NLS (Ghysels et al. 2007); exp_almon/beta weights, hf_lags is nobs x K.
state-dependent LP¶
lp_state¶
def lp_state(
y: _ArrayLike,
shock: _ArrayLike,
state_indicator: _ArrayLike,
horizons: int = ...,
n_lag_controls: int = ...,
se: str = ...,
maxlags: int | None = ...,
cumulative: bool | str | None = ...,
) -> dict[str, Any]:
State-dependent (interacted) local projections (Ramey-Zubairy 2018); per-regime IRFs and SEs.
`cumulative` takes False/"none", True/"outcome" or "both", as in `lp`.
mean-group panel VAR¶
mean_group_var¶
def mean_group_var(
entities: Sequence[_ArrayLike],
lags: int = ...,
trend: str = ...,
horizon: int = ...,
response: int = ...,
impulse: int = ...,
) -> dict[str, Any]:
Pesaran-Smith (1995) mean-group panel VAR over per-entity T_i x k matrices.
dynamic Nelson-Siegel¶
dynamic_ns¶
Dynamic Nelson-Siegel factors + one-step forecast (Diebold-Li 2006).
panel is T x n_maturities. Returns maturities, lambda, factors (T x 3),
rsquared, level/slope/curvature series, and a forecast dict.
FAVAR¶
favar¶
def favar(
panel: _ArrayLike,
policy: _ArrayLike,
n_factors: int = ...,
lags: int = ...,
trend: str = ...,
slow_indices: list[int] | None = ...,
horizon: int = ...,
orth: bool = ...,
) -> dict[str, Any]:
Two-step factor-augmented VAR (Bernanke-Boivin-Eliasz 2005).
factors (T x r), params, sigma_u, n_factors, n_endog, policy_index, and
the recursive policy-shock IRFs irf_panel (N x horizon+1) / irf_policy.
realized-volatility extras¶
realized_quarticity¶
Realized quarticity RQ = (n/3) sum r^4 (BNS 2002).
tripower_quarticity¶
Jump-robust tripower quarticity of integrated quarticity (BNS 2004).
bns_jump_test¶
BNS ratio jump test (BNS 2004; Huang & Tauchen 2005); dict with 'ratio'.
realized_range¶
def realized_range(
high: _ArrayLike,
low: _ArrayLike,
method: str = ...,
open: _ArrayLike | None = ...,
close: _ArrayLike | None = ...,
) -> float:
Range variance from OHLC bars; method is "parkinson" or "garman_klass".
score-driven volatility¶
gas_volatility¶
GAS(1,1) score-driven volatility (Creal-Koopman-Lucas 2013).
density is "gaussian" or "student_t". Returns omega/a/b (+ nu),
variance, std_resid, loglik, aic, bic, next_variance, and (horizon>0) a
forecast.
heterogeneous panel (MG)¶
panel_mean_group¶
def panel_mean_group(
ys: Sequence[_ArrayLike], xs: Sequence[_ArrayLike], method: str = ...
) -> dict[str, Any]:
Mean-group (Pesaran-Smith 1995) / CCE-MG (Pesaran 2006) panel estimator.
method is "mg" or "cce". ys/xs are per-unit response vectors and T_i x k
regressor matrices. Returns coef, se, tstat, coef_per_unit, n_units, k.
panel_pmg¶
Pooled Mean Group ARDL(1,1) panel estimator (Pesaran-Shin-Smith 1999).
Pools the long-run coefficient across units by ML; error-correction speed
and short-run dynamics stay unit-specific. Returns theta, theta_se,
phi_bar, phi, sigma2, loglik, iterations, n_units, k.
panel_unit_root¶
def panel_unit_root(
data: _ArrayLike | Sequence[_ArrayLike],
test: str = ...,
lags: str | int | None = ...,
regression: str = ...,
max_lags: int | None = ...,
lrv_kernel: str = ...,
lrv_bandwidth: float | None = ...,
) -> dict[str, Any]:
First-generation panel unit-root tests (LLC, IPS, Fisher/Maddala-Wu-Choi).
data is a balanced N x T array (rows = units) or a list of 1-D per-unit
series (unbalanced OK for "ips"/"fisher"; "llc" needs a common T). test is
"ips" (default), "llc", or "fisher"; regression is "c"/"ct"/"n" ("n" is
invalid for "ips"); lags is None (per-unit auto AIC), an int (fixed common
lag), or "aic"/"bic"/"t-stat". Returns statistic, p_value,
per_unit_tstat/pvalue/lags/nobs, n_units, regression, plus test-specific
extras: ips -> t_bar; llc -> delta_hat, t_delta, s_n, t_bar_periods;
fisher -> maddala_wu, choi_z, choi_z_pvalue.
DFM nowcasting¶
dfm_nowcast¶
def dfm_nowcast(
data: _ArrayLike,
n_factors: int = ...,
factor_order: int = ...,
method: str = ...,
) -> dict[str, Any]:
Dynamic-factor-model nowcast; data is T x N with an optional NaN edge.
method is "two_step" (Doz-Giannone-Reichlin 2011) or "mle" (exact
one-step Gaussian MLE, single factor). Returns nowcast, edge_factor,
loglik, fit_loglik, smoothed_factors, n_factors, factor_order.
dfm_news¶
def dfm_news(
old_vintage: _ArrayLike,
new_vintage: _ArrayLike,
target_series: int = ...,
target_period: int | None = ...,
n_factors: int = ...,
factor_order: int = ...,
) -> dict[str, Any]:
News/update decomposition of a DFM nowcast revision (Banbura-Modugno 2014).
Splits the target-series nowcast revision between two data vintages into
per-datapoint contributions (weight*news). Returns old_nowcast,
new_nowcast, total_revision, and contributions (a list of dicts).
predictive regressions / IVX¶
predictive_regression¶
def predictive_regression(
r: _ArrayLike, x: _ArrayLike, cz: float = ..., alpha: float = ...
) -> dict[str, Any]:
Predictive regression with a persistent regressor.
Returns ols, stambaugh (bias-corrected), and ivx (Kostakis-Magdalinos-
Stamatogiannis 2015, Wald test valid uniformly over persistence).
ivx_test¶
def ivx_test(
r: _ArrayLike, xs: _ArrayLike, cz: float = ..., alpha: float = ...
) -> dict[str, Any]:
Joint IVX predictability test for several persistent predictors (xs is T x k).
Returns beta_ivx, the joint wald/pvalue, rz, nregressors, nobs.
recession probability¶
recession_probit¶
def recession_probit(
y: _ArrayLike, x: _ArrayLike, link: str = ..., dynamic: bool = ...
) -> dict[str, Any]:
Probit/logit of a binary recession indicator (Kauppi-Saikkonen dynamic option).
link is "probit" or "logit". Returns params, bse, zstats, probabilities,
loglik, pseudo_r2, converged (and rho for dynamic=True).
survey expectations¶
cg_regression¶
def cg_regression(
errors: _ArrayLike,
revisions: _ArrayLike,
maxlags: int | None = ...,
use_correction: bool = ...,
) -> dict[str, Any]:
Coibion-Gorodnichenko (2015) information-rigidity regression (OLS-HAC).
Returns intercept/slope with HAC se/t/p, r_squared, implied_rigidity.
forecast_efficiency¶
def forecast_efficiency(
errors: _ArrayLike,
regressors: _ArrayLike,
maxlags: int | None = ...,
use_correction: bool = ...,
) -> dict[str, Any]:
Mincer-Zarnowitz forecast-efficiency Wald test (OLS-HAC); regressors is T x k.
forecast_disagreement¶
Forecast-disagreement measures (per-period std/quartiles/iqr) from a forecaster panel.
long memory¶
frac_diff¶
Fractional differencing (1-L)^d via the binomial expansion.
frac_integrate¶
Fractional integration (1-L)^-d, the inverse of frac_diff.
long_memory_d¶
Estimate the memory parameter d; method is "gph" or "local_whittle". Returns d, se, m.
specification tests¶
heteroskedasticity_test¶
Heteroskedasticity test (test="white" or "breusch_pagan"); x is T x k with a constant.
reset_test¶
Ramsey RESET functional-form F-test; x is T x k.
chow_test¶
Chow structural-break F-test at a known 0-indexed split; x is T x k.
cusum_test¶
CUSUM parameter-stability test (Brown-Durbin-Evans); returns the path and 5% bounds.
arbitrage-free NS¶
afns_adjustment¶
Arbitrage-free Nelson-Siegel yield adjustment (Christensen-Diebold-Rudebusch 2011); sigma has 3 elements.
DSGE-lite¶
dsge_solve¶
def dsge_solve(
a: _ArrayLike, b: _ArrayLike, c: _ArrayLike, n_predetermined: int
) -> dict[str, Any]:
Blanchard-Kahn solution of a linear RE model A E[y_{t+1}] = B y_t + C z.
Returns the decision rule g, the law of motion p/q, eigenvalue_moduli, and verdict.
quantile & growth-at-risk¶
quantile_regression¶
def quantile_regression(
y: _ArrayLike,
x: _ArrayLike,
taus: Sequence[float] | None = ...,
se: str = ...,
) -> dict[str, Any]:
Linear quantile regression (statsmodels QuantReg, all defaults).
IRLS check-loss coefficients with Powell kernel-sandwich standard errors
(Epanechnikov kernel, Hall-Sheather bandwidth; `se="robust"` is the only
flavor). Include the constant column in `x`. Returns per-tau `params`,
`bse`, `tvalues`, `iterations`, `bandwidth`, `sparsity`, plus a single
`converged` bool over all taus.
quantile_lp¶
def quantile_lp(
y: _ArrayLike,
shock: _ArrayLike,
taus: Sequence[float] | None = ...,
horizons: int = ...,
n_lag_controls: int = ...,
) -> dict[str, Any]:
Quantile local projections: irf[tau][h] with Powell-sandwich se[tau][h].
Per horizon, `y_{t+h}` on `[shock_t, const, p lags of y and shock]` at
each tau (tsecon-lp design conventions); matches statsmodels QuantReg on
the identical design.
growth_at_risk¶
def growth_at_risk(
y: _ArrayLike,
conditions: _ArrayLike,
horizon: int = ...,
taus: Sequence[float] | None = ...,
rearrange: bool = ...,
) -> dict[str, Any]:
Growth-at-risk (Adrian-Boyarchenko-Giannone 2019).
Conditional quantiles of the h-ahead outcome on `[const, conditions,
y_t]`, evaluated at every t — `current` is the latest risk read. `taus`
must be strictly increasing and `horizon >= 1`. `rearrange` applies the
Chernozhukov-Fernandez-Val-Galichon monotone sort across tau; `crossing`
reports whether the raw fitted quantile paths crossed either way.
functional shocks (FVAR / FLP)¶
functional_pca¶
Functional PCA of a T x M curve panel (Inoue-Rossi 2021).
Returns mean_curve, eigenfunctions (K x M), scores (T x K), eigenvalues,
explained, total_variance. Sign: each eigenfunction's largest-|.| entry
is positive.
flp¶
def flp(
y: _ArrayLike,
scores: _ArrayLike,
horizons: int = ...,
n_lag_controls: int = ...,
hac_maxlags: int | None = ...,
) -> dict[str, Any]:
Functional local projection: y_{t+h} on ALL K scores jointly + const + lags of y, Newey-West HAC (maxlags = h + n_lag_controls default).
Returns horizons, n_factors, betas ((H+1) x K), covs (joint (H+1) x K x K),
se, nobs.
flp_scenario¶
def flp_scenario(
y: _ArrayLike,
curves: _ArrayLike,
delta: _ArrayLike,
n_factors: int = ...,
horizons: int = ...,
n_lag_controls: int = ...,
hac_maxlags: int | None = ...,
) -> dict[str, Any]:
IRF of y to a whole-curve scenario delta (length M): FPCA, joint FLP, then response w'beta_h with se sqrt(w' Cov_h w).
Returns horizons, weights, response, se, betas, explained.
fvar_scenario¶
def fvar_scenario(
y: _ArrayLike,
curves: _ArrayLike,
delta: _ArrayLike,
n_factors: int = ...,
lags: int = ...,
horizon: int = ...,
) -> dict[str, Any]:
FVAR scenario: VAR([scores, y], scores FIRST) with Cholesky identification; score innovation set to w = phi'delta, outcome's own structural shock zero (impact response of y is a modeling assumption).
Returns horizons, weights, response_outcome, responses ((H+1) x (K+1),
scores first then outcome), implied_outcome_innovation.
structural breaks¶
bai_perron¶
def bai_perron(
y: _ArrayLike, x: _ArrayLike, max_breaks: int = ..., trim: float = ...
) -> dict[str, Any]:
Bai-Perron multiple breaks: DP global partitions, sequential supF(l+1|l) selection at 5%, per-regime OLS, and Bai (1997) break-date confidence intervals; x is T x q with all coefficients switching (include your constant).
sup_f_test¶
Andrews sup-F (Quandt) unknown-break test with Hansen (1997) approximate p-value; returns stat, p_value, break_date, and the full f_path over the trimmed dates.
smooth local projections¶
smooth_lp¶
def smooth_lp(
y: _ArrayLike,
shock: _ArrayLike,
horizons: int = ...,
n_lag_controls: int = ...,
lam: float | str | None = ...,
degree: int = ...,
n_basis: int | None = ...,
penalty_order: int = ...,
lambda_grid: Sequence[float] | None = ...,
n_folds: int = ...,
hac_maxlags: int | None = ...,
) -> dict[str, Any]:
Smooth local projections (Barnichon-Brownlees 2019): the IRF as a penalized B-spline in the horizon, estimated jointly across horizons.
`lam`: a float fixes the smoothing parameter (0.0 reproduces the
per-horizon `lp(se="hac")` point estimates with the default basis);
"cv"/None cross-validates it by leave-h-block-out CV over `lambda_grid`
(or a default log-spaced grid). `penalty_order=2` shrinks the IRF toward
a straight line as `lam` grows. `se` conditions on `lam` and does not
account for shrinkage bias; `irf_raw`/`se_raw` are the unsmoothed
per-horizon HAC LP for comparison. Keys: horizons, irf, se, lambda_used,
cv_grid, cv_scores, theta, irf_raw, se_raw.