tax_smoothing_1#
Series: lecture-dp
File:
lectures/tax_smoothing_1.mdAudit date: 2026-08-26
Corpus snapshot:
c30490a2f4Categories audited: writing, math, code, figures, references, links (JAX out of scope)
Overall score: 6.3 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
4.5/10 |
|
Math |
4/10 |
|
Code |
7/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
6/10 |
|
References |
7.5/10 |
|
Links |
9/10 |
|
Admonitions |
N/A |
no admonitions, exercises or solutions. |
Issues#
Critical#
None found.
High severity#
[qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 5. Lines: 373, 300, 479, 291, 376. Example: 373, 386 and 499 bind
Tto the simulation horizon, in a lecture whose central variable is \(T_t\), total tax collections (184, 203, 256, 262, 341, 354) - the collision is direct andts_lengthorn_periodsis available. 300-301 name the two row blocks of the state-transition matrixA_tandA_b(‘top’ and ‘bottom’), which read as \(A_t\) and \(A_b\), i.e. time- or state-indexed matrices, in the one lecture in the series that is entirely about matrices indexed by a Markov state. 479 ends a statement with a semicolon to suppress notebook output,lqm.stationary_values();(E703). 291-292 leaves a stray trailing comma inside the outer bracket,[Gbar, ρ],]). And 376, 389 and 503 wrap the x-axis in a redundantlist(...):plt.plot(list(range(T+1)), ...)- matplotlib accepts the range object. Note that the aligned spacing at 291 ([[1, 0],) is the matrix-notation exemption and should be left alone.[qe-fig-006] — Lowercase axis labels. Count: 6. Lines: 377, 378, 390, 391, 504, 505. Example: axis label
Time.[qe-math-002] — Use \top for transpose notation. Count: 11. Lines: 262. Example: apostrophe transpose
x_t'.[qe-ref-001] — Use correct citation style. Count: 9. Lines: 41, 43, 61, 63, 82, 123, 132, 175. Example:
{cite}in narrative flow: ‘by{cite}’.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 5. Lines: 43, 60, 95, 404, 447. Example: five sentences are broken as written. 43: ‘
{cite}`Barro1979`m is about a government that borrows and lends’ - a stray ‘m’. 41 and 61 both end ‘{cite}`barro2003religion`).’ with a closing parenthesis that was never opened. 153: ‘A{doc}`sequel to this lecture <tax_smoothing_2>`describes applies Markov LQ control to settings’ - two verbs. 404: ‘Markov jump linear quandratic control problems’. 447: ‘there is are equal chances of moving from one state to the other’. Separately, the same fact is stated three times in the first eighty lines: ‘The extensions are modified versions of his 1979 model suggested by{cite}`barro1999determinants`and{cite}`barro2003religion`)’ (40-41), ‘By doing these two things we extend{cite}`Barro1979`along lines he suggested in{cite}`barro1999determinants`and{cite}`barro2003religion`)’ (60-61), and ‘Partly inspired by{cite}`barro1999determinants`and{cite}`barro2003religion`, our generalizations of{cite}`Barro1979`, assume’ (82-83) - which is also where most of the nine qe-ref-001 hits come from. And what Markov jump LQ programming is gets explained three more times after 30-31 has already named it and linked the lecture that covers it: 95-101, 110-114, 116-119.[qe-writing-008] — Remove excessive whitespace between words. Count: 36. Lines: 30, 41, 47, 52, 53, 60, 61, 82, 83, 123, …. Example: 3 spaces.
Medium severity#
[qe-code-003] — Package installation at lecture top. Count: 1. Lines: 158. Example: install cell at line 158 of 508 (not near the top).
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 3. Lines: 372, 385, 498. Example: code-cell figure without mystnb figure metadata.
[qe-fig-008] — Use lw=2 for line charts. Count: 3. Lines: 376, 389, 503. Example: plot() without lw=.
[qe-link-002] — Use doc links for cross-series references. Count: 1. Lines: 178. Example: raw link to python-intro.quantecon.org.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 2. Lines: 248, 262. Example: 248 and 282-283 use
\hspace{2mm}as a display separator -G_t = S_G x_t \hspace{2mm}, \hspace{2mm} b_{t-1,t} = S_1 x_t- where\quadis the standard one-token form, and the comma sits before the space at 248 and after it at 282, so the hand-tuning is not even self-consistent. 262 runs every symbol together with no spacing at all:T_t^2 = x_t'S'Sx_t + u_t'M_t'M_tu_t + 2 u_t'M_t'S x_t, in whichS'S,Sx_tandM_tu_tare each two symbols the reader has to separate unaided - and this single line carries all 11 of the file’s qe-math-002 apostrophe transposes, so it will be rewritten anyway.[qe-math-011 (proposed)] — Distribution names in plain letters, not \mathcal / \mathbb. Count: 1. Lines: 220. Example: decorated distribution
{\cal N}.[qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 500, 320, 453, 382. Example: the lecture’s final claim is made against an incomparable figure. 492-496 says ‘Simulating a large number of such economies over time reveals interesting dynamics. Debt tends to stay low and stable but recurrently surges’ - a comparison with the constant-interest-rate debt figure at 385-392 - but the cell that draws it changes two inputs at once without saying so:
x0goes from[[100, 1, 25]](329) to[[1000, 1, 25]](500), a tenfold increase in initial debt, andTgoes from 500 (386) to 2000 (499). The ‘low and stable’ level and the ‘recurrent surges’ are therefore being read off a different initial condition and a horizon four times as long. Second, the no-Ponzi penalty exists only as a code comment:# Small penalty on the debt required to implement the no-Ponzi schemeat 320 followed byR[0, 0] = R[0, 0] + 1e-9at 321, with no mention anywhere in the prose that the objective has been perturbed or why. Third, 453-455 asserts that ‘If we were to set \(p_{t,t+1} = 0.9515\) in the version of the model with a constant interest rate, government debt would explode’ - the one falsifiable prediction in the lecture, and it is never run, though the machinery to run it is three lines. Fourth, 382-383 invites a comparison (‘We can see a similar, but a smoother pattern, if we plot government debt over time’) between two figures drawn from two independent unseeded runs of 250 simulations each (374-376, 387-389), so the taxation paths and the debt paths are not the same paths.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 4. Lines: 52, 223, 65, 93. Example: the same phrase is bold in three places and italic in a fourth: ‘Markov jump linear quadratic dynamic programming’ at 30 and 111 and ‘Markov jump linear quadratic dynamic program’ at 95-96, against ‘Markov jump linear quadratic dynamic programming’ at 52-53. The one place a term is actually being defined uses italic - ‘The variables \(T_t, b_{t, t+1}\) are control variables chosen at \(t\)’ (223) - while bold is doing emphasis duty at 65 (‘an exogenous sequence of expenditures’) and 93 (‘are time-varying and stochastic’). Bold appears nine times in the first 120 lines and never again in the remaining 390, so the convention is not so much inconsistent as abandoned partway through.
[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 485, 444, 372. Example: the payoff of the extension is dumped as two raw arrays. 482 says ‘The decision rules are now dependent on the Markov state’ and then 485 and 489 print
lqm.Fs[0]andlqm.Fs[1]in separate cells, leaving the reader to diff two 1x3 float arrays by eye in order to see the one thing the whole Markov-jump apparatus was built to show. Second, the two-state interest-rate process - \(p^1 = 0.97\), \(p^2 = 0.933\), \(\Pi = \begin{bmatrix} 0.8 & 0.2 \\ 0.2 & 0.8 \end{bmatrix}\) (429-445) - is never drawn, and 447-455 then reasons about its stationary distribution and unconditional mean in prose; a two-node diagram, or a single simulated path of the Markov state plotted under the debt path, would make ‘recurrently surges’ (495-496) legible as surges in the high-interest state. Third, all three figures (372, 385, 498) are drawn with theplt.global interface, carry no:name:, and are referred to positionally, and the lecture contains no admonitions at all in 508 lines - the no-Ponzi penalty at 320-321 and the explosion claim at 453-455 are both natural{note}s.
Low severity#
None found.
Strengths#
The mapping from Barro’s problem into the LQ framework is built in the right order and every piece is justified as it appears: the primitives are listed with units (182-190), the state and control are chosen and the reason given (233-235), the transition law is written in block form (239-241), \(G_t\) and \(b_{t-1,t}\) are expressed as selector matrices on the state (247-249), the budget constraint is used to get taxation as a function of state and control (251-257), and only then is \(T_t^2\) expanded to read off \((R, Q, W)\) (259-263) - so the code at 300-318 is a transcription the reader can check line by line.
The martingale property is derived and then checked numerically rather than asserted: 338-355 substitutes \(u_t = -Fx_t\) through the transition law to get \(E_t T_{t+1} = (S-MF)(A-BF)x_t\), 357-361 states the exact condition \((S-MF)(A-BF) = (S-MF)\) under which taxation is a martingale, and 366 prints both sides for comparison - and 369-370 then names the visible consequence in the figure (‘This explains the fanning out of the conditional empirical distribution of taxation across time’).
The extension is introduced by naming precisely which matrices stop being constant and why: 397-401 says that time-varying \(p_{t,t+1}\) forces \(M\) to vary, and that ‘\(Q\) and \(W\) matrices must also vary over time’ - which is exactly the dependency chain \(Q = M'M\), \(W = M'S\) that the code then implements at 470-475.
The two interest-rate states are given economic content before they are used: 429-437 fixes \(p^1 = \beta + 0.02\) and \(p^2 = \beta - 0.017\) and says which is the low-interest state, and 450-455 notes that the unconditional mean price 0.9515 exceeds \(\beta = 0.95\) and draws the consequence - the government is on average borrowing more cheaply than it discounts, which is what makes the debt dynamics interesting rather than merely different.
The lecture places itself in a sequence explicitly, with both sequels linked at 37-38 and the third one previewed again at 152-154, and it points at the lecture that supplies the method it depends on (30-31, 110) instead of re-deriving Markov jump LQ programming.
The public-finance questions the two generations of the model are meant to answer are separated and listed (121-140): the 1979 model’s tax-versus-borrow question against the later papers’ maturity-composition and roll-over-risk questions, which tells the reader what the added state dimension is for before any of it is formalised.
Recommended actions#
Make the last figure comparable to the second. Either keep
x0 = np.array([[100, 1, 25]])andT = 500at 499-500 so the Markov-jump debt paths sit on the same axes as the constant-rate ones (385-392), or state at 492 that the initial debt and horizon have changed and say why. As written, ‘Debt tends to stay low and stable but recurrently surges’ is a claim about a figure the reader cannot line up against anything.Seed the three simulation loops (374, 387, 501). Each redraws 250 unseeded paths at build time, so the figures - and the ‘fanning out’ claim at 369 and the ‘smoother pattern’ claim at 382 - change on every rebuild, and the taxation and debt figures are drawn from different draws even though the prose compares them.
Fix the five broken sentences: the stray ‘m’ at 43, the unopened closing parentheses at 41 and 61, ‘describes applies’ at 153, ‘quandratic’ at 404, and ‘there is are’ at 447.
Rewrite the nine
{cite}uses that stand in for a subject (41, 43, 61, 63, 82, 123, 132, 175) as author-year in prose with the citation in support - ‘Barro{cite}`Barro1979`studies a government that…’ rather than ‘{cite}`Barro1979`is about a government that…’. This is the qe-ref-001 finding, and the same edit removes most of the triple repetition at 40-41, 60-61 and 82-83.Explain the no-Ponzi penalty in the prose. Line 321 adds
1e-9to \(R_{11}\) and only a code comment says why; the sibling treatment inperm_income_cons(its 303-314) is the model to follow, since it names the trick, says what it approximates and promises a numerical check.Show the two decision rules instead of printing them: replace the bare
lqm.Fs[0]/lqm.Fs[1]cells at 485 and 489 with one cell that prints both against each other, or plots the implied tax rule \(T_t = (S - M_s F_s)x_t\) in the two Markov states. Then run the explosion claim at 453-455 - oneqe.LQinstance with \(M = -0.9515\) and one debt path is enough.Move the install cell (158) above the 130 lines of Overview and add the standard lead-in sentence, ‘In addition to what’s in Anaconda, this lecture will need the following libraries:’. It is currently the first code cell, so the qe-code-003 hit is about distance from the top rather than ordering among cells, but the missing lead-in the rule also asks for is genuinely absent (156-157 are blank).
Convert the 11 apostrophe transposes at 262 to
^\topand space the expression while doing it; replace the three\hspace{2mm}separators (248, 282, 283) with\quad; write{\cal N}(0,I)asN(0,I)at 220 (qe-math-011 (proposed)); mark up the bareMat 398 as$M$to match$Q$and$W$at 400; and convert the six bareE_0/E_tat 70, 203 and 354 to\mathbb{E}(the checker reports no qe-math-010 (proposed) for this file because its bare-letter branch needs a bracket after the E, so these are invisible in the counts).Figures: lowercase the six axis labels (377, 378, 390, 391, 504, 505) and expand ‘Govt Debt’ to ‘government debt’, add
lw=2and analphato the three overplotted loops (376, 389, 503), and addmystnbfigure metadata with names to the three cells (372, 385, 498) so 369, 382 and 492 can cite them. Note that this file is byte-identical tolecture-python-advanced.myst/lectures/tax_smoothing_1.md, so every fix should be made once, upstream, and both series clear - as withtax_smoothing_2andsmoothing_tax.Clear the 36 double and triple spaces, and normalise the ragged bullet indentation at 182-190 (
*,*), which is where several of them are.