model 04 — Federal Reserve macroeconomic model · frb-us · US · hosted

Test US monetary and fiscal shocks.

Trace how a funds-rate or fiscal shock affects US output, inflation, and unemployment quarter by quarter using the April 2026 baseline.

how far to trust it

The baseline agreement is an identity; the shocks are the evidence.

Shocked paths match the Fed's own pyfrbus to 6.0×10−9, inside the gap between the Board's own two releases. The baseline tracking residual is not evidence: init_trac makes that solve an algebraic identity (table below).

Fidelity to the Fed's baseline is not the baseline being right. Against 2026 outturns the April 2026 LONGBASE tracks GDP growth, unemployment and the funds rate within ~0.3pp but misses core PCE inflation by −1.7pp (2.7% vs a 4.4% annualized outturn, 2026Q1) — a weekly outturn backtest that reports rather than gates, because the baseline is the Board's.

tracking invariant 5.6e−17 an identity, not evidence — see the table
shock vs pyfrbus 1.0.0 6.0e−9 100bp shock, 284 endos × 20 quarters; the pinned reference, CI gate 1e−6
shock vs pyfrbus 1.1.1 1.4e−8 the Board's April 2026 LONGBASE vintage used here
the Fed vs the Fed 1.3e−8 pyfrbus 1.1.1 against 1.0.0 — the yardstick

The last tile frames the other three. The Board's two releases ship a byte-identical model.xml and LONGBASE, differing only in how Newton reuses its LU factorisation, yet disagree by 1.3×10−8 — as much as this implementation disagrees with either. Agreement sits at the reference's own numerical noise, not at a chosen tolerance; all three residuals concentrate in the same near-zero expectational-gap series (wpsn, zgap05).

frb-us: residuals against the Fed’s pyfrbus, log scale Horizontal bar chart on a base-10 logarithmic axis of maximum absolute residuals; shorter is closer. The rows fall into three kinds. ours vs LONGBASE — tracking identity, not evidence: 5.6e-17 (tracking identity); pyfrbus 1.1.1 vs LONGBASE — tracking identity: 1.1e-08 (tracking identity); ours vs pyfrbus 1.0.0 (shock): 6.0e-09 (ours vs the Fed); ours vs pyfrbus 1.1.1 (shock): 1.4e-08 (ours vs the Fed); pyfrbus 1.1.1 vs 1.0.0 — the Fed’s own releases: 1.3e-08 (the Fed vs itself). The two tracking rows are an identity — init_trac defines the add-factors as minus the residuals at the input data, so re-solving reproduces the input for any input at all — and are shown for completeness, not as evidence. The framing comparison is the last row: the Federal Reserve's own two pyfrbus releases disagree with each other by as much as this implementation disagrees with either, so our agreement sits at the scale of the reference implementation's own numerical noise rather than at a chosen tolerance. 1e-18 1e-16 1e-14 1e-12 1e-10 1e-8 ours vs LONGBASE — tracking identity, not evidence 5.6e-17 pyfrbus 1.1.1 vs LONGBASE — tracking identity 1.1e-08 ours vs pyfrbus 1.0.0 (shock) 6.0e-09 ours vs pyfrbus 1.1.1 (shock) 1.4e-08 pyfrbus 1.1.1 vs 1.0.0 — the Fed’s own releases 1.3e-08 ours vs the Fed’s pyfrbus, under shock the Fed’s two releases vs each other tracking identity — round-off, not fidelity
Maximum absolute residuals, log scale — lower is closer. The top two bars are the tracking identity and are not a ranking: they compare two implementations' round-off, not their fidelity to the Fed's economics. Source: papers/frb-us validation tables.
Validation results against the Federal Reserve Board's own artefacts
testwhat it checksresult
Tracking invariant Re-solving the baseline reproduces LONGBASE, 284 endogenous variables over 2026Q1–2030Q4. 5.6e−17 against a 1e−8 gate — but an identity, not a comparison. init_trac sets each add-factor to minus that equation's residual at the input data, so the solve reproduces whatever it was tracked to, for any input: the model repository's test_tracking_invariant_holds_for_arbitrary_data passes at 6.7e−9 on a scrambled baseline with every accounting identity destroyed. Read the row below, not this one, as evidence.
Cross-validation The same 100bp rffintay_aerr shock run in both implementations, all 284 variables × 20 quarters. 6.0e−9 against pyfrbus 1.0.0 and 1.4e−8 against 1.1.1, where the two Board releases differ from each other by 1.3e−8.

