calvo#
Series: lecture-python-advanced.myst
File:
lectures/calvo.mdAudit date: 2026-08-26
Corpus snapshot:
b83d6da399Categories 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 |
|
Math |
5.5/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
7/10 |
|
References |
8.5/10 |
|
Links |
8/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: 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_problemandcompute_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 bedefs, 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) andax.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 setsself.θ_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}\)” - buteq_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}\) iseq_old2(136) - and it says “equation{eq}`eq_old4`expresses how value \(v_t\) depends on \((\mu_t, \theta_t)\) and \(v_{t+1}\)”, whereeq_old4(189) is the law of motion \(x_{t+1} = Ax_t + B\mu_t\) and the value recursion iseq_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_tableaccepts adigargument and then discards it: 1297 formats each value asf'{round(val, dig):.3f}', so the call at 1398 withdig=4rounds 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 100in 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 levelrenders 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-inputis 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 theqe-fig-003fix 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 atcalvo_abreu, and cites the literature - so the omission is bounded rather than silent.
Recommended actions#
Fix the two equation references at 432 and 434: the relation between \(\theta_t\), \(\mu_t\) and \(\theta_{t+1}\) is
{eq}`eq_old2`(136), not{eq}`eq_old1`, and the value recursion is{eq}`eq_old8`(302), not{eq}`eq_old4`- as written, the section that names “dynamic programming squared” cites neither of the two Bellman equations it is about.Make
generate_tablehonour itsdigargument: 1297 hard-codes:.3fafterround(val, dig), so thedig=4call at 1398 produces the same three decimals as thedig=3call at 1383.Delete the duplicated install cell at 77-83 (the same
!pip install --upgrade quanteconalready runs at 28-34) and fix the comment at 1525, which says# Increase c to 100in the cell that 1521-1522 introduces as raising \(\alpha\) from 1 to 4.Strip the trailing whitespace from the 151 lines that carry it and the 242 runs of double spaces in the prose (qe-writing-008); both are single-pass edits and together they touch a quarter of the file.
Set the
bliss levelat 220 as bold rather than inline code, bold liquidity at 45 where the term is introduced, and move the emphatic costs/benefits at 251 to italic.Replace the four prose passes over the three timing protocols (373-378, 380-389, 396-405, 408-412) with one table whose columns are the three dimensions 373-378 already names, keeping the
{note}at 415-419 as the pointer to the fourth protocol.Tidy the code cells: convert the two attribute lambdas at 962 and 964 to methods (E731), split the compound
ifat 1259 (E701), correct the four docstrings that call module-level functions “Method to …” (1031, 1047, 1443, 1469), name the positional60at 1071 ass=60, and useclq.θ_CRrather thanclq.μ_CRon the \(\theta\) panel at 1458.Apply
hide-inputconsistently to the comparative-statics figure cells - 1027, 1350, 1382 and 1439 hide their plotting code while 1388, 1397, 1412, 1499, 1510 and 1524 show theirs - and move the panel-distinguishing \(\beta, c\) titles at 1263 and 1463 into figure captions before removing them for qe-fig-003.Finish the mechanical items: the ten apostrophe transposes to
\top(272, 485, 489, 501 - all genuine, including thebmatrix'at 272), the fivefigsize=,lw=2at 1454, the four raw links to{doc}(67, 193, 288, 765), the three{cite}that should be{cite:t}(122, 153, 445), the mid-sentence capitals at 67, 193, 765 and 817, “respectfully” for “respectively” at 1361, “structure structure” at 75, “a sequence of policymaker” at 386, and the opaque(41.16)/(41.17)/(41.18)equation references in the comments at 934, 938 and 941, which point at numbering no longer present anywhere in the lecture.