rational_learning_re#

  • Series: lecture-python.myst

  • File: lectures/rational_learning_re.md

  • Audit date: 2026-08-26

  • Corpus snapshot: e25fdf2345

  • Categories 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

qe-writing-005 ×2; qe-writing-003 ×3; qe-writing-002 ×3, +1 more.

Math

7.5/10

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

Code

7/10

qe-code-002 ×2; qe-code-001 ×3.

JAX

out of scope

JAX rules target lecture-jax.

Figures

7/10

qe-fig-005 ×3; qe-fig-004 ×1; qe-fig-001 ×6.

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 from simulate (429-431, 435) and from equilibrium_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) and brentq(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’s snap_times = {0, 5, 20, 50, 100, T} is hard-coded to T=200 - at a smaller T the later snapshots never fire and {numref}`fig-rle-posterior-density` silently loses curves - and its 0 entry is dead, because snapshots is 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-001 count 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 - and bayes_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.plot and one ax.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) omit mystnb metadata, so none of them can be {numref}-ed - and the file plainly knows the convention, because all three body figures carry a caption, a name and image: 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}, so qe-ref-001 measures zero - the only file in this batch of which that is true.

  • All three body figures carry a caption, a name and image: alt: text (485-488, 510-513, 546-551), which is more accessibility metadata than most of the corpus provides.