theil_2#

  • Series: lecture-python.myst

  • File: lectures/theil_2.md

  • Audit date: 2026-08-26

  • Corpus snapshot: e25fdf2345

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

  • Overall score: 8.1 / 10

  • Priority: LOW

Score breakdown#

Category

Score

One-line note

Writing

4.5/10

qe-writing-001 ×3; qe-writing-005 ×4; qe-writing-003 ×3, +3 more.

Math

7.5/10

qe-math-004 ×3; qe-math-009 ×4.

Code

6.5/10

qe-code-002 ×8; qe-code-001 ×4.

JAX

out of scope

JAX rules target lecture-jax.

Figures

8.5/10

qe-fig-005 ×1; qe-fig-001 ×5.

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-002] — Use Unicode symbols for Greek letters in code. Count: 8. Lines: 622, 632, 657, 658, 663, 668, 706, 707. Example: spelled-out beta.

  • [qe-fig-001] — Do not set figure size unless necessary. Count: 5. Lines: 163, 341, 660, 709, 779. Example: figsize=.

Medium severity#

  • [qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 4. Lines: 574, 631, 532, 663. Example: the cell that is supposed to verify Hall’s martingale computes two things and throws both away. 573 builds the closed-form policy F_pi = [[(R-1), (R-1)/(R-ρ)]] from 561 and 574 builds A_cl_std = A_pi - B_pi @ F_pi; A_cl_std is never read again, so F_pi exists only to feed a dead binding, and the closed form of 561 is never checked against LQ’s own F. What the cell does print is φ_std = 1.0 / (β_hat * R_rate) (576) where R_rate = 1.0 / β_hat (530), so the printed value is exactly 1 by construction rather than by computation. Three more bindings are dead: d_std (328), K_rob (337, rebound and used only at 840-858), and θ_pi (534), which is defined with a comment explaining the mapping and never used - the exercise recomputes θ_val = -1.0 / s at 838. Separately, 631 writes ν_rob ** 2 with spaces around the exponentiation operator, which the rule singles out to be written closed up (theil_1:361 has the same); six assignments pad with extra spaces before = to align columns, which PEP8 discourages (532, 534, 573, 626, 631, 632); 626-627 uses a backslash continuation inside an expression that parentheses would wrap; and three code lines run past 79 characters (332 at 89, 663 at 98, 669 at 80).

  • [qe-math-004] — Do not use bold face for matrices or vectors. Count: 3. Lines: 288, 289, 296. Example: \mathbf.

  • [qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 4. Lines: 117, 508, 135, 447. Example: the state-cost and control-cost matrices are named one way here and the opposite way in the companion lecture, and neither matches the library both lectures call. 117 writes the return as \(r(y,u) = -y^\top Q y - u^\top R u\), so \(Q\) is the state cost and \(R\) the control cost, and the code agrees - 150-151 comment Q_mat as “state cost” and R_mat as “control cost”. quantecon.LQ, whose docstring gives the objective as \(x_t' R x_t + u_t' Q u_t\), uses the reverse: \(R\) on the state, \(Q\) on the control - and that is the naming theil_1 adopts at its lines 277-278 (R_mat = state cost, Q_mat = control cost). Both lectures then compensate in the call, theil_1 with LQ(Q_mat, R_mat, A, B, ...) and theil_2 with LQ(R_mat, Q_mat, A, B, ...), so both compute the same thing - I ran both namings and got P = 1.472317, F = 0.524797, d = 27.974028 either way - but a reader moving between two lectures that share a title, a model and a code cell meets the same two matrices under swapped names, with no warning in either file. Second, \(R\) then does triple duty inside this lecture: control-cost matrix (117, 151), gross return on savings (494, 502, 561), and at 508 the collision is patched with a subscript rather than a rename - \(R_{\text{ctrl}} = 1\), a symbol that occurs exactly once - while the code carries R_mat (151), R_rate (530) and R_pi (543). Third, \(\sigma\) is the risk-sensitivity parameter, introduced at 58-59 with \(\theta = -\sigma^{-1}\) and used at 438-468 and 682-684, and also the noise level of the recap figure at 135, 153, 166, 171 and 324. Fourth, \(\rho\) is the scalar term of the candidate continuation value at 447 (\(U_{t+1}^e = -y_{t+1}^\top \Omega y_{t+1} - \rho\), with \(\hat\rho\) at 456-460) and the endowment persistence at 499-502 and 531.

  • [qe-writing-001] — Use one sentence per paragraph. Count: 3. Lines: 50, 291, 758. Example: 2 sentences in one paragraph.

  • [qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 3. Lines: 505, 49, 758. Example: 505-508 is a 50-word sentence whose main verb arrives at word 45: “After absorbing the constants \(-b\) and \(\mu_d(1-\rho)\) by augmenting the state vector, or equivalently by working with deviations from steady state, setting \(w_{t+1} \equiv 0\) and taking \(Q = 0\) (return depends only on the control \(\mu_{ct}\)) and \(R_{\text{ctrl}} = 1\) puts this in the standard LQ form” - four separate modelling steps, two of them parenthesised, before the reader learns what they accomplish. 49-52 is 45 words carrying a question, an answer and a mechanism in one block (and is the drafted qe-writing-001 finding at 50). 758-761 states the exercise in 45 words across two sentences in one paragraph, with the plotting instruction tacked on after the claim to be verified.

  • [qe-writing-003] (reviewer) — Maintain logical flow. Count: 3. Lines: 612, 618, 96. Example: the observational-equivalence formula is used 76 lines before it is stated. 612-614 says “The observational equivalence formula {eq}`eq:oe_locus` (derived below) immediately gives the robust AR(1) coefficient”, 621-628 defines beta_tilde implementing it, and 631-635 evaluates it - while {eq}`eq:oe_locus` itself appears at 688-693 and \(\alpha^2 = \tilde\nu^2\) is defined at 695, after α_sq = ν_rob ** 2 has already been written at 631. The lecture flags the inversion, but the code that depends on the formula still runs first. Second, \(\tilde\nu\) is an input read out of a paper rather than a computed quantity: 616-619 says “The innovation scale \(\tilde\nu\) follows from the robust permanent income formula with the distorted persistence; {cite:t}`HST_1999` report \(\tilde\nu \approx 8.0473\)”, no code follows the formula, and 630 hard-codes ν_rob = 8.0473. Everything downstream rests on it - the robust simulated path at 658, α_sq at 631, the entire locus plotted at 705-721 - so the lecture’s central quantitative claim is anchored to a number it does not derive. Third, the pair’s cross-references use three different mechanisms in two files: 38 links back with a bare markdown link [this lecture on certainty equivalence](theil_1), 96 uses {ref}companion lecture <certainty_equiv_theil1>``, and theil_1:391 links forward with [certainty equivalence and model uncertainty](theil_2); the exercise labels diverge the same way, theil1_ex1 in one file against ce_ex2 and ce_ex3 here - a numbering that starts at 2 with no ce_ex1 in either lecture.

  • [qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 4. Lines: 38, 54, 557, 724. Example: the lecture’s title concept is italicised where it is coined - 38, “established an important certainty equivalence (CE) property” - which is exactly what the companion lecture does at its line 51, and theil_1 then bolds the same term at its line 174, so across the pair the term appears in both styles and this file never bolds it. 54 italicises Risk-sensitive preferences. as a list header and 416 bolds risk-sensitive preferences as a definition, for the same term. 557-558 sets a whole clause in bold - “the marginal utility of consumption is a martingale” - and the term inside it, marginal utility of consumption, was already bolded at 488-489, so the bold is doing emphasis on top of a definition it repeats. Whole-sentence italics appear twice more, at 366-368 (“both the policy gain and the value matrix depend on the robustness parameter \(\theta\) and the noise-loading matrix \(C\)”) and 724-726 (“activating a preference for robustness is observationally equivalent – for consumption and saving behaviour – to increasing the discount factor”), where the lecture’s own word-level italics (distorted 51, conceals 232, ordinary 260, same 279, does 312, fully trusts 418, not 729) are the correct form.

  • [qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 2. Lines: 389, 413. Example: the distortion operator is the mechanism the lecture is about and it is never shown. \(\mathcal{D}\) appears at 385, 389, 456, 459 and 732, and {eq}`eq:distortion_op` at 389 is literally \(\mathcal{D}(P) = \mathcal{D}(P;\, f_2,\, \theta)\) - an equation that restates its own argument list - with {eq}`eq:constant_p` at 396 doing the same for \(p\). Meanwhile quantecon.RBLQ.robust_rule() already returns the worst-case distortion matrix: it is bound to K_rob at 337 in the very figure cell that plots \(F(\theta)\) and \(P(\theta)\), and discarded. A third panel showing \(K(\theta)\) next to those two would put the object the whole lecture turns on into a picture, and would show it going to zero as \(\theta \to \infty\) alongside the two quantities that already do. Second, the risk-sensitive section (413-468) has no figure at all: its content is that \(\mathcal{R}_t\) collapses to \(\mathbb{E}\) at \(\sigma = 0\) (441) and penalises right-tail risk for \(\sigma < 0\) (443-444), and one plot of \(\mathcal{R}_t(U)\) against \(\sigma\) for a Gaussian \(U\) - or of the exponential tilt \(\exp(\sigma U / 2)\) against \(U\) for two values of \(\sigma\) - would make the operator concrete. As written the section’s central claim sits in a blockquote at 467-468 and is not checked until exercise ce_ex3, 330 lines later.

  • [qe-writing-008] — Remove excessive whitespace between words. Count: 4. Lines: 50, 292, 467, 760. Example: 2 spaces.

Low severity#

  • [qe-fig-005] — Descriptive figure names for cross-referencing. Count: 1. Lines: 770. Example: code-cell figure without mystnb figure metadata.

Strengths#

  • The summary table at 739-743 answers the same three questions - does the policy depend on noise, which forecasts are used, does CE survive - for all three settings in one place, and it is the only spot in the lecture where the three are directly comparable.

  • The invariant half of the two-step algorithm is named explicitly every time the setting changes, so the reader can see what the extension does not touch: 309-310 (“step 1 is identical to the non-robust case; only step 2 changes, using distorted rather than rational forecasts”), 597-600 (“where \(h_1\) – the first step of the CE algorithm – is identical to the non-robust case. Only the expectations operator changes”), and again at 745-749.

  • Exercise ce_ex3 (799-872) does the work that the “Key equivalence” blockquote at 467-468 only asserts, and does it properly: for three values of \(\sigma\) it solves the robust problem with RBLQ, extracts \(\varphi\) from the closed loop \(A - BF\), inverts to \(\tilde\beta = 1/(\varphi R)\), re-solves a non-robust problem at that \(\tilde\beta\), and prints \(\max|F_{\text{rob}} - F_{\text{nr}}|\) - so observational equivalence is demonstrated rather than quoted.

  • That same solution then says what the equivalence does not cover, and why: 868-872 points out that the worst-case distortion \(K\) has no analogue in the non-robust model, which is why the two parametrisations imply different asset prices - and 728-732 makes the same point in the main text, attributing it to the \(\mathcal{D}(P)\) matrix in the stochastic discount factor.

  • Two numerical choices are declared rather than smuggled in: 521-523 explains the 1e-8 I regularisation and names the case that needs it (\(\beta R = 1\)), and the comment at 332 says why the robustness figure restricts \(\theta\) to \([2, 30]\) (“restrict attention to a numerically stable range”).

  • Both limiting cases of the risk-sensitive operator are stated where the operator is defined: \(\sigma = 0\) recovers ordinary expectation by L’Hopital’s rule (441), and \(\sigma < 0\) penalises right-tail risk in the continuation value (443-444) - so the reader can locate the standard case inside the generalisation.

  • The robustness figure at 317-359 plots both objects that ordinary CE holds fixed - the policy gain \(F\) and the value matrix \(P\) - against \(\theta\) on one row, with the non-robust values drawn as horizontal reference lines and their numerical values in the legend labels, which makes the convergence claim at 362-364 checkable by eye.