smoothing_tax#
Series: lecture-dp
File:
lectures/smoothing_tax.mdAudit date: 2026-08-26
Corpus snapshot:
c30490a2f4Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 7.1 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3.5/10 |
|
Math |
6/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
4/10 |
|
References |
10/10 |
no mechanical violations detected. |
Links |
9/10 |
|
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: 5. Lines: 584, 641, 572, 484, 213. Example: the
displaymethod builds three figures three different ways: 584-591 opens withplt.figure()and theplt.global interface, 593-601 opens withplt.titleand noplt.figure()at all (relying on the previousplt.show()having closed the last one), and 603-615 usesfig, ax = plt.subplots(). 641 is an f-string with no placeholders,print(f"Ex-post returns to purchase of Arrow securities:")(F541). 572-573 uses a backslash continuation where parentheses would wrap the tuple assignment. 484-485 bindsΠ = np.reciprocal(Q)- taking the symbol this series uses for the Markov transition matrix (Πintax_smoothing_1line 459 andtax_smoothing_2line 462) and giving it to a matrix of gross returns whileP, the actual transition matrix, sits in the same cell at 434 - and then aliases it once more asexretfor no gain. And 780 has a space before a closing bracket,[θ, 0, 0, 1-θ ]. Note that the aligned multiple spaces in the fiveP_ex*literals (701-703, 741-743, 777-780, 812-816, 853-859) are the matrix-notation exemption and must be left alone.[qe-fig-003] — No matplotlib embedded titles. Count: 7. Lines: 250, 257, 284, 292, 585, 593, 604. Example: .set_title.
[qe-fig-006] — Lowercase axis labels. Count: 9. Lines: 255, 263, 289, 298, 590, 600, 607, 608, 613. Example: axis label
Periods.[qe-fig-008] — Use lw=2 for line charts. Count: 20. Lines: 251, 252, 253, 258, 259, 260, 285, 286, 287, 293, …. Example: plot() without lw=.
[qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 5. Lines: 877, 884, 892, 898. Example: missing braces:
\mathbb E.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 6. Lines: 78, 82, 26, 425, 501, 515. Example: 78 collapses into fragments: ‘the government’s holdings of one-period risk-free bonds coming maturing at the due at the beginning of time \(t\)’ - three prepositional starts and no finish. 82 has ‘We’ll spend most of this lecture studying acquire finite-state Markov specification’. 26 promises a library and does not name it: ‘this lecture uses the library:’, where the double space is the gap the word
quanteconfell out of (the cell below installs it). 425 has ‘Here’s code that itinitializes government assets’. 501 has ‘the government always purchase \(1\) units’. 515-516 ends a section with ‘We recommend plugging the quantities computed above into the government budget constraints in the two Markov states and staring.’ Also 336 (‘the government has sold an Arrow securities paying off’), 722 (‘followed by a permanent peace .’) and 808 (‘We ssume that \(b_0 = 1\)’).[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 5. Lines: 42, 333, 416, 73, 371. Example: the two terms the lecture is organised around are bolded where they are mentioned and italicised where they are defined - ‘complete markets tradition’ and ‘incomplete markets tradition’ at 39-40, then ‘Complete markets allow a government to buy or sell claims contingent on all possible Markov states’ at 42 and ‘Incomplete markets allow a government to buy or sell only a limited set of securities’ at 44, which are the actual definitions. Bold then does emphasis duty: ‘it means the government is owed \(b_i\) or owes \(-b_i\)’ (333), ‘we’ll feed in a particular assumed path’ (416), ‘complete-markets models’ and ‘incomplete-markets model’ (921, 930). Meanwhile the genuine definitions are italic - ‘a consumer’s debt as a government’s assets’ (73), ‘\(b_i\) is the government’s level of assets’ (329), ‘claims owed to the government’ (331) - and 371 and 907 use bold as a run-in label (
**Convention:**,**Returns:**) where a{note}directive is what is wanted.[qe-writing-008] — Remove excessive whitespace between words. Count: 60. Lines: 26, 40, 42, 44, 46, 49, 68, 72, 75, 76, …. Example: 2 spaces.
Medium severity#
[qe-fig-001] — Do not set figure size unless necessary. Count: 2. Lines: 248, 282. Example: figsize=.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 2. Lines: 239, 281. Example: code-cell figure without mystnb figure metadata.
[qe-link-002] — Use doc links for cross-series references. Count: 1. Lines: 80. Example: raw link to python-intro.quantecon.org.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 2. Lines: 364, 910. Example: 364 writes the \(T\)-period compounded return as \(R^T(s_{t+T}, \ldots, s_t)\), loading a third meaning onto the letter \(T\) in a lecture where \(T_i\) and \(T_t\) are tax collections (317, 342, 441, 623) and \(T\) is also the horizon inside the same expression’s own subscripts; the code calls the object
RT_path(399) and computes it withnp.cumprod, so \(R_T\) or \(R^{(T)}\) - or naming it something other than \(R\) - would remove the collision. It also makes the expression indistinguishable from a transpose, which is why the checker miscounts it (see scanner_doubts). 910 puts the conditioning bar outside the operator:R(x_{t+1} | x_t) = \frac{b(x_{t+1})}{\beta E b(x_{t+1})| x_t}should be\beta \mathbb{E}[ b(x_{t+1}) \mid x_t ]; as written the \(| x_t\) dangles after the expectation’s argument, and the bareEis inconsistent with the\mathbb Eused at 877, 884, 892 and 898.[qe-writing-001] — Use one sentence per paragraph. Count: 1. Lines: 847. Example: 2 sentences in one paragraph.
[qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 452, 861, 232, 921. Example: three statements about the same quantity contradict each other, and one of them is printed to the reader as program output. The
msgstring at 452-456 says ‘Our assumptions imply that the government always purchases 0 units of the Arrow peace security’; the code comment at 460-461 says ‘since the spending on Arrow peace security is not 0 anymore after we change b0 to 1’; and the prose at 501-502 says ‘the government always purchase \(1\) units of the Arrow security that pays off in peace time’. The comment is the only one that admits the change, and the wrong statement is the one that renders. Second, Example 5 is short a state:g_ex5has seven entries andP_ex5is 7x7 (852-859), 847 says ‘the seven states’, butstates_ex5lists six (861), anddisplayloopsfor i in range(len(self.states))at 628, 634 and 642-643 - so the seventh state’s expenditure, tax and return figures are silently dropped from every printout. Third, the only{eq}reference in the file (232, ‘consumption_incomplete()that uses{eq}`cs_12`and{eq}`cs_13`’) points at labels defined insmoothing.md; this file defines no equation labels at all, so a reader is sent to two numbered equations with no indication that they are in a different lecture. Fourth, 921-928 is four consecutive sentences about the same two lectures, each giving them a differently-worded label: ‘optimal taxation in an LQ economy’ (921) and ‘Optimal Taxation in an LQ Economy ’ (924, 928), ‘recursive optimal taxation <opt_tax_recur>’ (921) and ‘Optimal Taxation with State-Contingent Debt <opt_tax_recur>’ (926, 928) - and 872 and 904 do the same to <smoothing>, which 37, 75 and 98 label in Title Case.[qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 1. Lines: 80. Example: mid-sentence ‘Savings’.
[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 579, 682, 515. Example: fifteen figures are produced by one
displaymethod (579-615) called five times, and not one of them can be referred to: they carry no:name:, three embeddedset_title/plt.titlecalls each (585, 593, 604), and the checker cannot even see twelve of them because they come from a helper. The third of the three - the cumulative-return path on a twin axis against government expenditures (603-615) - is the lecture’s one original exhibit, showing exactly the point 511-513 makes about high wartime returns on war insurance, and it arrives unlabelled after two other figures with no caption to say what to look for. Second, each of the five examples is specified by a Markov matrix given only as an array (682-688, 727-733, 761-768, 795-802, 835-844) with a state-name list in the code (705, 745, 782, 818, 861); the examples exist to trace paths like peace to war to postwar, and a small transition diagram per example would make that legible in a way a 5x5 or 7x7 matrix of \(1-\lambda\) and \(\phi\) entries does not. Third, 515-516 substitutes an instruction to the reader for a figure - ‘We recommend plugging the quantities computed above into the government budget constraints in the two Markov states and staring’ - where the budget identity \(T_i + b_i = G_i + \sum_j Q_{ij}b_j\) (317) checked in one bar chart or one printed table would settle it.
Low severity#
None found.
Strengths#
The isomorphism is not asserted but executed. 68-78 gives the relabelling as a four-item dictionary (consumption to tax collections, utility to loss, nonfinancial income to purchases, consumer debt to government assets) with the substitutions written out as \(c_t = T_t\), \(y_t = G_t\), \(-b_t = a_t\); 98 then reuses the code from
smoothingunchanged; and 281-301 re-plots the identical arrays with tax labels, so the reader sees the same numbers carrying two economic readings.The sign convention on \(b_i\) is nailed down in three sentences instead of left to be inferred: 329 says \(b_i\) is the government’s level of assets, 331 says it is ‘one-period state-contingent claims owed to the government’, and 333-337 spells out what a negative value means and where it comes from (‘in a previous war-time period the government has sold an Arrow security paying off \(-b_i\) in peacetime’).
The budget constraint is rearranged specifically to make the insurance interpretation visible: 341-346 rewrites \(T_i = G_i + (\sum_j Q_{ij} b_j - b_i)\) and then says in words what the bracketed term is - ‘the net amount that the government spends to purchase one-period Arrow securities that will pay off next period … after it has received payments \(b_i\) this period’ - which is the sentence that makes the whole complete-markets story concrete.
Returns on the state-contingent portfolio are defined at two horizons and both are computed: the one-period ex post return \(R(j|i) = b(j) / \sum_{j'} Q_{ij'} b(j')\) (357) with
ex_post_gross_return(374-390), and the cumulative rolled-over return (364-366) withcumulative_return(392-403) - and the degenerate case is declared rather than left to be discovered (‘Convention: In this code, when \(P_{ij}=0\), we arbitrarily set \(R(j|i)\) to be \(0\)’, 371).The first worked example is checked rather than displayed: 452-496 prints the transition matrix, the price matrix, expenditures, constant taxes, debts, spending on Arrow securities in each state, \(T+b\) in each state, total spending in each state, ex post and ex ante returns, and the cumulative return - which is every term of the budget constraint at 317, so the reader can verify the identity by arithmetic.
The five Markov chains are chosen to isolate distinct fiscal histories and each is given its historical referent: a one-way peace-war-postwar chain for the Civil War and World War I (676-697), a war followed by permanent peace (720-737), two war states differing only in whether peace is reachable next period (753-756), a five-state version of the same (790-806), and a fully deterministic path used as a control - ‘Since there is no randomness, the outcomes in complete markets setting should be the same as in incomplete markets setting’ (830), which is a prediction the figure then confirms.
The closing section maps the lecture’s boundary precisely (915-931): interest rates and Arrow prices are exogenous here, and the four lectures that make them endogenous are named with the mechanism that distinguishes them.
Recommended actions#
Fix the Example 5 state list at 861: it has six names for a seven-state chain, so every printed table in that example silently omits the last state. Add the missing war state (
g_ex5at 852 has four \(g_H\) entries, the list has three war names).Resolve the Arrow-peace-security contradiction. The printed
msgat 452-456 asserts the government buys 0 units of the peace security, the comment at 460-461 says that stopped being true when \(b_0\) was changed to 1, and 501-502 says it buys 1 unit. Rewrite themsgstring to match what the code now does, and delete the comment that explains the discrepancy.Name the library at line 26 - ‘this lecture uses the library:’ is missing
quantecon- and fix the other broken sentences: 78, 82, 336, 425, 501, 515-516, 722, 808.Fix the malformed expectation at 910: write \(R(x_{t+1} \mid x_t) = b(x_{t+1}) / (\beta \mathbb{E}[b(x_{t+1}) \mid x_t])\). As written the conditioning bar sits outside the operator’s argument and the operator is a bare
E.Convert the raw link at 80 to a
{doc}reference:https://python-intro.quantecon.org/perm_income_cons.htmlpoints at a lecture that is in this series (lecture-dp/lectures/perm_income_cons.md) and is not inlecture-python-introat all, so the link is wrong as well as raw. This is the qe-link-002 finding. Note also that the qe-writing-004 hit at the same line is a false positive - the capitalised ‘Savings’ is inside the link label[Optimal Savings II: LQ Techniques], which is that lecture’s actual H1 - so leave it alone once the link is converted.Either define
cs_12andcs_13here or say where they are. Line 232 is the file’s only{eq}reference and both labels live insmoothing.md; the honest form is ‘{eq}`cs_12`and{eq}`cs_13`of{doc}`smoothing`’.Give the figures identities.
display(579-615) produces three figures per call and is called five times: convert it to build onefig, axes = plt.subplots(3, 1)(or return the figures), move the three titles intomystnbcaptions, add:name:s so 511-513 and 830 can cite them, and lowercase the nine axis labels (255, 263, 289, 298, 590, 600, 607, 608, 613 - ‘Periods’, ‘Cumulative return’, ‘Government expenditures’). Addlw=2to the 20 line plots and drop the twofigsize=(14, 4)overrides (248, 282).Make the relabelling figure honest about being the same figure. 281-301 re-plots the identical arrays with tax labels - which is the pedagogical point - but it also silently changes two plotting details (
set_ylim([1.4, 2.1])at 290, which the consumption panel lacks, and the droppedalpha=.6at 295, which 260 has). One plotting function taking a label set would make the identity of the numbers visible and remove seven duplicated lines.Do NOT rewrite \(R^T\) at line 364 as a transpose. The qe-math-002 count of 1 for this file is a false positive: \(R^T\) is the return compounded over \(T\) periods, as 360-366 states and as
cumulative_return(392-403) computes. See scanner_doubts. Consider renaming it to \(R_T\) or \(R^{(T)}\) so it stops colliding with both the transpose notation and the tax variable \(T_t\).Rename
Πat 484: it is the reciprocal of the price matrix, andΠis the Markov transition matrix in both sibling lectures of this series (tax_smoothing_1459,tax_smoothing_2462) whilePis right there in the same cell. Drop theexret = Πalias at 485, and fix the f-string with no placeholders at 641.Be careful with
consumption_incomplete. Line 213 doesy.shape = (n, 1)oncp.yin place - the same aliasing side effect flagged in thesmoothingoverlay - but hereTaxSmoothingExample.displaydepends on it: 622 callsself.cp.y.flatten()and 635 indexesself.cp.y[i, 0], both of which assume the reshape already happened in__init__(572). Fixing 213 toy = cp.y.reshape((n, 1))without also fixing 622 and 635 will break this lecture, so the two files have to be changed together.Sentence-case nothing here - the headings are already sentence case, which is a strength relative to the rest of the series - but do clear the 60 double spaces (the highest count in this batch), split the two-sentence paragraph at 847-849, brace the five bare
\mathbb E(877, 884, 892, 898), and drop the trailing\crbefore\end{bmatrix}at 843. This file is byte-identical tolecture-python-advanced.myst/lectures/smoothing_tax.md, so every fix should be made once, upstream.