long_run_risk_operator#
Series: lecture-python.myst
File:
lectures/long_run_risk_operator.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 7.7 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3/10 |
|
Math |
7/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
6.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-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 5. Lines: 1466, 1681, 2045, 2599, 2954. Example: fifteen expressions surround
**with spaces where the rule asks explicitly fora**b- 1695, 1696, 1703, 1704, 1718, 1721, 1956, 1957, 1961, 1962, 2469, 2471, 2599, 2600, 2876 (disc = (λ + μ + r1) ** 2 - 4 * μ * r1). 1466-1467 and 3028-3030 put a space after the opening bracket of an array literal (np.array([[ 0.0, -0.20],,[ 0.20, -0.50, 0.30]), which PEP8 lists as E201, and pad with double spaces for column alignment. 1681-1691 unpacks eleven string-keyed dict entries one per line because the model parameters are adictrather than aNamedTuple, which also puts unicode Greek inside string literals where no tool can see it, and 2597-2604 then rebuilds one withdict(params_sdf)and five overrides. 2045, 2051 and 2066 repeat the magic floormax(Xf[k], 1e-10)three times without naming it. And 2954 names the loop variableslpandlrp.[qe-fig-008] — Use lw=2 for line charts. Count: 7. Lines: 2146, 2150, 2154, 2155, 2161, 2162, 2163. Example: plot() without lw=.
[qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 4. Lines: 391, 955, 1011, 1066. Example: non-blackboard
\Pr.[qe-writing-001] — Use one sentence per paragraph. Count: 6. Lines: 747, 900, 2764, 2992, 3215, 3278. Example: 2 sentences in one paragraph.
[qe-writing-008] — Remove excessive whitespace between words. Count: 14. Lines: 34, 44, 52, 121, 143, 179, 213, 248, 962, 1002, …. Example: 2 spaces.
Medium severity#
[qe-fig-004] — Caption formatting conventions. Count: 2. Lines: 1405, 2610. Example: caption of 9 words.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 2. Lines: 2948, 3025. Example: code-cell figure without mystnb figure metadata.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 4. Lines: 391, 2419, 2699, 2996. Example: \(V\) carries two unrelated meanings: the valuation functional, defined at 408-413 and given the semigroup \(\{\mathbb V_t\}\) at 391, and the Lyapunov function of the existence argument at 2698-2703 (“there is a function \(V \geq 1\) on the state space” with \(\mathbb A V / V \leq a_0\)).
\mathbbitself does three jobs - expectation (\(\mathbb{E}\), everywhere), the generator (\(\mathbb A\), 881-885, 2703) and the five semigroups (\(\mathbb M_t\), \(\mathbb S_t\), \(\mathbb V_t\), \(\mathbb G_t\), \(\mathbb Q_t\), 386-393) - which is what makes \(\mathbb V_t\) ambiguous with the variance operator. The affine displays at 2398-2440 stack three index dimensions on every symbol (\(\bar\beta^v\), \(\beta_f^v\), \(c_o^v\), \((\gamma_f^s+\gamma_f^v)^2\), \((c_o^v)^2\frac{\sigma_o^2}{2}\)) with no notation table anywhere in 3400 lines, so a reader meeting{eq}`eq:valuation-rho-affine`must hold functional, factor and coefficient-type simultaneously. And 2996 writes the twisted stationary distribution as \(\hat\varsigma\) - a final-sigma variant - in a lecture where \(\sigma_f\) and \(\sigma_o\) are the diffusion coefficients, so the two share a glyph family for no gain over a plain letter.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 4. Lines: 44, 2095, 2172, 2659. Example: line 44-46 inverts and then overloads: “At center stage will be a stochastic discount factor process and a return process that are multiplicative across time in the sense that conditional expectations define a semigroup of valuation operators indexed by horizon \(t\)” is 38 words carrying the two primitives, the multiplicativity property and the definition of the semigroup. Line 2095 says the identity error is “up to machine precision” where the sense wanted is at machine precision. Line 2172 is a sentence that could describe any figure in any lecture. And 2659 and 2764-2766 break the file’s own one-sentence-per-paragraph discipline with semicolon-joined compounds (“For finite-state chains and the affine model, it really is; Perron-Frobenius theory and closed-form algebra handle every requirement”; “In the finite-state case, all four follow from one Perron-Frobenius calculation; in the affine model, they reduce to picking the right root of a quadratic. In general, each must be checked separately.”) - three sentences in one block in the second case.
[qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 1772, 1956, 2560, 2948. Example: the “### Recursive preferences (optional)” section runs 125 lines (1772-1896) and the lecture then twice says it will not use it - 1792 “the numerical example uses the simpler Breeden parameters above” and 1896 “The numerical example below uses the simpler Breeden specification” - so the reader is asked to work through a derivation whose only role is to be set aside. Lines 1956-1968 recompute the discriminant, the two \(c_f\) roots and the twisted mean reversion that
solve_affine_eigenfunctionalready computes at 1695-1712, re-inlining even themean_reversionhelper defined at 1709, so the root-selection demonstration and the solver can drift apart. Line 2544 announces that stability of the growth-twisted process “needs three conditions”, lists them at 2546-2558, and then 2560 adds “The Feller inequality is necessary but not sufficient on its own” with no stated relation to the list, immediately followed by a{note}at 2562-2567 making a third point. And the two exercise-solution figures (2948, 3025) carry nomystnbmetadata where all ten body figures carrycaptionandname, so exercise 3’s instruction to “Plot … on a logarithmic scale” (3002-3013) produces an uncaptioned figure that cannot be{numref}-referenced.[qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 4. Lines: 699, 966, 2557, 2672. Example: mid-sentence ‘Assumption’.
[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 3. Lines: 2192, 2727, 2740. Example: the lecture’s bold/italic discipline is otherwise the best in this batch - every one of its twenty-plus defined terms is bold (principal eigenvalue 67, generator 106, valuation operator 336, local martingale restriction 498, twisted probability measure 951, Girsanov construction 2675, resolvent operator 2709, and the rest inside
{prf:definition}directives) and its emphasis is italic (short end 34, long end 39, any 999, local 964, immediate/cumulative 2188-2189, rejected 2689, existence 2695). Three slips: 2192-2193 puts the closing full stop inside the italic span (*plus a persistence correction.*); 2727, 2732 and 2743 use bold for run-in step labels inside a numbered list (**Irreducibility for the resolvent.**,**Nummelin minorization.**,**Eigenfunction extraction.**), which are headings rather than definitions; and 2740 then italicises minorization function, which is a definition, eight lines after bolding the label of the step that introduces it.[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 4. Lines: 370, 2161, 2725, 2948. Example: the bottom-right panel of the lecture’s title figure (2161-2166) plots \(\exp(\rho t)\), \(\hat M_t\) and \(\phi(X_0)/\phi(X_t)\) on one linear axis over \(t \in [0, 40]\); the exponential trend spans orders of magnitude the other two do not, so the martingale and transient components - the two the lecture exists to explain - are flattened onto the axis, and 2172’s “The figure shows how the three components evolve over time” is all the prose the reader gets. The semigroup identity at 370-384 is explained as a choice between two discounting routes and is exactly a two-path commuting diagram, drawn in no form. The dependency chain at 2725-2762 - which assumption buys which conclusion, across three failure modes and four rows of a table - is the lecture’s structural spine and is carried by a markdown table and three prose subsections. And the lecture has no picture at all of the eigenfunction \(\phi\) it spends 300 lines constructing:
solve_affine_eigenfunctionreturns \(c_f\) and \(c_o\), so \(\phi(x) = \exp(c_f x^f + c_o x^o)\) is one contour plot away, and the finite-state \(\phi\) is a two- or three-vector already printed as numbers at 1475 and 3043-3045.
Low severity#
[qe-fig-001] — Do not set figure size unless necessary. Count: 1. Lines: 2144. Example: figsize=.
Strengths#
The destination is on the first page:
{eq}`eq:hs-factorization`appears at 58-63 with all three factors glossed in a bulleted list (67-74), the finite-state special case named as Perron-Frobenius (76-77), and a five-step plan at 101-117 that the section headings then follow in order.The formal apparatus is carried entirely by labelled
{prf:definition}directives - one-parameter semigroup (348), multiplicative semigroup (357), SDF (400), valuation functional (408), growth functional (416), cash-flow valuation semigroup (437), generator eigenfunction (878), martingale component and twisted measure (946), Harris recurrence (1059), stochastic stability (1083) - and later prose points back with{prf:ref}(488, 3278) instead of restating them.The semigroup identity is given its economics before it is used: 373-381 calls it the Markov law of iterated values and spells out the two discounting routes explicitly, then 383-384 identifies it as the operator-level form of no-arbitrage across horizons.
The lecture names the gap in its own argument and shows what survives without closing it: 962-964 states that the verification gives only a local martingale, 966-972 quotes Assumption 6.1 of
{cite:t}`HansenScheinkman2009`verbatim and says “We carry this assumption from here on”, and 974-986 derives the one-sided bound \(\mathbb M_t \phi \leq \exp(\rho t)\phi\) that holds regardless.The indeterminacy of the growth/payoff split is raised exactly where it arises: the
{note}at 448-471 exhibits the whole family of alternative factorizations \(D_t = D_0[G_t\varphi(X_t)/\varphi(X_0)][\psi(X_t)\varphi(X_0)/\varphi(X_t)]\), states the martingale normalisation that resolves it, and says the eigenfunction construction will pick which martingale.Both numerical checks are run and their logical status is distinguished before either is reported: 2016-2019 says the algebraic identity is automatic for any \((\rho, \phi)\) so its error is round-off, 2021-2023 says the substantive test is \(\mathbb{E}[\hat M_t] = 1\), and 2128-2134 reports mean, standard error and z-statistic at four horizons rather than a single number.
Root selection is demonstrated rather than asserted: 1944-1968 recomputes both algebraically valid \(c_f\) roots and prints the twisted mean reversion for each, so the reader sees stability rather than algebra picking the eigenfunction - and 2689-2691 cites that experiment back when discussing what can go wrong.
Probability notation applies the events-versus-sets convention with judgment (qe-math-014 (proposed)): 955 writes \(\widehat{\Pr}(F \mid X_0=x)\) with parentheses because \(F \in \mathcal F_t\) is a named set, and 1066 writes \(\widehat{\Pr}\{\int_0^\infty \mathbf 1_{\{X_t \in \Lambda\}}\, dt = \infty \mid X_0 = x\}\) with braces because that argument is a logical condition - both correct, in the same lecture.
The failure modes get their own section with one subsection each (2665, 2680, 2693), a four-row table mapping each desired conclusion to the assumption that buys it (2757-2762), and a closing statement of which of them the two worked examples discharge for free (2764-2766).
Recommended actions#
Decide what the recursive-preferences section is for: 1772-1896 develops it over 125 lines and 1792 and 1896 both then say the numerical work uses the Breeden specification instead - either use it or move it to an exercise.
Refactor
solve_affine_eigenfunctionto expose both \(c_f\) candidates and their mean reversions, so the root-selection cell at 1956-1968 stops duplicating the discriminant, the roots and themean_reversionhelper from 1695-1712.Rescale the bottom-right panel at 2161-2166 - a log axis or three stacked panels - because \(\exp(\rho t)\) over 40 units of time hides \(\hat M_t\) and \(\phi(X_0)/\phi(X_t)\), and replace 2172 with a sentence saying what the reader should see in each component.
Plot the eigenfunction: \(\phi(x) = \exp(c_f x^f + c_o x^o)\) is one contour plot from the \(c_f\), \(c_o\) that
solve_affine_eigenfunctionalready returns, and the finite-state \(\phi\) is currently only printed as numbers (1475, 3043-3045).Convert the parameter dicts to
NamedTuples - 1681-1691 unpacks eleven string keys by hand and 2597-2604 rebuilds one withdict(...)plus overrides - which also takes the unicode Greek out of string literals.Rename one of the two \(V\)’s: the valuation functional (391, 408-413, with semigroup \(\mathbb V_t\)) and the Lyapunov function (2698-2703, appearing as \(\mathbb A V / V\)) share the letter in the same lecture; and add a notation table for the \((\beta, \gamma, \kappa, c)\) superscript/subscript scheme that
{eq}`eq:valuation-rho-affine`and{eq}`eq:growth-functional`depend on.Give the two structural arguments their diagrams: a two-route commuting diagram for the semigroup identity of 370-384, and a dependency diagram for the assumption chain of 2725-2762.
Clear the mechanical list: write
a**bin the fifteen**sites (1695-1704, 1718-1721, 1956-1962, 2469-2471, 2599-2600, 2876), addlw=2to the seven bare plot calls (2146-2163), give the two exercise figuresmystnbcaption/name metadata (2948, 3025) and shorten the captions at 1405 and 2610, brace\mathbb Vat 391 and write\widehat{\mathbb P}for\widehat{\Pr}at 955, 1011 and 1066, drop the space after[at 1466-1467 and 3028-3030, un-italicise the full stop at 2192, promote the three bold run-in labels at 2727, 2732 and 2743, and remove the fourteen double spaces.