sargent_surico#

  • Series: lecture-python.myst

  • File: lectures/sargent_surico.md

  • Audit date: 2026-08-26

  • Corpus snapshot: e25fdf2345

  • Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)

  • Overall score: 7.2 / 10

  • Priority: HIGH

Score breakdown#

Category

Score

One-line note

Writing

6.5/10

qe-writing-005 ×3; qe-writing-002 ×3; qe-writing-008 ×2, +1 more.

Math

5.5/10

qe-math-002 ×13.

Code

4.5/10

qe-code-002 ×147; qe-code-001 ×6; qe-code-004 ×8, +1 more.

JAX

out of scope

JAX rules target lecture-jax.

Figures

4/10

qe-fig-003 ×16; qe-fig-005 ×6; qe-fig-001 ×12, +1 more.

References

10/10

no mechanical violations detected.

Links

10/10

no mechanical violations detected.

Admonitions

10/10

no mechanical violations detected.

Issues#

Critical#

None found.

High severity#

  • [qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 6. Lines: 87, 88, 112, 625, 967, 1702. Example: 87 is warnings.filterwarnings('ignore') at module scope, which silences everything for the remaining 2000 lines - and this lecture leans harder on numerical warnings than most: ordqz (636), solve_discrete_lyapunov, svd (647, 660), two optimize.minimize calls (1702-1705, and the earlier mode search), a hand-written Kalman filter, and NUTS. Its own headline finding is that sampler diagnostics led to a second and better posterior mode (1897-1899), so globally suppressing the other diagnostic channel is at odds with the lecture’s method. 1702-1706 compounds it: the bimodality claim rests on a Powell run followed by an L-BFGS-B run whose res_a.success is never inspected, and the printed comparison at 1708-1713 reports the log posteriors as if both had converged. 88-90 sets figure.figsize, axes.grid and grid.alpha in plt.rcParams, so all sixteen figures are 10x6 whether or not that suits them (this is what the three qe-fig-001 “style override” hits at 88-90 are). 112-120 implements a filter that is not the one displayed at 98-100: the equation truncates at \(\pm n\) with the explicit normalizing constant \(a\), while lucas_filter weights every observation and renormalizes, so \(a\) and \(n\) appear in the lecture’s first equation and are used by nothing - and the loop rebuilds a length-\(T\) weight vector \(T\) times where one Toeplitz construction would do. 625 and 695 give one matrix two names in adjacent cells - gensys(g0, g1, psi, pi, ...) takes it as pi while toy_nk returns it as pie, presumably to dodge np.pi. And exponentiation is written s ** 2 at all seven sites (967, 972, 976 and four more) where the rule asks for a**b; 660 uses SMALL * n as a tolerance three lines after using bare SMALL at 648, with no note on why the two differ.

  • [qe-code-002] — Use Unicode symbols for Greek letters in code. Count: 147. Lines: 112, 118, 321, 323, 324, 330, 331, 333, 368, 374, …. Example: spelled-out beta.

  • [qe-code-004] — Use quantecon Timer context manager. Count: 8. Lines: 1086, 1088, 1548, 1552, 1554, 1557, 1627, 1630. Example: time.time(.

  • [qe-fig-001] — Do not set figure size unless necessary. Count: 12. Lines: 88, 89, 90, 258, 290, 418, 1096, 1135, 1178, 1731, …. Example: style override.

  • [qe-fig-003] — No matplotlib embedded titles. Count: 16. Lines: 265, 267, 300, 303, 426, 428, 1102, 1103, 1140, 1143, …. Example: .set_title.

  • [qe-fig-005] — Descriptive figure names for cross-referencing. Count: 6. Lines: 254, 404, 1095, 1132, 1787, 1860. Example: code-cell figure without mystnb figure metadata.

  • [qe-math-002] — Use \top for transpose notation. Count: 13. Lines: 181, 182, 183, 184, 190, 202, 204, 782, 929. Example: apostrophe transpose A'.

Medium severity#

  • [qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 3. Lines: 1215, 1911, 1931. Example: the lecture ends twice. “What to take away” (1886-1909) and “Concluding remarks” (1911-1943) make the same four points in the same order: the obstacle is the solver and not the statistics (1888 against 1935), a fixed point that uses only linear algebra buys exact gradients (1891-1893 against 1937), cheap chains and their diagnostics found a second mode (1895-1899 against 1939-1941), and the caveat about efficiency being posterior-specific (1908-1909 against 1937). Twenty-five lines apart, that is a whole section restated. 1215 announces three deliverables in one sentence (“Here is where the slopes bottom out, a slice through the grid at the posterior mean of \(\phi_x\), and the fraction of the grid the stationarity test removes”) and then delivers all three as printed text. 1931 is 37 words whose subject and verb are eleven words apart: “driving it to the near-zero values that the post-1984 data display takes a money growth rule far more anti-inflationary than the one those same data select”.

  • [qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 3. Lines: 1334, 1615, 1716. Example: three bold spans are emphasis rather than definition: sorts at 1334 (“the standard solver … sorts eigenvalues”), four chains at 1615, and higher at 1716 (“the low-indexation one has the higher posterior density”) - the last being the lecture’s key claim, so it is the one place the emphasis matters and it is set in the definition marker. The file’s italics are all correct emphasis (not 56, only 60, sum 125, first/second 575/581, local 1036 and 1720, negative 1209, ordered 1333, between 1821, identity 1923, lower 1941) and its other six bold spans are correct definitions (effective sample size 1282, Hamiltonian Monte Carlo 1315, No-U-Turn sampler 1323, dense mass matrix 1609, Intrinsic persistence 1676, Inherited persistence 1679), so the three above are the whole finding.

  • [qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 4. Lines: 506, 870, 1226, 1687. Example: the four results the lecture is proudest of are all delivered as printed numbers. “\(\tau\) is not identified” (506-524) is the cleanest correction in the file and is verified by four lines of output at 870-874 showing \(h_\pi\) unchanged as \((\tau, \sigma_e)\) scale together - a flat ridge in the log posterior that one panel would show as a horizontal line, and 516-520 makes a further quantitative claim about the paper’s Table 2 posterior for \(\tau\) being prior-driven (“the data want \(\sigma_e/\tau \approx 0.31\), while the inverse gamma prior on \(\sigma_e\) has mean \(0.3\)”) that prior and posterior densities on one axis would settle. The verification of {prf:ref}`ss_prop` at 877-884 prints five random draws in which \(h_\pi\) is one to twelve decimals while \(h_R\) “moves all over the place” (895) - a scatter of \(h_R(0)\) against \(h_\pi(0)\) over a few hundred such draws collapses to a vertical line at one, which is the asymmetry the concluding remarks build to at 1923-1927. “Two modes” (1687-1764) establishes the lecture’s most surprising result from two optimizer runs and a nine-number table (1708-1713), where 1673-1682 has already named the two parameters that separate the stories - a contour of the log posterior in \((\alpha_\pi, \rho_e)\), or a slice along the segment joining the two modes, would show two peaks and how deep the valley between them is. And 1217-1228 prints a nine-row slice through the \((\phi_\pi, \phi_x)\) surface that the figure at 1196-1200 already draws.

  • [qe-writing-008] — Remove excessive whitespace between words. Count: 2. Lines: 585. Example: 2 spaces.

Low severity#

  • [qe-code-005] — Use quantecon timeit for benchmarking. Count: 1. Lines: 1548. Example: hand-rolled benchmark loop — use qe.timeit.

  • [qe-fig-004] — Caption formatting conventions. Count: 1. Lines: 1724. Example: caption of 10 words.

Strengths#

  • The lecture states three specific problems with the published paper’s statement of its own model and then checks all three numerically in one cell: that \(\tau\) enters only through \(\sigma_e/\tau\) (506-524, verified at 871-874), that the first unit slope is an identity when \(\phi_\pi = \phi_x = 0\) (526-585, verified on five random parameter draws at 877-884), and that the paper’s posterior for \(\alpha_x\) terminating at exactly 0.5000 is a constraint rather than a determinacy boundary (587-595, verified on both sides at 886-888). 891-893 then says which held.

  • {prf:proposition} ss_prop at 551-561 is stated as an exact result (“\(h_{\pi,\Delta m}(0) = 1\) exactly, whatever the values of the other parameters”) with a four-step proof at 563-571 that turns on one observation - every term of the money demand equation other than \(\pi_t + z_t\) is a first difference, and \(1 - e^{-i\omega}\) vanishes at \(\omega = 0\) - and 575-585 then draws the consequence the paper does not: Lucas’s two illustrations are not on the same footing, because the second has no such backing.

  • The gensys solver is validated against a case with a closed-form answer before it is trusted: 679-689 writes the textbook three-equation new Keynesian model whose equilibrium solves a two-by-two system and is unique iff \(\phi_\pi > 1\), and 705-716 checks both the determinacy verdict at \(\phi_\pi \in \{0.5, 1.5, 3.0\}\) and the coefficient values against the analytic solution.

  • The policy-experiment figure (1176-1200) carries five things at once and the prose reads all five: filled contours of both slopes over the \((\phi_\pi, \phi_x)\) grid, the \(h = 1\) contour in red, the \(h = 0.2\) contour in white, the non-stationary region shaded grey, and the posterior draws scattered on top - so 1205-1213 can point out that the draw cloud sits where both slopes are near one, and that the red contour passes exactly through the origin as {prf:ref}`ss_prop` requires.

  • 897-909 reports the strip of the paper’s own Figure 6 grid on which no covariance stationary equilibrium exists, says it is far from the estimated rule so the paper’s conclusions are safe, and then states the point precisely anyway: “an \(h(0)\) reported over it would be a number computed from a spectral density that does not exist”.

  • The Hamiltonian Monte Carlo section diagnoses its own obstacle rather than working around it: 1313-1341 identifies eigenvalue sorting as the non-differentiable step, 1343-1476 replaces it with a fixed point that uses only linear algebra, 1535-1544 checks the resulting gradient against a central difference parameter by parameter, and 1547-1566 measures that a full 18-partial gradient costs about one likelihood evaluation - with grad_ll warmed up at 1536 before the timing loop, so the number is not a compilation time.

  • The bimodality is found the honest way and then followed through: weak mixing in three parameters (1655-1665) is turned into a hypothesis about which two economic stories the data cannot separate (1673-1682), the optimizer is restarted from the opposite corner to settle it (1697-1713), and 1765-1813 then asks whether the second mode changes the paper’s conclusions - it does not, which 1943 reports as good news for the paper that only the better sampler could establish.

  • The sampler comparison refuses the flattering statistic: 1819-1823 explains why effective sample sizes for the three mode-separating parameters are not comparable across samplers and excludes them, 1835-1848 then reports median ESS per draw and per second, and 1851-1858 says which of the two is the ratio that matters and why.

  • Installation and imports are staged deliberately - the install cell is at the top with hide-output and 32-34 says which packages are for which section, then arviz at 1285 and jax/numpyro at 1388-1393 are imported where the HMC section begins, so a reader stopping at line 1268 never needs them.