model 03 — 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.
Parse, add-factor, solve by Newton.
The five stages of the frb-us pipeline, from the Board's published artefacts to an impulse response. Each step's formal structure follows its narrative; equations render locally (no CDN). The full derivations are in the working paper.
Parse the Board's model file
The published artefacts
The Federal Reserve Board publishes FRB/US whole: the equation system as model.xml, the LONGBASE historical and projection database, the documentation, and a reference Python solver, pyfrbus — all in the public domain.
One source of truth
The parse stage reads model.xml directly: variables, equations, per-equation coefficients, and the endogenous / exogenous classification for the VAR-expectations ("standard") equation set. Nothing is re-typed or re-specified — the XML file is the single source of truth for the model's semantics. That yields 284 endogenous variables and their equations, classified into behavioural and identity blocks exactly as the Board's file declares them.
Residual form
Each equation is normalised — EViews lag and difference notation rewritten, coefficient references substituted by their published values — flipped to residual form \(F_i(\cdot) = 0\), and augmented with its additive shock term (_aerr) and a tracking residual (_trac), so each equation solves \(F_i + \mathrm{aerr}_i + \mathrm{trac}_i = 0\).
Load LONGBASE, then add-factor
The baseline database
The load stage brings LONGBASE.TXT — the April 2026 vintage — into a pandas frame on a quarterly PeriodIndex. This is the Board's own historical and projection database, and it conditions everything that follows: every simulation is read as a deviation from this baseline.
Tracking residuals (init_trac)
init_trac sets each equation's tracking residual so that solving the model reproduces the database exactly. This is the Fed's own device, used the Fed's own way — the direct analogue of the OBR emulator's anchoring. Shocks are then imposed on top of the add-factored baseline.
Solve by damped Newton
Period by period
Under VAR expectations every expectations term depends only on current and lagged observables, so the model is simultaneous within each quarter but recursive across quarters. The solver therefore works period by period, starting each quarter from the previous quarter's solution.
Analytic sparse Jacobian
Each quarter, a damped Newton iteration solves the full simultaneous system with an analytic sparse Jacobian — differentiated symbolically with sympy, factorised with scipy.sparse.linalg.splu. Damping backtracks the step only to stay inside the domain of definition (no logs of non-positive arguments, no NaNs). Defaults are \(\mathrm{xtol} = 10^{-8}\), \(\mathrm{rtol} = 5\times 10^{-4}\).
One block, not many
The reference implementation decomposes each period into recursive and simultaneous blocks; this one solves the whole period at once. Both approaches solve the same \(F(x) = 0\), which is why the two agree to solver tolerance rather than to some negotiated threshold — see how far to trust it.
Policy rules
A modular funds rate
Monetary policy is modular: exogenous 0/1 switches in the model file select which rule sets the funds rate. Three are exposed through frbus_shock: inertial_taylor (the default, the LONGBASE rule and the one the validation numbers use), taylor, and fixed_funds_rate, which holds the funds rate on its baseline path so there is no endogenous monetary offset.
The rule choice is the exercise
The choice is usually the economic point of the exercise. Run the same government-purchases shock (1% of GDP) under both settings and the multiplier moves from 0.72 in year one under the inertial Taylor rule to 0.99 in year two with the funds rate fixed — and the price-level response is larger still without the monetary offset. The overview places both inside the published cross-model ranges.
Each rule reads its own error term
Each policy rule reads its own add-error, so rffintay_aerr works only under inertial_taylor; asking for it under taylor is rejected with a pointer to rfftay_aerr rather than silently returning all-zero responses — one of the two traps the code page walks through before you shock anything.
Shock and compare
Shocks are error-term additions
A shock is an addition to an equation's error term — rffintay_aerr for the policy rule, for instance. Solve shocked and baseline paths over the same window and read the difference. Shock sizes are per-lever and not interchangeable — percentage points for the policy-rate error, log points of quarterly growth for the spending levers; the code page spells out the units trap.
What comes out
The headline 100bp tightening lands where the Board's documentation says it should: the funds rate up 1.000pp on impact, real GDP bottoming at −0.55% in 2027Q4, unemployment peaking +0.26pp, core inflation down 0.034pp at its trough. The same four numbers are the simulation-properties row of the validation tables.
What stays out of scope
The pipeline covers the VAR-expectations model only: the model-consistent-expectations variants, forward guidance, and the reference implementation's mcontrol trajectory-targeting routine are not implemented, and there is no bridge from a PolicyEngine reform to model variables — see the known limits.