calvo#

  • Series: lecture-python-advanced.myst

  • File: lectures/calvo.md

  • Audit date: 2026-08-26

  • Corpus snapshot: b83d6da399

  • Categories 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/10

qe-writing-002 ×5; qe-writing-004 ×4; qe-writing-001 ×2, +4 more.

Math

5.5/10

qe-math-002 ×10.

Code

7.5/10

qe-code-001 ×6.

JAX

out of scope

JAX rules target lecture-jax.

Figures

7/10

qe-fig-003 ×2; qe-fig-001 ×5; qe-fig-008 ×1.

References

8.5/10

qe-ref-001 ×3.

Links

8/10

qe-link-002 ×4.

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: 922, 962, 1029, 1259, 1455, 1484. Example: 151 of the file’s 1557 lines end in whitespace, and most are inside the code cells - the continuation rows of the matrix literals (922-927), the blank separators inside solve_LQ_problem and compute_value_and_policy (937, 947, 967, 1001, 1008, 1010), and the argument lines of every plotting helper (1031, 1035, 1038, 1056-1064, 1079, 1258, 1275-1283, 1475-1478, 1487, 1495) - which is PEP8 W291/W293 throughout. 962 and 964 assign lambdas to attributes (self.J_θ = lambda θ_array: ..., self.V_θ = lambda θ: ...), which PEP8 E731 asks to be defs, and 962-963 adds a backslash continuation to do it. 1259 puts a compound statement on one line, if not isinstance(clqs, list): clqs, axes = [clqs], [axes] (E701). Four module-level functions describe themselves as methods - “Method to compute θ” (1031), “Method to plot the policy functions” (1047), “Method to plot Ramsey plan against Markov Perfect Equilibrium” (1443), “Method to generate a table of parameters” (1469) - none of which is a method. 1267 and 1297 run past 79 characters. And two lines pass magic values positionally where the keyword would say what they are: ax.scatter(θ, μ_min - offset, 60, color='black', marker='v') at 1071 (s=60) and ax.hlines(clq.μ_CR, 0, T-1, ...) at 1458, which draws the μ constrained-Ramsey level on the \(\theta\) panel and labels it \(\theta^{CR}\) - correct only because 959 sets self.θ_CR = self.μ_CR.

  • [qe-fig-001] — Do not set figure size unless necessary. Count: 5. Lines: 1051, 1352, 1390, 1414, 1447. Example: figsize=.

  • [qe-math-002] — Use \top for transpose notation. Count: 10. Lines: 272, 485, 489, 501. Example: apostrophe transpose }'.

  • [qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 5. Lines: 251, 1426, 1521, 1532, 1535. Example: 1426-1436 is five consecutive one-sentence paragraphs of announcement before a single code cell - “The following code plots sequences …”, “The following graphs report values for the value function parameters …”, “We’ll vary \(\beta\) while keeping a small \(c\).”, “After that we’ll study consequences of raising \(c\).”, “We’ll watch how the decay rate \(d_1\) … is affected” - and the cell that follows at 1499-1503 uses \(c = 2\), which is not small relative to the \(c \in \{1, 10, 100\}\) the next cell uses. 1532-1535 closes the comparative statics with two sentences that assert nothing checkable: “The above panels for an \(\alpha = 4\) setting indicate that \(\alpha\) and \(c\) affect outcomes in interesting ways” and “We leave it to the reader to explore consequences of other constellations of parameter values” - where 1367-1377, 1401-1408 and 1421-1424 had each stated a specific prediction and checked it. And three sentences are garbled: “the value of attained by the government” at 318 and again at 321, “is greater than the value \(V(\theta_\infty^R)\) and of the continuation value \(J(\theta_\infty^R)\)” at 1341, and “the recursive structure structure of the Ramsey problem” at 75.

  • [qe-writing-008] — Remove excessive whitespace between words. Count: 242. Lines: 38, 41, 43, 45, 46, 51, 57, 59, 61, 63, …. Example: 2 spaces.

Medium severity#

  • [qe-fig-003] — No matplotlib embedded titles. Count: 2. Lines: 1263, 1463. Example: .set_title.

  • [qe-link-002] — Use doc links for cross-series references. Count: 4. Lines: 67, 193, 288, 765. Example: raw link to python-intro.quantecon.org.

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

  • [qe-writing-001] — Use one sentence per paragraph. Count: 2. Lines: 287, 416. Example: 2 sentences in one paragraph.

  • [qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 79, 432, 1297, 1525. Example: the section that explains the lecture’s organising idea cites the wrong two equations. “Note on dynamic programming squared” (423-437) says “equation {eq}`eq_old1` expresses how \(\theta_t\) depends on \(\mu_t\) and \(\theta_{t+1}\)” - but eq_old1 (112) is the Cagan money-demand function \(m_t - p_t = -\alpha(p_{t+1}-p_t)\), and the equation that relates \(\theta_t\) to \(\mu_t\) and \(\theta_{t+1}\) is eq_old2 (136) - and it says “equation {eq}`eq_old4` expresses how value \(v_t\) depends on \((\mu_t, \theta_t)\) and \(v_{t+1}\)”, where eq_old4 (189) is the law of motion \(x_{t+1} = Ax_t + B\mu_t\) and the value recursion is eq_old8 (302). So both halves of the passage that names the technique point at equations that do not do what the sentence says. Second, the install cell is duplicated: 28-34 says “this lecture will need the following libraries” and runs !pip install --upgrade quantecon, and 77-83 says “this lecture will use the following libraries” and runs the identical cell again. Third, generate_table accepts a dig argument and then discards it: 1297 formats each value as f'{round(val, dig):.3f}', so the call at 1398 with dig=4 rounds to four digits and prints three, and the table the prose introduces as more precise is identical in precision to the one at 1383. Fourth, the cell comment at 1525 reads # Increase c to 100 in a cell whose stated purpose at 1521-1522 is to raise \(\alpha\) “from its default value \(\alpha=1\) to \(\alpha=4\)” - and the cell varies \(c\) over \([10, 100]\) at \(\alpha = 4\) only, so the \(\alpha = 1\) comparison the sentence promises is never shown.

  • [qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 4. Lines: 67, 193, 765, 817. Example: mid-sentence ‘Control’.

  • [qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 3. Lines: 45, 220, 251. Example: 220 sets a defined term in double backticks, so bliss level renders as inline code in the middle of a sentence of prose - the one place the lecture names the object that {eq}`eq:Friedmantheta` computes, and the code comment at 949 calls it the same thing. 45 italicises liquidity where the term is being introduced (“increasing a representative agent’s liquidity, as measured by his or her holdings of real money balances”), while every other defined term in the lecture is bolded - time inconsistency (38), Ramsey plan (55), rational expectations and perfect foresight (122), policy (329), dynamic programming squared (426), Markov perfect equilibrium (412), credible government policy and sustainable plan (417). And 251 uses bold for emphasis rather than definition: “balances the costs of imposing the distorting taxes … against the benefits that expected deflation generates”, where the italic used correctly at 373-375 (what, when, assumes) and 1554 (adverse consequences) is the right tool.

  • [qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 369, 1027, 1263. Example: the three timing protocols are the spine of the lecture and are laid out entirely in prose across fifty lines (369-419): the three distinguishing dimensions are named at 373-378 (what is chosen, when, what is assumed about expectations), then restated as two paragraphs at 380-389, then as a three-item list at 396-405, then as three separate one-line sentences at 408-412, then extended by a {note} about a fourth protocol at 415-419 - where one table with the three protocols as rows and those same three dimensions as columns would replace all of it, and the lecture already has table machinery (generate_table, 1287-1300). Second, hide-input is applied to some figure cells and not others: 1027, 1350, 1382 and 1439 hide their plotting code while 1388, 1397, 1412, 1499, 1510 and 1524 - which call the same helpers - show theirs, so a reader scrolling the comparative-statics section meets alternating walls of code and clean figures. Third, the two embedded titles at 1263 and 1463 carry the parameter values that distinguish the panels (fr'$\beta$={clq.β}, $c$={clq.c}'), so they are the one piece of information a reader needs to tell the three panels apart, and the qe-fig-003 fix has to move them into a caption rather than delete them.

Low severity#

  • [qe-fig-008] — Use lw=2 for line charts. Count: 1. Lines: 1454. Example: plot() without lw=.

Strengths#

  • The three timing protocols are distinguished along three dimensions stated in advance - what a policymaker chooses, when it chooses, and what it assumes about the effect of its choice on the representative agent’s expectations (371-378) - so the later comparisons of \(V(\mu^{MPE})\), \(V(\mu^R_\infty)\) and \(V(\mu^{CR})\) rest on a declared basis rather than on intuition.

  • The reduction from money demand to a two-dimensional LQ problem is visible at every step: the Cagan demand function (109-113), differenced to give {eq}`eq_old2` (125-137), the coefficient checked to be inside the unit circle (139), solved forward to {eq}`eq_old3` (147-151), and written in state-space form (164-190) - with 199 pointing out that \((1+\alpha)/\alpha > 1\) is an eigenvalue that “threatens to destabilize” the system and 202 saying what will handle it.

  • Chang’s insight is isolated, labelled and then used: 153-157 states that \(\theta_t\) intermediates how all of \(\mu_{t+j}\) bears on time-\(t\) real balances, that an equivalence class of continuation sequences delivers the same \(\theta_t\), and that this is what simplifies the policy problems - and 159-160 immediately draws the consequence that future money creation influencing earlier inflation is why timing protocols matter.

  • One yardstick is defined once and used throughout: {eq}`eq:barvdef` gives \(V(\bar\mu) = s(\bar\mu,\bar\mu)/(1-\beta)\), and 316-321 names in advance the three values of it that will matter - \(V(\mu^{MPE})\), \(V(\mu^R_\infty)\) (flagged there as the worst continuation value along a Ramsey plan) and \(V(\mu^{CR})\) - which are exactly the three horizontal lines the later figures draw.

  • ChangLQ.__init__ calls six named methods in order (913-918) - setup_LQ_matrices, solve_LQ_problem, compute_policy_functions, simulate_ramsey_plan, compute_θ_range, compute_value_and_policy - so any computed object can be located from its name, and the closed-form MPE and constrained-Ramsey rates are given directly (953-959) rather than solved numerically.

  • Each comparative-statics experiment states in advance what should and should not move, and then checks it: 1367-1377 predicts that varying \(\beta\) shifts \(\theta_\infty^R\) and \(\theta_0^R\) but leaves \(\theta^*\), \(\theta^{CR}\) and \(\theta^{MPE}\) alone, and gives the three closed forms that imply it; 1401-1408 does the same for \(c\) and adds the \(c \to \infty\) limit; 1421-1424 takes \(c \to 0\) and explains the collapse to Friedman’s rate as the disappearance of the tax-distortion wedge Calvo introduced.

  • The {note} at 415-419 does real work: it names the fourth timing protocol the lecture will not cover, says exactly what a policymaker believes under it, names the resulting object (credible government policy, sustainable plan), points at calvo_abreu, and cites the literature - so the omission is bounded rather than silent.