The SC-MIDAS framework¶
SC-MIDAS (Staggered-Combination MIDAS) is a two-layer nowcasting recipe that turns a heterogeneous panel of monthly and quarterly indicators into a single best-estimate forecast for the quarterly target \(y_t\) (typically GDP growth) at several horizons.
The three building blocks¶
1. Indicator models¶
Each monthly indicator \(x^{(i)}\) is paired with the target through a direct-forecast MIDAS regression:
Optional outlier dummies \(\mathbf{d}_{t+h}\) enter at the target frequency. Estimation uses OLS for linear-in-parameter weighting schemes (Almon, U-MIDAS) and Levenberg-Marquardt non-linear least squares with closed-form analytic Jacobians for the rest (exponential Almon, Beta).
Each quarterly hard indicator \(z^{(k)}\) uses a plain OLS counterpart:
In both cases, the pipeline stores one model per horizon \(h\) in
MidasCombo.midas_models_[var][h] and MidasCombo.ols_models_[var][h].
2. Layer 1 — soft combination¶
The indicator fits feed into one or more first-layer
ComboSpec nodes whose
combination weights are derived from rolling-window residuals. Three
inverse-error variants are available (mean absolute error, mean squared
error, root mean squared error) plus equal-weight average.
Each source uses its own prior residuals. Lower errors receive more weight;
window selects how many residuals to use and discount_rate controls the
influence of older errors. With a finite window, sources without enough
residuals receive an equal share. See Weighting schemes
for the calculation and observation-count rules.
minimum_sample_size excludes sources with too few finite fitted observations
before weighting. The default is 10.
3. Layer 2 — soft × hard merging¶
The second layer pools the Layer-1 combo with a quarterly hard
regressor via constrained regression
(fit_regression_weights) with
method='constrained_ls':
ComboSpec(method='regression', window=None) uses an expanding window
over the full sample, which is the natural Layer-2 set-up. When there
are exactly two sources (soft combo + hard) this reduces to the
EViews-style convex combination \(w \in [0, 1]\).
End-to-end recipe¶
from nowcast_midas import MidasCombo, MidasSpec, OLSSpec, ComboSpec
midas_monthly_1 = MidasSpec("monthly_1", method="almon", n_lags=5)
midas_monthly_2 = MidasSpec("monthly_2", method="almon", n_lags=5)
midas_monthly_3 = MidasSpec("monthly_3", method="unrestricted", n_lags=3)
ols_quarterly_1 = OLSSpec("quarterly_1", n_lags=1)
soft = ComboSpec(
"soft",
sources=[midas_monthly_1, midas_monthly_2, midas_monthly_3],
method="mse",
window=8,
discount_rate=0.95,
)
final = ComboSpec(
"final", sources=[soft, ols_quarterly_1], method="regression", window=None
)
model = MidasCombo(combo_specs=final, horizons=3)
model.fit(target=target_df, regressors=regressors_df)
forecasts = model.forecast()
Relation to the EViews reference¶
Single-vintage numerical equivalence is a reference-validation target. The remaining gap is the recursive OOS estimation loop (re-fitting at every historical vintage), which is a workflow-level feature outside the scope of the estimation API.