tsyrennikov_2013#

  • Series: lecture-python-advanced.myst

  • File: lectures/tsyrennikov_2013.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.2 / 10

  • Priority: LOW

Score breakdown#

Category

Score

One-line note

Writing

4.5/10

qe-writing-001 ×4; qe-writing-009 (proposed) ×2; qe-writing-003 ×4, +3 more.

Math

5.5/10

qe-math-010 (proposed) ×6; qe-math-014 (proposed) ×3; qe-math-009 ×3.

Code

5.5/10

qe-code-002 ×5; qe-code-001 ×3; qe-code-003 ×1.

JAX

out of scope

JAX rules target lecture-jax.

Figures

5/10

qe-fig-003 ×6; qe-fig-005 ×2; qe-fig-004 ×1, +2 more.

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: 5. Lines: 992, 993, 2165, 2185, 2193. Example: spelled-out delta.

  • [qe-fig-003] — No matplotlib embedded titles. Count: 6. Lines: 1880, 1889, 1899, 1909, 1923, 1936. Example: .set_title.

  • [qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 6. Lines: 136, 144, 221, 222, 1004, 1955. Example: non-blackboard \Pr.

Medium severity#

  • [qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 3. Lines: 757, 894, 2177. Example: 894 and 2177 both bind l = λ(I), which is PEP8’s ambiguous single-character name (E741, the l/O/I rule) and is also inconsistent with the file’s own convention - the function being called is named with the unicode λ (820) and the quantity is \(\lambda(I)\) throughout the algebra, so λ_val or lam would be both legal and closer to the mathematics; I for investment in the same lines is E741 too but has the mathematical justification the rule allows, and should be kept. 757-758 puts a side-effecting statement in the middle of the import block - from jax import config / config.update("jax_enable_x64", True) / import jax / import jax.numpy as jnp - where PEP8 asks imports to be grouped before other code; moving the config.update call below the imports keeps the same effect. And 2163 and 2250 create the figure with fig, ax = plt.subplots() and then define a function and run a print loop for twenty-five lines before the first ax.plot, so the handle sits unused across a block of unrelated work.

  • [qe-code-003] — Package installation at lecture top. Count: 1. Lines: 743. Example: install cell at line 743 of 2335 (not near the top).

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

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

  • [qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 589, 628, 2195. Example: the apostrophe carries two meanings at once, and they meet inside single expressions. Next period’s net worth is written \(n'\), \(n_j'\), \(n_1'\), \(n_2'\) (16 occurrences of n_j', 23 of n_1', 19 of n_2', 6 of bare n'), while derivatives are written \(u'\), \(v'\), \(v''\), \(\lambda'\), \(W'\) - so 589-590 reads \(\kappa = \frac{\beta}{\beta_c} v'(n_j')[(1+\xi_j) + \mu\frac{\lambda'(I)\Delta g_j}{g(Y_j|I)}]\), in which the same mark means “derivative of” on \(v\) and \(\lambda\) and “next period” on \(n\), and 628-629 stacks \(v'(n) = \mathbb E\,v'(n_j') + \mu\lambda'(I)\sum_j \Delta g_j v'(n_j')\). The same collision runs through 577, 583, 596, 605, 615, 641-642 and 650. A subscript or an overbar for the continuation state would remove it, and would also stop the transpose detector counting all 64 of them (see scanner_doubts). Separately, the autarky value is subscripted two ways - v_{\text{aut}} in the algebra (272, 276, 281, 285, 294) and v_{\rm aut} in the figure labels (2195, 2197, 2200) - and the risk-sharing index appears as \operatorname{RSI} (724), as the dictionary key 'RSI', and as the words “risk-sharing index” in axis labels.

  • [qe-math-014 (proposed)] (reviewer) — Braces {…} for events, parentheses (…) for sets. Count: 3. Lines: 221, 222, 2076. Example: the three probability statements in the lecture write an event with parentheses: \(\Pr(Y_1 \mid I) = 1 - \lambda(I)\) and \(\Pr(Y_2 \mid I) = \lambda(I)\) at 221-222, and the axis label r'$\lambda(I) = \Pr(Y_2 \mid I)$' at 2076. The argument in each case is a logical condition on the output random variable, not a named subset of the sample space, so the proposed convention asks for braces - \(\mathbb{P}\{Y = Y_2 \mid I\}\). These same three lines are already the \Pr half of the qe-math-010 (proposed) count, so both conventions can be applied in one edit; the rest of the lecture states probabilities as the mass function \(g(Y_j \mid I)\) (190, 228, 281, 490, 568-572, 590, 597, 606, 625, 650), which is correct and needs no change.

  • [qe-writing-001] — Use one sentence per paragraph. Count: 4. Lines: 29, 2149, 2237, 2303. Example: 2 sentences in one paragraph.

  • [qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 4. Lines: 33, 114, 150, 2132. Example: the headline result is stated three times in the same words before any of it is shown: 33-37 (“The central finding is that moral hazard, not limited enforcement, does most of the work in matching several key features of emerging market economies”), 114-116 (“Tsyrennikov’s main quantitative result is that moral hazard, rather than limited enforcement, is the friction that makes the optimal contract resemble non-contingent debt and that generates the crisis-like dynamics”) and again at 2111-2114 (“A crucial result … is that limited enforcement contributes almost nothing”). The notation glossary is likewise given twice around one table: 136-142 defines \(E(\cdot)\), \(\sigma(\cdot)\), \(\rho(\cdot,\cdot)\) and the four variables, and 150-152 then re-explains three of the same symbols (“So \(\sigma(c)/\sigma(y)\) is consumption volatility relative to output, \(\rho(c,y)\) is consumption-output comovement”). And 2132-2133 has two subordinate clauses on the same conjunction: “the MH and MH+LE policies are very close to each other, while the LE policy is quite different, while LE is closer to the frictionless benchmark”.

  • [qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 136, 514, 805, 2150. Example: 136 promises a table that does not exist: “Here and in the moments table below, \(E(\cdot)\) is a mean, \(\sigma(\cdot)\) a standard deviation …” - the lecture contains exactly one table, the data moments at 144-148, and no model-moments table anywhere in its 2335 lines. Second, 514-551 spends 38 lines re-explaining the one step of the proof the {prf:proof} block has just made: 480-501 already establishes that at \(I=0\) the payoff is independent of \(n_2'\), that raising \(n_2'\) to \(n_1'\) leaves lender participation and the realised path untouched because \(g(Y_2\mid 0) = 0\), and that the spread becomes zero - and 516-548 says all of it again in shorter sentences. Third, the exercise at 2137-2153 answers itself: after asking “how does a milder default penalty, corresponding to a larger \(\delta\), affect the tightness of the enforcement constraint and, via the Euler equation, the interest rate spread?” it continues in the same sentence “At \(\delta = 1\) default carries no output penalty, so the enforcement constraint is tightest; as \(\delta \to 0\) the penalty is harsh and the constraint rarely binds” - which is the substance of the solution at 2207-2219. Fourth, 766 says “We store the parameters in a NamedTuple” and 787-802 builds one with per-parameter validation, but 805-807 immediately unpacks it into nine module-level names that every jitted function then closes over (820-833, 884-899), so the model object is never used: the two exercises that need different parameters have to thread β_val= overrides through each function (2165-2168, 2257-2259) instead of calling create_model, and default_values_for_delta takes \(\delta\) as an argument while reading \(\theta\), \(Y_1\) and \(Y_2\) from globals.

  • [qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 144, 458, 1880. Example: the lecture opens by putting six Argentina and Canada moments in a table (118-152) as the thing the model has to explain, computes a full solution and a crisis simulation, and then never scores the model against them - there is no model-moments panel or table anywhere, and 136’s forward reference to “the moments table below” points at nothing. The machinery is already present (policies, simulate_crisis, implied_R, unconditional paths), so the natural closing figure or three-column table is missing rather than infeasible. Second, the contract itself - a loan \(b\) and two repayments \(d_1, d_2\) mapping into two continuation net worths \(n_1', n_2'\), with the spread \(S = v(n_2') - v(n_1')\) as the incentive - is the object of the whole lecture and is only ever described in prose (56-100, 455-511, 720-727); one small diagram of the two-state contract with the spread marked would carry the mechanism section, the proof and the definition of the risk-sharing index at once. Third, the six panel identifiers that the prose depends on - “Panel A” (1943), “Panel B” (1954), “Panels C and D” (1967), “Panel E” (1981), “Panel F” (1992, and again at 1844) - live in ax.set_title calls (1880, 1889, 1899, 1909, 1923, 1936), which is what qe-fig-003 flags, so removing them as the rule asks would break every one of those references unless the letters move into the caption first.

  • [qe-writing-009 (proposed)] — Write “IID” — not “i.i.d.” or “iid”. Count: 2. Lines: 48, 100. Example: i.i.d…

Low severity#

  • [qe-fig-004] — Caption formatting conventions. Count: 1. Lines: 1847. Example: caption of 10 words.

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

  • [qe-writing-008] — Remove excessive whitespace between words. Count: 1. Lines: 30. Example: 2 spaces.

Strengths#

  • The two-state reduction is derived rather than assumed: 179-202 states the general mixture \(g(Y_j\mid I) = \lambda(I)g_{0j} + (1-\lambda(I))g_{1j}\) with \(\lambda\) increasing and concave, 210-216 specialises to \(g_0 = (0,1)\) and \(g_1 = (1,0)\), 218-223 reduces the probabilities to \(1-\lambda(I)\) and \(\lambda(I)\), and 227-231 records \(\Delta g = (-1,1)\) - which is then the object every subsequent first-order condition uses (571, 590, 597, 628, 632), so the sign arguments later in the lecture rest on something the reader watched being constructed.

  • The first-order-approach lemma is proved in full rather than cited: the {prf:proof} at 455-511 builds the perturbation explicitly (\(\tilde n_2' = n_1'\), equivalently \(\tilde d_2 = Y_2 - n_1'\)), checks it against each constraint separately - lender participation is unaffected because \(g(Y_2\mid 0) = 0\), the state-2 enforcement constraint is relaxed because \(v(\tilde n_2') > v(n_2')\) - and then argues both directions of the equivalence, including why the relaxed constraint can only hold when \(S > 0\).

  • The Euler equation is read, not just derived: 609-621 isolates the three things that produce immiseration (\(\beta/\beta_c \approx 0.99\), \(\Delta g_1 = -1 < 0\), concavity of \(v\)) and names the two literatures it comes from, and 623-643 then works both limiting cases - setting \(\mu = 0\) flips the inequality and gives upward drift - so the paper’s headline claim is visible as a statement about the sign of a single term.

  • The lecture states precisely how its computation differs from the paper’s: 696-707 describes the paper’s algorithm (cubic spline on \([0.2, 1.2]\), 100 nodes, sup-norm tolerance \(10^{-5}\), Appendix B’s damped borrowing-limit update), 709-730 describes the two-stage substitute it uses instead, and 720-730 explains why the polishing step exists at all - a near-zero risk-sharing index is not representable on the coarse mesh the fixed-point step uses.

  • create_model validates each parameter against the domain the theory requires, with a separate message per condition (789-802), so a reader experimenting with \(\nu \geq 1\) or \(Y_1 \geq Y_2\) gets told which assumption they broke rather than a silent wrong answer.

  • The policy-function figure is built to be compared with the paper’s Figure 3 line for line: 1857-1872 sets the paper’s own axis limits and tick positions per panel, 1841-1845 says so and explains the \(\times 10\) rescaling of panel F before the reader can misread the scale, and both figures carry mystnb captions and fig-tsy-* names.

  • The crisis simulation reports the probability of the path it plots: 2081-2084 prints \(\prod_t (1-\lambda(I_t))\) for each of the three economies, which is exactly the caveat an eight-period all-low-output path needs, and it also makes the point of the section - the MH economy’s own investment collapse is what makes that path likely.

  • The three exercises target the three results the main text uses without deriving - the default thresholds behind {eq}`eq:tsyrennikov_enforcement`, the discounting wedge behind the drift, and the envelope condition cited at 577 - and each solution derives it, with ex3 identifying exactly which two terms of the Lagrangian depend on \(n\) and why every other term contributes zero (2315-2332).