Multipliers. Read these as plausibility bands, not as a test passed: the comparisons are not horizon-matched throughout, and Ramey's survey range pools estimates across horizons and monetary regimes.

frb-us fiscal multipliers (1% of GDP, sustained) against published ranges
QuantityOursPublishedReading
Gov. purchases, yr 1, inertial Taylor rule0.720.7–1.0 (Coenen et al. 2012); Ramey (JEP 2019): "a surprisingly narrow range of 0.6 to 1"inside range
Gov. purchases, yr 2, pegged funds rate0.90"roughly one" pegged; 1.1–1.2 with accommodationbelow the accommodation range
Personal tax cut, yrs 1–20.22 → 0.320.2–0.4; CBO central ≈0.3; yr-1 benchmark is a two-year figureinside range, horizons unmatched

Uncertainty engine. Seeded stochastic simulation jointly resamples the official residual vector, preserving contemporaneous dependence; model and LONGBASE packages carry SHA-256 provenance gates. Published probability results still need a reviewed simulation design, and model-consistent expectations remain unavailable.

CI does not just re-check a committed CSV: a dedicated job re-runs the Board's pyfrbus from source and gates against that fresh solution, and a weekly run repeats the suite across Python 3.10–3.12. The multiplier comparisons are refreshed manually. Full tables in VALIDATION.md and the working paper.

This is an independent implementation built from the Federal Reserve Board's published model equations and data. It is not produced, maintained, or endorsed by the Federal Reserve, and its results should not be presented as official Federal Reserve estimates.

evidence — a worked shock

Run the same 100bp shock, read it against the Board.

One command reproduces a 100bp funds-rate tightening under the inertial Taylor rule:

pe-macro frbus-shock --var rffintay_aerr --shock 1.0
ResponseOursPublished Fed reference
Funds rate, on impact+1.000pp+1.00pp by design — exact
Real GDP, trough−0.55%right sign, size and timing vs the Board's documented VAR-expectations properties
Unemployment, peak+0.26ppright sign and order, same source
Core inflation, trough−0.034ppright sign and order, same source
Output gap, trough−0.50pp~−0.4pp, read off 2014 FEDS Note charts — approximate by nature (limits)

The exact cross-check is numerical, not chart-reading: the same shock in the Board's own pyfrbus matches to 6.0×10−9.

limits

Known limitations.

Known limits of the frb-us implementation
limitdetail
VAR expectations only Model-consistent expectations are not implemented (mce= raises NotImplementedError), so forward guidance is out of scope.
No mcontrol Trajectory targeting is out of scope. stochsim_bands() does produce seeded bootstrap bands, but the hosted frbus_shock returns a single deterministic path.
Hosted, but only as raw shocks One lever, one shock size, a policy rule and a headline set of responses — not the full 284-variable model. Anything more means installing the package.
No PolicyEngine reform bridge Reforms enter as shocks, not statute: score_reform refuses model="frbus", so US reform scoring stops at pe-microsim's static answer.
Approximate published comparisons The 2014 FEDS Note responses are read off charts. Our −0.50pp output-gap trough against its ~−0.4pp reflects vintage and shock-design differences, not a claimed match.
Vintage The Board's April 2026 model.xml and LONGBASE. Later vintages not adopted.