tsyrennikov_2013#
Series: lecture-python-advanced.myst
File:
lectures/tsyrennikov_2013.mdAudit date: 2026-08-26
Corpus snapshot:
b83d6da399Categories 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 |
|
Math |
5.5/10 |
|
Code |
5.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
5/10 |
|
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, thel/O/Irule) 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λ_valorlamwould be both legal and closer to the mathematics;Ifor 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 theconfig.updatecall below the imports keeps the same effect. And 2163 and 2250 create the figure withfig, ax = plt.subplots()and then define a function and run a print loop for twenty-five lines before the firstax.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 ofn_1', 19 ofn_2', 6 of baren'), 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) andv_{\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\Prhalf of theqe-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 aNamedTuple” 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 callingcreate_model, anddefault_values_for_deltatakes \(\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,unconditionalpaths), 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 inax.set_titlecalls (1880, 1889, 1899, 1909, 1923, 1936), which is whatqe-fig-003flags, 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_modelvalidates 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
mystnbcaptions andfig-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).
Recommended actions#
Either add the model-moments table that 136 promises (“Here and in the moments table below”) or drop the forward reference - the lecture has one table, the data moments at 144-148, and never puts the model’s \(\sigma(c)/\sigma(y)\), \(\rho(c,y)\), \(E(r)\), \(\sigma(r)\), \(\rho(r,y)\) and \(\rho(tb,y)\) beside them, even though the solved policies and the crisis simulation make that a short cell.
Cut the answer out of Exercise 1: 2150-2152 tells the reader what happens at \(\delta = 1\) and as \(\delta \to 0\), which is the substance of the solution at 2207-2219.
Move the
!pip install jaxcell from 743 to the top of the lecture (qe-code-003) - it currently sits 730 lines in, after the whole theory section.Delete or fold in 514-551: the
{prf:proof}at 455-511 has already made this argument, including the \(g(Y_2 \mid 0) = 0\) step and the conclusion that the spread can be raised to zero.Decide whether the parameters live in the
ModelNamedTuple or in module globals: 805-807 unpacks the model into nine globals that the jitted functions close over, socreate_model’s validation never runs for the exercises, which threadβ_val=overrides throughautarky_vfiandmh_vfiinstead (2165-2168, 2257-2259).Move the six panel letters from
ax.set_title(1880, 1889, 1899, 1909, 1923, 1936) into the figure caption or into an axes annotation before removing the titles forqe-fig-003, since “Panel A” through “Panel F” are referenced seven times in the prose (1844, 1943, 1954, 1967, 1981, 1992).Rename
l = λ(I)at 894 and 2177 (PEP8 E741, and inconsistent with the unicodeλthe file uses everywhere else), and move theconfig.update("jax_enable_x64", True)call at 758 below the import block.Fix the doubled conjunction at 2132-2133 (“while the LE policy is quite different, while LE is closer to the frictionless benchmark”) and the repeated statement of the headline result at 33-37, 114-116 and 2111-2114.
Finish the mechanical items:
\Prto\mathbb{P}\{\cdot\}at 221, 222 and 2076 and the bareE(\cdot)at 136 and 144 (qe-math-010 (proposed)), “i.i.d.” at 48 and 100 (qe-writing-009 (proposed)), the threefigsize=(1781, 1854, 2045),lw=2at 2263, the 10-word caption at 1847, and the double space at 30.