perm_income#

  • Series: lecture-dp

  • File: lectures/perm_income.md

  • Audit date: 2026-08-26

  • Corpus snapshot: c30490a2f4

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

  • Overall score: 7.0 / 10

  • Priority: HIGH

Score breakdown#

Category

Score

One-line note

Writing

3/10

qe-writing-006 ×15; qe-writing-005 ×6; qe-writing-002 ×5, +4 more.

Math

4/10

qe-math-002 ×8; qe-math-010 (proposed) ×3; qe-math-009 ×3.

Code

7.5/10

qe-code-001 ×5.

JAX

out of scope

JAX rules target lecture-jax.

Figures

6/10

qe-fig-005 ×3; qe-fig-003 ×1; qe-fig-006 ×1, +2 more.

References

8.5/10

qe-ref-001 ×3.

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: 5. Lines: 810, 829, 516, 513, 498. Example: 810 redefines time_path, a function already defined at 482 with a different signature and a different meaning - the first returns w, b, c for the IID-income example, the second returns b, c for the impulse-response example and takes a permanent flag - 328 lines apart with no note that the name is being reused, so a reader who re-executes the earlier cell silently gets the wrong function. 829 binds L = 0.175 as a plot limit in a lecture that has just told the reader ‘\(L\) is the lag operator’ (705) and written \(d(L) = \sum_j d_j L^j\) (705, 1001). 516 pulls in the stdlib random module (imported at 52) solely to randomise line colours, rcolor = random.choice(('c', 'g', 'b', 'k')), so the figure mixes two unseeded RNGs and its colours carry no information. 513 assigns b_sum = np.zeros(T+1) and never uses it. 498 has a space after the opening parenthesis, ax.plot( b, 'b-', label="Debt") (E201), where 496 and 497 do not. And 836 draws the impulse date as a two-point series, ax.plot((S, S), (-L, L), 'k-', lw=0.5), where axvline(S) is the one-call form.

  • [qe-fig-008] — Use lw=2 for line charts. Count: 5. Lines: 496, 497, 498, 834, 835. Example: plot() without lw=.

  • [qe-math-002] — Use \top for transpose notation. Count: 8. Lines: 158, 394, 406, 417, 623, 669. Example: apostrophe transpose A'.

  • [qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 3. Lines: 663, 896. Example: non-blackboard \mathrm{Var}.

  • [qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 5. Lines: 997, 848, 935, 173, 683. Example: the footnote at 997 contradicts itself in three lines: it says ‘Suppose instead that we had imposed the following more standard assumptions on the utility function: \(u'(c) >0, u''(c)<0, u'''(c) > 0\)’, and then two sentences later ‘But the fact that \(u''' <0\) implies via Jensen’s inequality that \(\mathbb{E}_t [u'(c_{t+1})] > u'(\mathbb{E}_t [c_{t+1}])\)’ - the sign has flipped, and the flipped sign is the one the argument runs on (the inequality as stated needs \(u''' > 0\), i.e. \(u'\) convex). 848 says the same word twice with opposite meanings intended: ‘notice how most of a transitory income shock is saved and only a small amount is saved’ - the second should be ‘consumed’, and the sentence is contradicting 784-786 as written. 935 has lost its reference: ‘Application of formula to this example shows that’, where the parallel sentence at 788 reads ‘Application of the formula for debt in {eq}`pi_ssr` to this example shows that’. 173 packs two sentences and a double space into one {note} line. And 687 states a result by describing a picture instead of showing one: ‘The impulse response function of \(\{c_t\}\) to the innovation \(\{w_t\}\) is a box’.

  • [qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 6. Lines: 264, 270, 41, 621, 553, 856. Example: the same term is italic and bold six lines apart: ‘consumption equals economic income’ at 264, then ‘economic income equals’ at 270. The pattern runs through the lecture - the cointegration family is italic when introduced (cointegration 41, cointegrating residual 633) and bold in between (cointegrating vector 621); the innovation family likewise (innovation 97, innovation to the expected present value 553, innovation representation 856, against present value of the moving average coefficients 730). Eight definitions are bolded (random walk 91, the five wealth terms at 266-270, cointegrating vector 621, present value of the moving average coefficients 730, fundamental 1005) and twelve are italicised (state 40 and 276, cointegration 41, information set 77, innovation 97, no Ponzi scheme 176, Euler equations 196, dynamic programming 222, innovation to the expected present value 553, cointegrating residual 633, innovation representation 856, random walks 89), so the file is close to a coin flip. The three genuine italic emphases (necessary 209, is 609, permanent 922) are correct.

  • [qe-writing-006] — Capitalize lecture titles properly. Count: 15. Lines: 56, 107, 186, 217, 274, 331, 421, 525, 530, 635, …. Example: H2 Title Case: ‘The Savings Problem’ (Savings, Problem).

  • [qe-writing-008] — Remove excessive whitespace between words. Count: 29. Lines: 45, 69, 76, 91, 173, 196, 223, 269, 271, 383, …. Example: 2 spaces.

Medium severity#

  • [qe-fig-001] — Do not set figure size unless necessary. Count: 3. Lines: 494, 511, 826. Example: figsize=.

  • [qe-fig-003] — No matplotlib embedded titles. Count: 1. Lines: 833. Example: .set_title.

  • [qe-fig-005] — Descriptive figure names for cross-referencing. Count: 3. Lines: 474, 510, 803. Example: code-cell figure without mystnb figure metadata.

  • [qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 259, 276, 234. Example: the same fraction is written two ways in one derivation: {r \over 1+r} at 259 and 304 against \frac{r}{1+r} at 269, and {1 \over 1-\beta} at 560 and 584 against \frac{c_t}{1-\beta} at 249 - \over is the deprecated plain-TeX primitive and four of the file’s nine fractions use it. 276 writes the state as the row vector \begin{bmatrix} b_t & z_t \end{bmatrix} while 349-353 writes the same object as the column \(x_t = [z_t; b_t]\) with the components in the opposite order, and 623 writes a third variant, \begin{bmatrix} b_t & c_t \end{bmatrix}'. 234 puts a \frac in an exponent, \(\beta^{\frac{t}{2}}\), which renders as a two-storey fraction at superscript size; \(\beta^{t/2}\) is both simpler and legible.

  • [qe-ref-001] — Use correct citation style. Count: 3. Lines: 858, 898. Example: {cite} in narrative flow: ‘of {cite}’.

  • [qe-writing-001] — Use one sentence per paragraph. Count: 4. Lines: 173, 222, 997, 1005. Example: 2 sentences in one paragraph.

  • [qe-writing-003] (reviewer) — Maintain logical flow. Count: 2. Lines: 896, 492. Example: 896 defines the innovation with a bare E - ‘\(a_t := y_t - E [ y_t \,|\, y_{t-1}, \ldots, y_0]\)’ - the only bare expectation operator in a lecture that writes \mathbb{E} more than thirty times (73, 76, 114, 119, 158, 181, 193, 206, 249, 258, 293, 394, 540, 550, 560, 571-573, 630, 977, 983, 990, 997), so the definition of the object Example 2 is built on looks like a different operator from the one used everywhere else. Second, the two figures in the IID example (492-503, 510-522) draw from np.random.randn with no seed, and the claims made about them are specific - ‘consumption is considerably smoother than income’ (506) and the cross-sectional fan at 508 - so both the picture and the strength of the claim change on every build; the copy of this file in lecture-python.myst has already been converted to a seeded np.random.default_rng generator threaded through time_path.

  • [qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 683, 656, 601. Example: the section headed ‘### Impulse Response Functions’ (683-689) contains no impulse response function. It asserts the shape in prose (‘is a box’, 687) and gives the height as a formula (689), and the figure that actually draws it appears 120 lines later inside ‘### Example 1’ (803-843), after which 850 refers back to ‘The box-like impulse responses’ - so the reader meets the claim, the formula, and the picture in three different places. Second, 656-681 derives the lecture’s one testable cross-sectional prediction, \(\mathrm{Var}[c_t] = \mathrm{Var}[c_0] + t\,\hat\sigma^2\), and reports that ‘A number of different studies have investigated this prediction and found some support for it’ - while the 250-path fan at 510-522, which is exactly that prediction rendered, sits 150 lines earlier with no cross-reference; overlaying \(\pm\sqrt{\mathrm{Var}[c_0] + t\hat\sigma^2}\) on those paths would make the linear-in-\(t\) spread a visible check rather than a citation. Third, the Cointegration section (598-633) builds to ‘\((1-\beta) b_t + c_t\) is asymptotically stationary’ (619) and never plots the residual, even though the sequel perm_income_cons plots precisely this object (its 701-719) - a figure here, or a forward pointer to that one, would close the argument.

Low severity#

  • [qe-fig-006] — Lowercase axis labels. Count: 1. Lines: 501. Example: axis label Time.

Strengths#

  • The martingale machinery is set up before it is needed and at exactly the level required: 66-105 defines a discrete-time martingale, says what the information set is and who chooses it (‘just a collection of random variables that the modeler declares to be visible at \(t\)’, 79-80), gives the gambler’s fair game as the intuition, specialises to random walks, and then closes the loop with a caution that the specialisation is strict (‘Not every martingale arises as a random walk’, 105) - so when {eq}`sprob5` arrives at 206 the reader already knows what it claims.

  • The optimal decision rule is derived by naming its three ingredients as a numbered list (228-232: the Euler equation, the period budget constraint, the boundary condition) and then using each one visibly - {eq}`sprob3` gives the transversality limit at 234, {eq}`sprob2` is solved forward at 236-242, and the martingale property plus the law of iterated expectations turns {eq}`sprob6` into {eq}`sprob7` at 244-250.

  • The lecture flags its own hard step instead of hiding it: after the four-line chain at 312-323 it says ‘To get from the second last to the last expression in this chain of equalities is not trivial’ and then supplies the two facts needed, \((1+r)\beta = 1\) and \((I - \beta A)^{-1} = \sum_j \beta^j A^j\) (325-327).

  • Wealth accounting is spelled out as a list of definitions with the marginal propensity to consume identified as the interest factor (264-272), which is what makes the phrase ‘consumption equals economic income’ mean something, and the final bullet gives the operational reading - ‘the amount the consumer can consume while leaving its wealth intact’.

  • Hall’s representation is presented as a change of state, with the consequence stated explicitly: 590-596 says the state can be taken as \((c_t, z_t)\), that ‘Debt \(b_t\) has disappeared as a component of the state because it is encoded in \(c_t\)’, and that the consumption innovation \((1-\beta) U (I-\beta A)^{-1} C w_{t+1}\) is ‘a more explicit representation of the martingale result in {eq}`sprob5`’ - so the alternative representation earns its section.

  • The two classic examples are built on one common endowment process (737-765, with \(z_{1t}\) permanent and \(z_{2t}\) transitory) and differ only in what the consumer observes - the state \(z_t\) in Example 1 (769), only \(y_t\) and its history in Example 2 (854) - which isolates the informational assumption, and Example 2 then derives the Kalman-gain weighting \(1 - \beta(1-K)\) and reconciles it with Example 1 by taking \(K\) to its endpoints (920-943).

  • Six of the seven footnotes carry real content rather than asides - the necessity of linear marginal utility for the martingale result (997), the definition of an optimal decision rule (999), \(d(L) = U(I - AL)^{-1}C\) (1001), the sufficient condition for asymptotic stationarity (1003), and the definition of a fundamental moving-average representation (1005).