rational_learning_re#
Series: lecture-python.myst
File:
lectures/rational_learning_re.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 8.1 / 10
Priority: LOW
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
5.5/10 |
|
Math |
7.5/10 |
|
Code |
7/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
7/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-fig-001] — Do not set figure size unless necessary. Count: 6. Lines: 490, 515, 556, 913, 959, 1003. Example: figsize=.
[qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 1. Lines: 1032. Example: non-blackboard
\operatorname{Var}.
Medium severity#
[qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 3. Lines: 378, 359, 425. Example: two functions take the same three scalars in different orders, and every call site passes them positionally.
uninformed_demand(p, XI, f, θ_grid, θ_U, σ2, μ_s, τ2)(339) endsσ2, μ_s, τ2;bayes_update(f, θ_grid, p_t, xU_t, r_t, σ2, τ2, μ_s)(378) endsσ2, τ2, μ_s. Both are called positionally fromsimulate(429-431, 435) and fromequilibrium_price(371), so a transposition of \(\mu_s\) and \(\tau^2\) produces a wrong posterior rather than an error - and with eight, nine and eleven positional parameters (339, 363, 399) the reader cannot check a call site against a signature without scrolling. Keyword arguments, or a small parameter object, would remove the whole class. Second, both root-finders carry unexplained magic brackets:brentq(foc, -50.0, 50.0, xtol=1e-10)(359) andbrentq(mc_residual, s_t - 10.0, s_t, xtol=1e-8)(374), whose upper limit of exactly \(s_t\) silently assumes \(X^I_t > 0\) by{eq}`eq:bk-price`and whose width of 10 is tied to the baseline calibration that the three exercises then vary. Third, 425’ssnap_times = {0, 5, 20, 50, 100, T}is hard-coded toT=200- at a smallerTthe later snapshots never fire and{numref}`fig-rle-posterior-density`silently loses curves - and its0entry is dead, becausesnapshotsis pre-seeded at 426 and the loop tests(t + 1) in snap_times. flake8 (--select=E1,E2,E5,E7,W2,W3,W6,F,C4 --max-line-length=79) is otherwise clean over every cell, which for 1052 lines is notable.[qe-code-002] — Use Unicode symbols for Greek letters in code. Count: 2. Lines: 348, 352. Example: spelled-out
phi.[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 3. Lines: 906, 958, 1002. Example: code-cell figure without mystnb figure metadata.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 1019, 699, 594. Example: 1019 renames a parameter for the length of one derivation: “To see why, write \(\nu=\sigma^2\) and hold the realized trade \(X^I_t\) fixed”, after which \(\nu\) carries the argument through 1026, 1032, 1034, 1040, 1044 and 1047 - so a reader arriving at exercise 3’s answer has to translate a fresh symbol back into the \(\sigma^2\) used in the previous thousand lines, and gains nothing but a shorter fraction. Second, the uninformed demand function has two different signatures. 266, 274 and 279 write \(x^U(p, X^I; f_t)\) - price, conjectured informed trade, and belief as a density - and 699, 747 and 783 write \(x^U(p, F)\), dropping the \(X^I\) argument and changing the belief from a density to a CDF, in
{prf:ref}`assum-bk-continuity`, which is the hypothesis step 1 of the proof turns on. Third, \(\Theta\) is defined twice and differently: 152 says “\(\Theta = [a,b]\) supports the unknown \(\theta^I\)”, 594 says “\(\Theta = [a,b] \times \{\theta^U\}\) collects the structural parameters”, and 652 goes back to the first (“In the two-agent example \(\Theta = [a,b]\) trivially satisfies this assumption”) - and \(\Theta\) is the space every convergence statement in the lecture is about.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 3. Lines: 823, 588, 680. Example: 823 is 42 words and carries the whole of obstacle 3 in one breath: “An equilibrium can exist in which agents assign asymptotic probability one to an incorrect model that gives the observed events positive likelihood, while the true stable price relation receives zero posterior probability because that relation was absent from the prior model class.” It splits cleanly at the “while”. 588 is 39 words and is a three-part roadmap (“We first state the two convergence results … then specialize to the two-agent example … and finally explain when those hypotheses can fail”) that would be better as the three-item list it describes. 680 is 35 words compressing a whole proof into one sentence with two subordinate clauses and a named theorem at the end. Also over 32: 268 (37), 855 (37), 859 (36), 640 (35), 779 (34). Eight sentences past 32 words in a 1052-line file whose
qe-writing-001count is zero, which is the trade the file is making - one sentence per paragraph, but some very long ones.[qe-writing-003] (reviewer) — Maintain logical flow. Count: 3. Lines: 300, 694, 284. Example: the Bayesian update silently restarts from a different posterior than the one the reader was just told the agent uses. 196-205 builds the intra-period posterior \(f_t^{(p, X^I)} \propto f_t(\theta)\phi_s(\cdot)\) and says it “is the posterior on \(\theta^I\) that the agent actually uses to forecast \(r_t\) before \(r_t\) is observed”; then
{eq}`eq:bk-bayes`at 320-324 updates \(f_{t+1} \propto f_t(\theta)\, g(s_t(\theta) \mid r_t)\) - from \(f_t\), not from the tilted version - andbayes_update(378-393) implements that faithfully. The update is right, and the reason it is right is exactly the sort of thing the reader needs and does not get: \(g(s \mid r)\) already has \(\phi_s\) as a factor (it is the posterior of \(s\) given \(r\) under the \(N(\mu_s,\tau^2)\) prior), so tilting first and updating with \(g\) would count the signal prior twice. Second, the number and membership of the convergence “ingredients” changes four times. 694 promises “Three ingredients”; 696-716 gives two as{prf:assumption}blocks and 724 gives the third in a bare sentence (“The IID assumption on \(\{s_t\}\) … supplies the ergodicity used in step 2”), so ergodicity has no label and cannot be{prf:ref}-ed; 733 then cites three assumptions of which one,assum-bk-borel, is not one of the three ingredients; and 871 lists “continuity ({prf:ref}`assum-bk-continuity`), ergodicity, and identification ({prf:ref}`assum-bk-identification`)” with the middle term still unreferenced. Third, 284-288 presents{eq}`eq:bk-price`as the outcome of “Combining the two equations”, but \(p_t = s_t - \sigma^2 X^I_t/\theta^I\) is the first line of{eq}`eq:bk-mc`(277) solved for \(p_t\) - no market clearing enters it - and 282 has already said where the real content is (“a single root-finding problem for \(p_t\)”), so a display that reads like the answer is an identity.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 2. Lines: 883, 859. Example: all three exercises use an italic line as a title:
*Off-center prior*(883),*Speed of learning across $\theta^I$*(935),*Effect of return noise*(983), each as the first body line of an{exercise}directive. The directive takes a title argument, so as written the titles do not appear in the rendered exercise header and cannot be picked up by a cross-reference - italic emphasis doing the job of a heading, which is the “overuse of emphasis formatting” the rule names. Second, 859 bolds a term it is not defining: “replaces Bayes’ rule with ordinary least squares or related recursive estimators” - OLS is not introduced here and is not this lecture’s subject, so the bold reads as emphasis. The genuine definitions are all correctly bolded - rational learning (43), safe asset and risky asset (74-75), Agent \(I\) (informed) and Agent \(U\) (uninformed) (95-96), full communication equilibrium price (134).[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 787, 590, 906. Example: the entire theory half of the lecture - 590 to 828, some 240 lines covering martingale convergence, weak convergence of regular conditional probabilities, a three-step proof and three obstacles - contains no figure at all, while the 130 lines of simulation before it contain three. Obstacle 2 is the clearest loss: 805-813 says the limiting posterior is supported on \(\{(\theta_1,\theta_2) \in [a,b]^2 : \theta_1 + \theta_2 = \theta^{I1}_{\rm true} + \theta^{I2}_{\rm true}\}\) “not on the singleton”, which is a line segment in a square with one point marked on it - one
ax.plotand oneax.scatter- and it is given in set-builder notation instead. Second, the “learning within versus learning about” section (829-863) is the lecture’s conceptual payoff and is nine paragraphs of prose contrasting two regimes on four dimensions (is the equilibrium map in the prior, Bayes or OLS, convergence guaranteed or not, does it explain where the map came from); a two-column table would carry 851-863 at a glance. Third, all three exercise figures (906-923, 958-971, 1002-1015) omitmystnbmetadata, so none of them can be{numref}-ed - and the file plainly knows the convention, because all three body figures carry a caption, anameandimage: alt:text (485-488, 510-513, 546-551).
Low severity#
[qe-fig-004] — Caption formatting conventions. Count: 1. Lines: 481. Example: caption of 7 words.
[qe-math-014 (proposed)] (reviewer) — Braces {…} for events, parentheses (…) for sets. Count: 1. Lines: 761. Example: 761 writes a membership event with parentheses: “for any subinterval \([c,d] \subseteq [a,b]\) the limiting posterior satisfies \(P_\infty^U(\theta^I \in [c,d]) = \mathbf 1_{\{\theta^I_{\rm true} \in [c,d]\}}\)”. Under the proposed rule that is the event case and wants braces, \(P_\infty^U\{\theta^I \in [c,d]\}\) - and the same line gets the indicator right, \(\mathbf 1_{\{\cdot\}}\), so the two halves of one equation use both conventions for the same condition. The lecture also gets the set case right elsewhere: 662 writes \(P_t^n(\omega)(A)\) for a named measurable \(A \subseteq \Theta\), which is exactly the parenthesis case. I am reporting this with a caveat about scope: the rule as drafted says “When writing probability using
\mathbb{P}”, and this lecture uses an italic \(P^n\) for its probability measures throughout and no\mathbb{P}at all, so a strict reading leaves 761 outside the rule. It is the only site in my batch where the event-versus-set distinction is actually in play, and if the rule is meant to be about semantics rather than about one macro, its scope should say so.
Strengths#
Every
{prf:}block is labelled and every one is actually used:prop-bk-event-convergence(618) is referenced at 636, 680, 853 and 869;assum-bk-borel(646) at 654, 669, 733, 837, 869;prop-bk-measure-convergence(666) at 684, 692, 747, 805, 853, 869;assum-bk-continuity(696) at 747, 777, 837, 871;assum-bk-identification(702) at 759, 789, 837, 871;prop-bk-sharpening(728) at 769. In a 1052-line theory lecture that is what makes the argument navigable.The density-versus-CDF convention is followed exactly and held for 550 lines: lowercase \(f_t\), \(f_0\), \(f_t^{(p,X^I)}\), \(\phi_s\), \(g\) for densities (188, 199, 249, 311, 320, 731) and uppercase \(F_t\), \(F_\infty\) for the CDF of the same posterior (690, 692, 705, 736, 747), with 690 saying in words which is which (“Write \(F_t\) for the CDF of agent \(U\)’s posterior”). This is precisely what the proposed
qe-math-015(proposed) asks for.The uninformed agent’s problem is derived rather than quoted: 216-262 goes from CARA utility through the normal moment-generating formula to the tilted weight
{eq}`eq:bk-weight`and the first-order condition{eq}`eq:bk-foc`, and 264 then reads the answer back in words (“\(X^I\) multiplied by a tilted expectation of \(1/\theta^I\)”), so the reader knows what the integral ratio is before meeting it in code.The code implements that FOC in logs with a max-shift for stability (352-356) and wraps the \(\log 0\) of a zero-density prior in
np.errstate(345-346), so the root-finder is numerically honest at the ends of the grid rather than accidentally working.The simulation is checked against a benchmark derived independently in the text:
{eq}`eq:bk-full-info-trade`at 293-296 is obtained analytically from the point-mass limit of{eq}`eq:bk-foc`, and 553-554 recomputes it to draw as the dashed reference line in{numref}`fig-rle-trade-price`- so 578’s convergence claim is a comparison against a number the reader can verify by hand.Each obstacle section says which step of the proof it breaks (777 “step 1 of the proof breaks”, 789 “step 3 breaks even when steps 1 and 2 succeed”) and obstacle 2 supplies a concrete counterexample rather than an abstraction: with two informed agents the full-communication price depends on \(\theta^{I1}, \theta^{I2}\) only through their sum (793-803), so the posterior converges to a level set.
638-642 states the qualification most treatments omit: the almost-sure statement in
{prf:ref}`prop-bk-event-convergence`is relative to agent \(n\)’s own prior, so mutually singular priors need not converge simultaneously on a common positive-probability event.Exercise 3 is built so the obvious guess is wrong: 985 states it (“Larger \(\sigma^2\) widens the conditional density … which one might guess slows learning”), 987 states the competing effect, and 1037-1049 resolves it with an explicit signal-to-noise calculation. I checked the algebra at 1040-1044 and it is right - the ratio does simplify to \(\frac{|X^I_t|}{\theta^2}\sqrt{\nu(\nu+\tau^2)/\tau^2}\), which is increasing in \(\nu\).
Citations are handled correctly throughout: 21
{cite:t}uses and no bare{cite}, soqe-ref-001measures zero - the only file in this batch of which that is true.All three body figures carry a caption, a
nameandimage: alt:text (485-488, 510-513, 546-551), which is more accessibility metadata than most of the corpus provides.
Recommended actions#
Say at 317-324 why the update starts from \(f_t\) rather than from the intra-period posterior of 199-203 - because \(g(s \mid r)\) already contains \(\phi_s\), so tilting first would double-count the signal prior. The code is right; only the reader is stranded.
Give ergodicity a
{prf:assumption}block of its own so that 694’s “Three ingredients”, 733’s three references, 769’s three names and 871’s three names are the same three things - at present 724 supplies the third ingredient in an unlabelled sentence and 733 substitutesassum-bk-borelfor it.Fix the two signatures of the uninformed demand: \(x^U(p, X^I; f_t)\) at 266-279 against \(x^U(p, F)\) at 699, 747 and 783.
{prf:ref}`assum-bk-continuity`is the hypothesis step 1 of the proof rests on, so the argument list there has to be the one the model defines. And settle \(\Theta\), defined as \([a,b]\) at 152 and 652 and as \([a,b] \times \{\theta^U\}\) at 594.Draw obstacle 2: the level set at 808 is a line in the unit square with the true point marked, and the section is the clearest illustration of what identification failure means. Add
mystnbcaption and name metadata to the three exercise figure cells (906, 958, 1002), which is the whole of the draftedqe-fig-005finding.Move the three exercise titles into the directive argument -
```{exercise} Off-center priorrather than an italic first line (883, 935, 983) - so they render as titles and can be referenced.Pass \(\sigma^2\), \(\mu_s\) and \(\tau^2\) by keyword, or bundle the parameters:
uninformed_demandendsσ2, μ_s, τ2andbayes_updateendsσ2, τ2, μ_s, and both are called positionally, so transposing two of them yields a wrong answer silently.Drop the alias \(\nu = \sigma^2\) at 1019 and write the exercise-3 derivation in \(\sigma^2\); also close the display at 1045 with a full stop rather than a comma before 1047’s new sentence.
Rewrite 284-288 to say what it actually is -
{eq}`eq:bk-price`is{eq}`eq:bk-informed-demand`rearranged, and the equilibrium content is the root-finding problem 282 names - and split the three long sentences at 823, 588 and 680.Sweep the mechanical items: the six
figsize=overrides (490, 515, 556, 913, 959, 1003), the 7-word caption at 485 cut to six, and\mathbb{V}for the\operatorname{Var}at 1032.