Say which numbers are a replication and which are calibration inputs; make MPCs mean something - #3
Merged
Conversation
… make MPCs mean something **The validation section was reporting inputs as results.** Y=1, K=10, r=1.25% quarterly, total wealth 14 and B=1.04 were listed as "the steady state reproduces the paper's calibration targets". They are calibration *inputs*: they are imposed, and (Z, alpha, mu_p, tau, phi) are backed out to make them consistent. "Target 10, achieved 10" is a constant equalling itself. The real replication is the parameters solved for internally, which reproduce ABRS (2021) Table B.III to the last published digit — beta 0.9762739 vs 0.976, chi1 6.4164196 vs 6.416, Z 0.4677898 vs 0.468, alpha 0.3299492 vs 0.33, mu_p 1.0152284 vs 1.015, tau 0.3560606 vs 0.356. chi1 is the strongest of these: it is solved numerically from a 6.5 starting guess and lands on the published value. That table is now the headline, gated by a test, and the imposed quantities are labelled as imposed. Two related corrections. Market clearing was quoted at 3.2e-13, which is a solver *target*; goods-market clearing at 3.3e-08 is untargeted (it holds only by Walras' law) and is the honest measure — five orders looser. And the upstream regression targets (A, B, UCE) that this repo matches bit for bit are `sequence-jacobian` v1.0.0's own partial- equilibrium test at the solver's chi1 = 6.5 *guess*, so they validate the household code, not the calibration. **A published discrepancy that was not disclosed.** Table B.III gives phi = 2.073; this DAG's `union_ss` yields 1.7135, a 17% gap that does not reconcile under either definition of UCE. It looks like a reporting convention — phi is a pure normalisation making N=1 optimal, the wage Phillips residual is 7e-15 here, and nothing else depends on it — but it is unexplained, so it is written down and deliberately not asserted. **IRF magnitudes were claimed and cannot be.** The README said signs *and magnitudes* match the paper. ABRS (2021) publishes no figure plotting Y/C/I/pi against these shocks, so there is nothing to match magnitudes against. Signs and timing are gated; magnitudes are not claimed. **MPCs were being measured at a kink the grid does not resolve.** Just over half the population sits exactly at the liquid borrowing constraint, and the one-grid-step MPC is the policy slope right at that kink: it rises monotonically from 0.076 at nB=50 to 0.100 at nB=150 with no plateau, so the published number was a grid artefact. MPCs are now defined out of a windfall of stated economic size (default 25% of mean quarterly post-tax labour income, roughly the 2001/2008 US rebates the empirical literature measures), which is stable across grids. The legacy one-step difference is kept for the grid-sensitivity test and documented as not quotable. Related: the hand-to-mouth share is an atom, not a threshold — 51.2% hold exactly zero liquid assets, so the count is insensitive to the cutoff over [0, 0.028], and `hand_to_mouth_breakdown` now shows that rather than leaving the cutoff looking load-bearing. **Units trap, stated once.** `size` is a level change for all three shock kinds. That reads naturally for the policy rate and for G (Y_ss = 1, so a level change in G is a share of GDP), and is a trap for productivity: Z_ss = 0.468, so size=0.01 is a **2.14%** TFP improvement, not 1%. `SHOCK_UNITS` states this and every result carries `shock_pct_of_ss` so the reading is never left to the caller. **A latent cache bug.** The Jacobian cache keyed on `id(ss)` without holding a reference, so a garbage-collected steady state could have its address reused by a different one, which would then be handed the first one's Jacobian. It keeps the reference now. `PRODUCTION_CALIBRATION` was also passed by reference into a solver that writes its solved unknowns back, letting the first solve seed every later one; it is copied. Also: `budget_residual` is an arithmetic identity — `tax_revenue` is defined as exactly that expression rearranged — so the test asserting it is ~0 can catch a refactoring slip and nothing else, and now says so. `sequence-jacobian` is pinned exactly and the numeric stack carries major-version ceilings, because the replication asserts published digits and a silent NumPy major bump must not be able to move them. 24 -> 43 test functions; 47 pass with `--runslow`, none removed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The validation section was reporting inputs as results. Y=1, K=10,
r=1.25% quarterly, total wealth 14 and B=1.04 were listed as "the steady
state reproduces the paper's calibration targets". They are calibration
inputs: they are imposed, and (Z, alpha, mu_p, tau, phi) are backed out
to make them consistent. "Target 10, achieved 10" is a constant equalling
itself.
The real replication is the parameters solved for internally, which
reproduce ABRS (2021) Table B.III to the last published digit — beta
0.9762739 vs 0.976, chi1 6.4164196 vs 6.416, Z 0.4677898 vs 0.468, alpha
0.3299492 vs 0.33, mu_p 1.0152284 vs 1.015, tau 0.3560606 vs 0.356. chi1
is the strongest of these: it is solved numerically from a 6.5 starting
guess and lands on the published value. That table is now the headline,
gated by a test, and the imposed quantities are labelled as imposed.
Two related corrections. Market clearing was quoted at 3.2e-13, which is
a solver target; goods-market clearing at 3.3e-08 is untargeted (it
holds only by Walras' law) and is the honest measure — five orders
looser. And the upstream regression targets (A, B, UCE) that this repo
matches bit for bit are
sequence-jacobianv1.0.0's own partial-equilibrium test at the solver's chi1 = 6.5 guess, so they validate the
household code, not the calibration.
A published discrepancy that was not disclosed. Table B.III gives
phi = 2.073; this DAG's
union_ssyields 1.7135, a 17% gap that does notreconcile under either definition of UCE. It looks like a reporting
convention — phi is a pure normalisation making N=1 optimal, the wage
Phillips residual is 7e-15 here, and nothing else depends on it — but it
is unexplained, so it is written down and deliberately not asserted.
IRF magnitudes were claimed and cannot be. The README said signs
and magnitudes match the paper. ABRS (2021) publishes no figure
plotting Y/C/I/pi against these shocks, so there is nothing to match
magnitudes against. Signs and timing are gated; magnitudes are not
claimed.
MPCs were being measured at a kink the grid does not resolve. Just
over half the population sits exactly at the liquid borrowing constraint,
and the one-grid-step MPC is the policy slope right at that kink: it
rises monotonically from 0.076 at nB=50 to 0.100 at nB=150 with no
plateau, so the published number was a grid artefact. MPCs are now
defined out of a windfall of stated economic size (default 25% of mean
quarterly post-tax labour income, roughly the 2001/2008 US rebates the
empirical literature measures), which is stable across grids. The legacy
one-step difference is kept for the grid-sensitivity test and documented
as not quotable. Related: the hand-to-mouth share is an atom, not a
threshold — 51.2% hold exactly zero liquid assets, so the count is
insensitive to the cutoff over [0, 0.028], and
hand_to_mouth_breakdownnow shows that rather than leaving the cutoff looking load-bearing.
Units trap, stated once.
sizeis a level change for all threeshock kinds. That reads naturally for the policy rate and for G (Y_ss = 1,
so a level change in G is a share of GDP), and is a trap for
productivity: Z_ss = 0.468, so size=0.01 is a 2.14% TFP improvement,
not 1%.
SHOCK_UNITSstates this and every result carriesshock_pct_of_ssso the reading is never left to the caller.A latent cache bug. The Jacobian cache keyed on
id(ss)withoutholding a reference, so a garbage-collected steady state could have its
address reused by a different one, which would then be handed the first
one's Jacobian. It keeps the reference now.
PRODUCTION_CALIBRATIONwasalso passed by reference into a solver that writes its solved unknowns
back, letting the first solve seed every later one; it is copied.
Also:
budget_residualis an arithmetic identity —tax_revenueisdefined as exactly that expression rearranged — so the test asserting it
is ~0 can catch a refactoring slip and nothing else, and now says so.
sequence-jacobianis pinned exactly and the numeric stack carriesmajor-version ceilings, because the replication asserts published digits
and a silent NumPy major bump must not be able to move them.
24 -> 43 test functions; 47 pass with
--runslow, none removed.Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
🤖 Generated with Claude Code