time_series_with_matrices#
Series: lecture-python-intro
File:
lectures/time_series_with_matrices.mdAudit date: 2026-08-26
Corpus snapshot:
a12d17c0efCategories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 7.4 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3/10 |
|
Math |
6/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
7/10 |
|
References |
10/10 |
no mechanical violations detected. |
Links |
8/10 |
|
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: 6. Lines: 394, 401, 473, 526, 550, 637. Example: 394 names a class
population_momentswhere PEP8 asks for CapWords; the rule’s escape hatch is “unless closer to mathematical notation”, and there is no mathematics being approximated by a lowercase-with-underscores class name - contrast the Greek identifiersα_0,σ_u,μ_y,Σ_y, which are exactly the justified departure the rule has in mind. 637 writesβ ** np.arange(0, T-i)with spaces around the exponentiation operator, which the rule names explicitly (“writea**b”), and the same file gets it right at 449 (σ_u**2). Missing space after the comma in a slice at 473 (ys[i,:]), 526 (Σ_y[72:,72:]) and 550 (A_inv[0:7,0:7]). And 24 lines carry trailing whitespace, most of it inside the class - every keyword argument line of the two constructor calls (401-407, 499-504) plus the blank-but-indented lines at 428, 450 and 455; in narrative text 214 and 514 end in two spaces, which Markdown reads as a hard line break in the middle of a paragraph.[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 9. Lines: 222, 254, 315, 328, 346, 466, 486, 655, 670. Example: code-cell figure without mystnb figure metadata.
[qe-fig-008] — Use lw=2 for line charts. Count: 9. Lines: 223, 255, 316, 474, 488, 656, 657, 673, 674. Example: plot() without lw=.
[qe-math-003] — Use square brackets for matrix notation. Count: 7. Lines: 93, 100, 107, 284, 607, 613, 619. Example: array used as matrix.
[qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 7. Lines: 371, 518, 533. Example: mid-sentence ‘Distribution’.
[qe-writing-008] — Remove excessive whitespace between words. Count: 27. Lines: 40, 373, 391, 460, 462, 464, 496, 512, 516, 520, …. Example: 2 spaces.
Medium severity#
[qe-link-002] — Use doc links for cross-series references. Count: 3. Lines: 371, 518, 533. Example: raw link to python.quantecon.org.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 93, 275, 388. Example: the two stacked systems (93-114, 607-625) annotate each block with
\underset{\equiv A}{\underbrace{...}}- two nested decoration commands wrapped around a\left[ \begin{array} \right]- four times, where the lecture’s own plainer idiom twenty lines later does the same job better: 119-127 writesA y = band then names \(y\) in a separate display. The normal distribution is written two different ways: plainN\left(0, \sigma_{u}^{2}\right)at 275 and{\mathcal N}(\mu_y, \Sigma_y)at 376, so the same object carries a decoration in one place and not the other (the decoration itself is what qe-math-011 (proposed) counts; the inconsistency is the simplicity problem). And 388 writes the identity asI_{T \times T}, spelling its dimensions as a subscripted product where plain \(I\) suffices because \(T\) is fixed for the whole lecture, and writes the transpose as(A^{-1})^Trather than(A^{-1})^\top- the drafted report shows no qe-math-002 finding because the checker cannot see this shape (see scanner_doubts).\left( \right)also wraps contents that can never grow tall at 275, 302 and 590.[qe-math-011 (proposed)] — Distribution names in plain letters, not \mathcal / \mathbb. Count: 1. Lines: 376. Example: decorated distribution
{\mathcal N}.[qe-writing-001] — Use one sentence per paragraph. Count: 2. Lines: 78, 213. Example: 2 sentences in one paragraph.
[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 3. Lines: 464, 535, 543. Example: 535 is a sentence whose content is that there will be no content: “There is a lot to be learned about the process by staring at the off diagonal elements of \(\Sigma_y\) corresponding to different time periods \(t\), but we resist the temptation to do so here.” 541-547 spends four lines and a one-item bullet list getting to a single
printcall at 550: “Let’s print out \(A^{-1}\) and stare at its structure”, then a bulleted rhetorical question “* is it triangular or almost triangular or \(\ldots\) ?” (543), then “To study the structure of \(A^{-1}\), we shall print just up to \(3\) decimals” (545) - which describes nothing the cell does, since the precision was set globally at line 57 - and then “Let’s begin by printing out just the upper left hand corner” (547). And 464 has lost a conjunction: “generating \(N\) time realizations of \(y\) plotting them together with population mean \(\mu_y\)”.[qe-writing-003] (reviewer) — Maintain logical flow. Count: 3. Lines: 499, 645, 665. Example: 499-509 silently replaces the model. Line 496 says “let’s print out the covariance matrix \(\Sigma_y\) for a time series \(y\)”, but the cell instantiates
population_moments(α_0=0, α_1=.8, α_2=0, T=6, y_neg1=0., y_0=0., σ_u=1)- a first-order autoregression with zero drift and zero initial conditions, not the Samuelson second-order model the reader has followed for 400 lines - and the conclusions at 512-514 about the superdiagonal of \(\Sigma_y\) are drawn from that unannounced substitute, after which 523 switches back to the defaults just as silently. 645 does the same to the shocks:σ_u = 0.turns off the randomness the preceding three sections were built around, so both price figures (655, 670) are deterministic, while the display at 589-591 still writes \(y = A^{-1}(b + u)\) and nothing in the prose says \(u\) has been set to zero. And 665 asks the reader “Can you explain why the trend of the price is downward over time?” in a lecture that has no exercises and no solutions, so the question has nowhere to land - the one-sentence answer (the sum \(\sum_{j=0}^{T-t}\) in 596 loses a term every period) is never given.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 4. Lines: 31, 78, 85, 574. Example: definitions are set in italic about as often as in bold, and one term appears both ways. Bold is used correctly for second-order linear difference equation (29-30), national income and gross domestic product (75-76), autoregressive and moving average (40, 567, 570), second-order stochastic linear difference equation (266-267), statistical stationarity (462) and stationary (514). But multiplier-accelerator model - the model the whole lecture is built on - is introduced in italic at 31; the
{note}at 83-88 defines three terms in italic (boundary conditions 85, initial conditions and terminal conditions 86, after initial conditions already appeared in italic at 73); and the forward-looking section defines four more the same way (backward looking 574, forward looking 577, perfect foresight 579-580 and again 593). Worst, line 78 sets “Equation{eq}`tswm_1`is called a second-order linear difference equation” in italic - the same term the lecture bolded at 29-30, and 78 is the sentence that actually defines it. Genuine emphasis in italic is rare and correct (not at 512), so the file is not overusing italic; it is using it for the wrong job. One markup slip in the same family: 230 nests the emphasis inside a cross-reference label,{ref}steady statescalar-dynam:steady-state``.[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 255, 474, 488. Example: the lecture draws nine figures and never once puts two series on one set of axes where the comparison is the point. 237-238 announces the contrast between the general path and the constant steady-state path and then plots them in two separate figures (222, 254) that a reader has to flip between; the same happens for the price paths (655, 670), which differ only in the initial conditions. The lecture already knows the idiom - 656-660 plots \(y\) and \(p\) together with a legend - so it is a missed application, not a missing skill. 466-479 plots the population mean inside the sampling loop (474), so the red line is drawn a hundred times, and it is given no
labeland no legend, which means nothing on the figure identifies the one curve the figure exists to show. And 486-489 is the only figure in the file with no axis labels at all - every other plot setsxlabelandylabel- even though 492 immediately asks the reader to notice how “the population variance increases and asymptotes”, a claim about the very axes that are unlabelled.
Low severity#
[qe-fig-001] — Do not set figure size unless necessary. Count: 1. Lines: 54. Example: style override.
Strengths#
The lecture checks its own claims in code at the moment it makes them: 198-202 solves the system a second way and asserts
np.allclose(y, y_second_method), and 205 claims \(A\) is lower triangular with 209 verifyingnp.allclose(A, np.tril(A))in the very next cell - so two statements a reader would otherwise have to take on trust are executable.Both
{note}admonitions earn their place by carrying a caveat the main argument does not need: 83-88 states the two-boundary-condition requirement exactly where a reader starts wondering why \(y_0\) and \(y_{-1}\) are handed over, and 212-218 explains why the lecture keeps usingnp.linalg.invafter having just recommendednp.linalg.solve- the honest answer being thatA_invis reused later.Unicode Greek is used throughout the code as qe-code-002 asks (
α_0,α_1,α_2,σ_u,β,μ_y,Σ_y) and the naming keeps code and algebra in one-to-one correspondence even in the awkward case -y_neg1for \(y_{-1}\) at 150 with the maths spelled out in a trailing comment.The moving-average representation is read off something the reader can see rather than asserted: 549-550 prints the top-left corner of \(A^{-1}\), 553-555 states what its structure is (“every row ends with the previous row’s pre-diagonal entries”), and only then does 564 write the time-varying-coefficient moving average - and 569-570 closes the loop by naming
{eq}`eq:eqma`and{eq}`eq:eqar`as the two representations of the same system.The
lw=0.5on the two hundred-path figures (335, 353) is a correct and deliberate departure from the houselw=2, since a hundred thick overlaid lines are unreadable - and the drafted qe-fig-008 count leaves those two cells alone, so the file’s judgment and the checker’s agree.The two cross-series references that are done right are done right in the way the rule asks -
{doc}`intermediate:samuelson`at 36 and 140, with automatic titles - so the correct idiom is already in the file for the three raw URLs at 371, 518 and 533 to be rewritten against.
Recommended actions#
The seven
qe-writing-004hits at 371, 518 and 533 are false positives - do not lowercase them. The capitalised words are the titles of the lectures being linked (“Multivariate Normal Distribution”, “Linear State Space Models” twice), which are legitimately Title Case. The real defect on those three lines is the co-locatedqe-link-002: replace the rawpython.quantecon.orgURLs with{doc}`intermediate:multivariate_normal`and{doc}`intermediate:linear_models`, following 36 and 140 - which clears the link-002 findings and the spurious writing-004 ones in one edit.Say in the prose what 499-509 does: the covariance matrix printed there belongs to a first-order autoregression with \(\alpha_0 = 0\), \(\alpha_1 = 0.8\), \(T = 6\) and zero initial conditions, not to the Samuelson model, and the superdiagonal conclusion at 512-514 is drawn from it; then say that 523 returns to the default parameters.
State that
σ_u = 0.at 645 makes the whole forward-looking section deterministic, or drop \(u\) from the display at 589-591, which still presents \(y\) as random while both price figures (655, 670) are not.Fix the sampling loop at 470-474:
sample_y(N, rng=rng)is called once per iteration, so a hundred batches of a hundred paths - ten thousand draws - are generated in order to plot a hundred, andplt.plot(μ_y, color='red')redraws the same mean line a hundred times. Hoist the sample out of the loop, plotys.Tin one call, and give the mean linelabel='$\mu_y$'plusplt.legend()so the figure says what its red curve is.Answer the question at 665 in one sentence, or wrap it in an
{exercise}/{solution}pair - the lecture has no exercises, so as written it is a question with nowhere to go; the reason the price trends down is that \(\sum_{j=0}^{T-t}\) at 596 loses a term every period.Settle bold for definitions and italic for emphasis: bold multiplier-accelerator model (31), boundary conditions (85), initial conditions (73, 86), terminal conditions (86), backward looking (574), forward looking (577) and perfect foresight (579, 593); pick one form for “second-order linear difference equation”, which is bold at 29-30 and italic at 78; and move the emphasis outside the cross-reference label at 230.
Recast the four
arrayblocks asbmatrix(93-114, 284-289, 607-625, qe-math-003 x7), which also retires the\left[ \right]and\underset{\equiv A}{\underbrace{...}}scaffolding in favour of naming \(A\) and \(b\) in prose the way 119-127 already names \(y\); write(A^{-1})^\topat 388; and use plainNat 376 to match 275 (qe-math-011 (proposed)).Give the nine figure cells mystnb
caption/namemetadata (222, 254, 315, 328, 346, 466, 486, 655, 670), setlw=2on the seven single-series plots (qe-fig-008), addxlabel/ylabelto the variance figure at 488, drop the globalfigure.figsizeoverride at 54 (qe-fig-001), and merge the pairs that exist to be compared - 222 with 254, and 655 with 670 - onto shared axes with a legend.Sweep the whitespace and paragraphing: 27 internal double spaces, 24 lines of trailing whitespace (401-407, 428, 450, 455, 499-504 and others), the two of those that end in two spaces and so force a mid-paragraph line break (214, 514), and the two multi-sentence paragraphs at 78 and 213-217 (qe-writing-001).