Migrating from R¶
Part of The tsecon Guide to Time Series Econometrics. An adoption guide for R users: it maps the packages you already load —
vars,svars,lpirfs,BVAR,urca,rugarch,midasr,plm,quantreg,strucchange, and friends — to tsecon functions, and says plainly where tsecon has no equivalent yet. Every Python block runs against the current library.
R's time-series econometrics is spread across dozens of specialized packages, each with its own conventions, and much of it is unmaintained. tsecon's pitch to an R user is consolidation: one installed library, one calling grammar, one HAC implementation shared across every estimator, and a compiled core that turns the overnight Monte Carlo into a coffee-break one. This page is the translation layer.
What changes when you cross over¶
Four habits to reset:
-
No formulas, no
data.frame, no model objects. R leans on the formula interface (y ~ x1 + x2) and returns rich S3/S4 objects you inspect withsummary(),coef(),irf(). tsecon takes NumPy arrays and returns plaindicts and arrays. You indexfit["params"], there is nosummary()method, and column order in a matrix carries the meaning R attaches to variable names. -
Matrices are
T x k(time down the rows). A VAR, a cointegration test, a connectedness table — all take aT x karray with observations in rows and variables in columns, matching howvarsandurcaexpect their input. Panel estimators instead take a list of per-unit arrays (see below), which maps cleanly onto R's split-by-ididiom. -
se_type=replaces the vcov zoo. Instead ofsandwich::vcovHC,NeweyWest,vcovSCC, and per-package robust options, every regression estimator takes a uniformse_type=argument ("nonrobust","hc0"–"hc3","hac"; panels add"cluster"and"driscoll_kraay"). One implementation, stamped into the result. -
Reproducible RNG lives in the arguments. Where R uses a global
set.seed(), tsecon's stochastic routines take an explicitseed=and run a parallel Philox stream, so results are bit-reproducible at any thread count.
The mapping tables¶
"Roadmap" marks a capability tsecon does not ship today. Everything else is callable now.
VARs and structural analysis — vars, svars¶
| R | tsecon | Notes |
|---|---|---|
vars::VAR(data, p, type="const") |
var_fit(data, lags=p, trend="c") |
data is T x k. type="none"/"trend" → trend="n"/"t". |
vars::irf(v, n.ahead=h, ortho=TRUE) |
var_irf(data, lags, horizon=h, orth=True) |
Nested list [h][response][shock]. |
vars::irf(..., cumulative=TRUE) |
var_irf(..., cumulative=True) |
Running sums. |
vars::fevd(v, n.ahead=h) |
var_fevd(data, lags, horizon=h) |
[variable][horizon][shock]; sums to 1 across shocks. |
vars::causality(v, cause=) |
var_granger(data, caused, causing, lags) |
F-test. Pass integer column indices. |
predict(v, n.ahead=h) |
var_forecast(data, lags, steps=h, alpha=0.05) |
{"point", "lower", "upper"}. |
svars::id.chol(v) |
var_irf(..., orth=True) |
Recursive/Cholesky = column order of data. |
VARsignR, svars sign restrictions |
sign_restricted_svar(data, restrictions, ...) |
Sign-restricted Bayesian SVAR + identified-set bands. |
svars::id.dc, id.ngml (independence/heteroskedasticity ID) |
— | Statistical identification: roadmap. |
svars long-run / Blanchard-Quah |
— | Long-run restrictions: roadmap. |
Local projections — lpirfs¶
lpirfs is the standard R local-projection package; tsecon covers its main
entry points.
| R | tsecon | Notes |
|---|---|---|
lpirfs::lp_lin(..., shock_type) |
lp(y, shock, horizons, se="lag_augmented") |
Lag-augmented inference by default (Montiel Olea–Plagborg-Møller 2021). |
lpirfs::lp_lin_iv(...) |
lp_iv(y, impulse, instrument, horizons) |
Reports a first-stage F. |
lpirfs::lp_nl(...) (state-dependent) |
lp_state(y, shock, state_indicator, ...) |
Ramey-Zubairy (2018) per-regime IRFs. |
lpirfs::lp_lin_panel(...) |
panel_lp(outcome, shock, ...) |
Panel LP with fixed effects; Driscoll-Kraay SEs. |
Smooth/penalized LP — no lpirfs support |
smooth_lp(y, shock, horizons, lam="cv") |
Barnichon-Brownlees (2019) penalized-B-spline IRF, estimated jointly across horizons; cross-validates lam. tsecon-native. |
Bayesian VARs — BVAR, bvartools¶
| R | tsecon | Notes |
|---|---|---|
BVAR::bvar(data, lags, priors=) |
bvar_fit(data, lags, lambda0, lambda1, lambda3, delta) |
Minnesota-NIW conjugate posterior + log marginal likelihood. |
irf(bv, horizon=h) posterior draws |
bvar_irf_draws(data, lags, horizon, n_draws, seed) |
4-D list [draw][h][variable][shock]; take quantiles for bands. |
coda/rstan R-hat, ESS |
mcmc_diagnostics(chains) |
Rank-normalized split R-hat and bulk/tail ESS (ArviZ-exact). |
| Hierarchical / SSVS / hyperparameter priors | — | Only the conjugate Minnesota-NIW prior ships; other priors: roadmap. |
Cointegration and unit roots — urca, tseries¶
| R | tsecon | Notes |
|---|---|---|
urca::ur.df(y, type="drift") |
adf(y, regression="c") |
Or tseries::adf.test. Dict return with MacKinnon p-value. |
urca::ur.kpss(y) |
kpss(y, regression="c") |
Null is stationarity. |
urca::ca.jo(data, type="trace", K=) |
johansen(data, k_ar_diff=K-1) |
Trace + max-eig stats and selected ranks. |
urca::cajorls, vars::vec2var |
vecm(data, k_ar_diff, coint_rank) |
ML VECM: alpha, beta, gamma, sigma_u, llf. |
tseries::Box.test(y, type="Ljung-Box") |
ljung_box(y, nlags) |
Box-Pierce also returned. |
tseries::jarque.bera.test(y) |
jarque_bera(y) |
|
FinTS::ArchTest(y) |
arch_lm(y, nlags) |
Engle's ARCH-LM. |
ur.df + ur.kpss read together |
check_stationarity(y) |
The ADF+KPSS confirmatory-quadrant workflow with a differencing recommendation. |
(a whole battery of ur.df/Box.test/ArchTest/Fstats by hand) |
check_series(y) |
One-call diagnostic battery returning ordered model recommendations (also runs Johansen + VAR lag search on 2-D input). A tsecon convenience, not a 1:1 port. |
urca::ca.po (Phillips-Ouliaris), ur.pp |
— | Phillips-Perron / Phillips-Ouliaris: roadmap. |
urca::ca.jo (Engle-Granger via po.test) |
— | Engle-Granger two-step: roadmap; use johansen. |
Structural breaks and specification tests — strucchange, lmtest¶
| R | tsecon | Notes |
|---|---|---|
strucchange::breakpoints(y ~ x) |
bai_perron(y, x, max_breaks=, trim=) |
Bai-Perron multiple breaks: global DP partition, sequential supF(l+1|l) at 5%, per-regime OLS, Bai (1997) break-date CIs. x is T x q with all coefficients switching (include the constant). |
strucchange::Fstats, sctest(type="supF") |
sup_f_test(y, x, trim=) |
Andrews-Quandt sup-F unknown-break test; Hansen (1997) p-value and the full f_path. |
Chow test (strucchange::sctest(type="Chow")) |
chow_test(y, x, split) |
F-test at a known 0-indexed split. |
strucchange::efp(type="OLS-CUSUM") + sctest |
cusum_test(y, x) |
Brown-Durbin-Evans CUSUM path with 5% bounds. |
lmtest::resettest |
reset_test(y, x, max_power=) |
Ramsey RESET functional-form F-test. |
lmtest::bptest, skedastic::white |
heteroskedasticity_test(y, x, test="breusch_pagan"/"white") |
Breusch-Pagan / White; x is T x k with a constant. |
Univariate models and volatility — forecast, rugarch, rmgarch, MSwM¶
| R | tsecon | Notes |
|---|---|---|
forecast::Arima(y, order=c(p,d,q)) |
arima_fit(y, p, d, q, constant=True) |
Exact-MLE. |
forecast::auto.arima(y) |
— | Automatic order selection: roadmap (compare AIC/BIC from arima_fit by hand). |
forecast::thetaf(y, h) |
theta_forecast(y, steps=h, period=) |
The Theta method. |
forecast::accuracy(f, y) |
accuracy(actual, forecast, insample=, period=) |
ME/RMSE/MAE/MAPE/sMAPE/MASE/RMSSE. |
forecast::dm.test(e1, e2) |
dm_test(e1, e2, h=1, loss="squared") |
HLN small-sample correction. |
rugarch::ugarchfit(spec, y) |
garch_fit(y, vol="garch"/"egarch", p, o, q, dist=) |
GJR via o=. se_robust = Bollerslev-Wooldridge. |
rmgarch::dccfit(...) |
dcc_garch(returns) |
Engle (2002) DCC; returns is T x k. |
ccgarch, constant-correlation |
ccc_garch(returns) |
Bollerslev (1990) CCC. |
GAS::UniGASFit(...) |
gas_volatility(y, density="gaussian"/"student_t") |
Creal-Koopman-Lucas score-driven volatility. |
MSwM::msmFit, MSGARCH |
markov_switching_ar(y, k_regimes, order, switching_variance=) |
Hamilton EM; regimes, transition, durations. |
Mixed frequency and nowcasting — midasr, nowcasting¶
| R | tsecon | Notes |
|---|---|---|
midasr::midas_r(y ~ ..., nbeta/nealmon) |
weighted_midas(y, hf_lags, scheme="beta"/"exp_almon") |
NLS-estimated restricted weights; hf_lags is nobs x K. |
midasr::midas_u / U-MIDAS |
umidas(y, hf_lags, se_type="hac") |
Unrestricted mixed-frequency regression. |
midasr::nbeta, nealmon weight builders |
midas_weights(scheme, theta1, theta2, k) |
The weight vector alone. |
nowcasting::nowcast(...) (DFM) |
dfm_nowcast(data, n_factors, factor_order) |
Two-step DGR (2011); handles the ragged edge (NaNs). |
nowcasting news decomposition |
dfm_news(old_vintage, new_vintage, target_series, ...) |
Banbura-Modugno (2014) per-datapoint news contributions. |
Panel time series — plm, xtmg-style estimators¶
R's panel workflow (plm) uses a long pdata.frame. tsecon instead takes a
list of per-unit arrays: ys is a list of response vectors, xs a list of
T_i x k regressor matrices — which is what you get from split(df, df$id). The
alternative panel_fe/panel_lp layout is a dense N x T outcome with a
k x N x T regressor tensor.
| R | tsecon | Notes |
|---|---|---|
plm::pmg(..., model="mg") |
panel_mean_group(ys, xs, method="mg") |
Pesaran-Smith (1995) mean group: per-unit OLS, then average. |
plm::pmg(..., model="pmg") |
panel_pmg(ys, xs) |
Pooled Mean Group ARDL(1,1) (Pesaran-Shin-Smith 1999); pools the long-run coef by ML. |
xtmg/CCEMG (Pesaran 2006) |
panel_mean_group(ys, xs, method="cce") |
Common-correlated-effects mean group. |
plm::plm(..., model="within") |
panel_fe(outcome, regressors, se_type=) |
Fixed effects; outcome is N x T, regressors is k x N x T. |
plm + vcovSCC (Driscoll-Kraay) |
panel_fe(..., se_type="driscoll_kraay") |
Same SE, one argument. |
Panel VAR (panelvar) |
mean_group_var(entities, lags, horizon) |
Pesaran-Smith mean-group panel VAR over per-entity T_i x k matrices. |
Panel unit-root (IPS, LLC via plm::purtest) |
— | Roadmap. |
Realized volatility, connectedness, term structure¶
| R | tsecon | Notes |
|---|---|---|
highfrequency::rCov, rBPCov |
realized_measures(returns) |
RV, bipower variation, jump component (BNS 2004). |
HARModel::HARestimate |
har_rv(rv, variant="level"/"log"/"sqrt") |
HAR-RV (Corsi 2009) with HAC SEs. |
highfrequency::medRQ, rQuar |
realized_quarticity, tripower_quarticity |
Integrated-quarticity estimators. |
highfrequency::BNSjumptest |
bns_jump_test(returns) |
BNS ratio jump test. |
TTR/highfrequency range vol |
realized_range(high, low, method="parkinson"/"garman_klass") |
From OHLC bars. |
frequencyConnectedness, ConnectednessApproach |
connectedness(data, lags, horizon) |
Diebold-Yilmaz spillover table (GFEVD). |
YieldCurve::Nelson.Siegel |
nelson_siegel(maturities, yields, optimal_lambda=) |
Level/slope/curvature + fit. |
YieldCurve::Svensson |
svensson(maturities, yields, lambda1, lambda2) |
Four-factor, nests Nelson-Siegel. |
YieldCurve dynamic NS (Diebold-Li) |
dynamic_ns(panel, maturities, decay) |
Factor series + one-step forecast. |
GMM and penalized regression — gmm, glmnet¶
| R | tsecon | Notes |
|---|---|---|
gmm::gmm(g, x, ...) linear IV |
iv_gmm(x, z, y, method="2step"/"iterated", weight="robust"/"hac") |
Hansen (1982); over-identified fits report the Hansen J. |
gmm::gmm(...) nonlinear moments |
gmm_nonlinear(moments_fn, initial, weight=) |
Custom moment function as a Python callback. |
AER::ivreg(y ~ x | z) (2SLS) |
iv_gmm(x, z, y, method="2sls") |
The 2SLS special case. |
glmnet(x, y, alpha=1) (lasso) |
lasso(x, y, alpha) / lasso_path(x, y) |
lasso_path returns the full path with AIC/BIC selection. |
glmnet(x, y, alpha=a) (elastic net) |
elastic_net(x, y, alpha, l1_ratio) |
scikit-learn objective. |
glmnet(x, y, alpha=0) (ridge) |
ridge(x, y, alpha) |
Closed form. |
adaptive lasso (glmnet + weights) |
adaptive_lasso(x, y, alpha, gamma=) |
Zou (2006) oracle-property weights. |
Quantile regression and Growth-at-Risk — quantreg¶
| R | tsecon | Notes |
|---|---|---|
quantreg::rq(y ~ x, tau=) |
quantile_regression(y, x, taus=) |
IRLS check-loss with Powell kernel-sandwich SEs; include the constant column in x. |
| Quantile local projections — no standard R package | quantile_lp(y, shock, taus, horizons) |
Per-tau IRFs irf[tau][h] with Powell-sandwich SEs. tsecon-native. |
| Conditional-quantile Growth-at-Risk — no single-call R equivalent | growth_at_risk(y, conditions, horizon, taus) |
Adrian-Boyarchenko-Giannone (2019); current is the latest GaR read, with optional CFG monotone rearrangement. |
Filters and spectra — mFilter, neverhpfilter¶
| R | tsecon | Notes |
|---|---|---|
mFilter::hpfilter(y, freq) |
hp_filter(y, lamb, one_sided=) |
|
mFilter::bkfilter(y) |
bk_filter(y, low, high, k) |
|
mFilter::cffilter(y) |
cf_filter(y, low, high, drift) |
|
neverhpfilter::yth_filter |
hamilton_filter(y, h=8, p=4) |
Hamilton (2018) regression filter. |
spectrum(y), stats::spec.pgram |
periodogram(x), welch(x), coherence(x, y) |
Match SciPy's spectral estimators. |
Worked translations¶
Five you can run. The R call is shown as a comment.
urca::ca.jo → johansen + vecm¶
import numpy as np, tsecon
rng = np.random.default_rng(7)
trend = np.cumsum(rng.standard_normal(200)) # one shared stochastic trend
data = np.column_stack([trend + rng.standard_normal(200) for _ in range(3)])
jo = tsecon.johansen(data, k_ar_diff=1) # urca::ca.jo(data, type="trace")
print(np.round(jo["trace_stat"], 2), jo["rank_trace_5pct"])
vm = tsecon.vecm(data, k_ar_diff=1, coint_rank=1) # cajorls / vec2var
print(np.round(np.asarray(vm["beta"]).ravel(), 3)) # the cointegrating vector
BVAR::bvar → bvar_fit + bvar_irf_draws¶
import numpy as np, tsecon
rng = np.random.default_rng(5)
data = rng.standard_normal((200, 3))
bv = tsecon.bvar_fit(data, lags=2, lambda1=0.2) # BVAR::bvar(data, lags=2)
draws = tsecon.bvar_irf_draws(data, lags=2, horizon=12,
n_draws=500, seed=1) # [draw, h, var, shock]
med = np.median(np.asarray(draws), axis=0) # posterior-median IRF surface
print(round(bv["log_marginal_likelihood"], 2), med.shape)
rmgarch::dccfit → dcc_garch¶
import numpy as np, tsecon
def garch_sim(seed, T=1000): # a clustered return series
rng = np.random.default_rng(seed)
e = rng.standard_normal(T); h = np.empty(T); r = np.empty(T)
h[0] = 0.5; r[0] = np.sqrt(h[0]) * e[0]
for t in range(1, T):
h[t] = 0.05 + 0.08 * r[t-1]**2 + 0.90 * h[t-1]
r[t] = np.sqrt(h[t]) * e[t]
return r
ret = np.column_stack([garch_sim(s) for s in (6, 7, 8)])
dcc = tsecon.dcc_garch(ret) # rmgarch::dccfit(spec, ret)
print(round(dcc["a"], 4), round(dcc["b"], 4))
midasr::midas_r → weighted_midas¶
import numpy as np, tsecon
rng = np.random.default_rng(8)
hf = rng.standard_normal((120, 3)) # three high-frequency lags
y = hf @ np.array([0.6, 0.3, 0.1]) + rng.standard_normal(120)
wm = tsecon.weighted_midas(y, hf, scheme="beta") # midasr::midas_r(y ~ ..., nbeta)
print(round(wm["slope"], 3), round(wm["rsquared"], 3))
plm::pmg → panel_pmg (and mean group)¶
import numpy as np, tsecon
rng = np.random.default_rng(9)
ys = [rng.standard_normal(40) for _ in range(15)] # split(df, df$id) -> per-unit
xs = [rng.standard_normal((40, 2)) for _ in range(15)]
pmg = tsecon.panel_pmg(ys, xs) # plm::pmg(..., model="pmg")
mg = tsecon.panel_mean_group(ys, xs, method="mg") # plm::pmg(..., model="mg")
print(np.round(pmg["theta"], 3), np.round(mg["coef"], 3))
What R has that tsecon does not (yet)¶
R's long tail is deep; several widely used capabilities are roadmap:
auto.arima-style automatic order selection (comparearima_fitICs by hand).- Phillips-Perron / Phillips-Ouliaris unit-root and Engle-Granger cointegration tests.
- Statistical SVAR identification (
svars::id.dc/id.ngml) and long-run / Blanchard-Quah restrictions. - Non-conjugate BVAR priors (SSVS, hierarchical, stochastic volatility).
- Panel unit-root tests (IPS, Levin-Lin-Chu) and the fuller
panelvartoolkit. - STL / seasonal decomposition and TBATS/Prophet-style seasonal forecasters.
- Threshold models (SETAR/STAR via
tsDyn); tsecon offersmarkov_switching_arandlp_statefor nonlinearity.
Where tsecon repays the switch is speed and coherence: one library instead of a
dozen, a single shared HAC/bootstrap core, reproducible parallel RNG, and the
modern macro-structural methods (lp, sign_restricted_svar, dfm_nowcast,
favar, connectedness) delivered under one calling grammar.
See also the statsmodels and Stata guides, and the cross-package Rosetta glossary.