two_auctions#
Series: lecture-python.myst
File:
lectures/two_auctions.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories audited: writing, math, code, figures, references, links (JAX out of scope)
Overall score: 6.0 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3/10 |
|
Math |
4.5/10 |
|
Code |
6.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
3/10 |
|
References |
10/10 |
no mechanical violations detected. |
Links |
9/10 |
|
Admonitions |
N/A |
no admonitions, exercises or solutions. |
Issues#
Critical#
None found.
High severity#
[qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 6. Lines: 219, 220, 407, 550, 567, 607. Example: 219 binds a lambda to a name,
b_star = lambda vi, N: ((N-1)/N) * vi(E731), with a parametervithat matches neither thev_hatof 387 nor thev_gridof 430; 220 then calls it asb_star(v,N)with no space after the comma (E231). 550 declaresclass bid_price_solution:in snake_case where PEP8 asks for CapWords. Nine lines carry trailing whitespace - 266, 407, 409, 417, 420, 495, 580, 582, 617. Four methods end with a barereturn None(567, 574, 625, 662), including__init__. 607-608 indents a continuation one column past the opening parenthesis (E127) and 617-618 and 495-496 indent theirs to a column that matches nothing (E128), while the identical construction at 528-529 is aligned correctly. And the duplicated method at 576 silently drops the docstring that documents itsorderparameter at 388-403, so the copy is undocumented while the original is documented (with “(N,R)” at 396 missing the comma space that 561 gets right).[qe-fig-001] — Do not set figure size unless necessary. Count: 8. Lines: 200, 262, 316, 437, 492, 526, 614, 646. Example: style override.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 6. Lines: 255, 315, 429, 455, 488, 525. Example: code-cell figure without mystnb figure metadata.
[qe-fig-006] — Lowercase axis labels. Count: 16. Lines: 270, 271, 327, 328, 443, 444, 460, 499, 500, 538, …. Example: axis label
Valuation, $v_i$.[qe-fig-007] — Keep figure box and spines. Count: 7. Lines: 272, 329, 446, 501, 540, 623, 660. Example: spine removal.
[qe-fig-008] — Use lw=2 for line charts. Count: 6. Lines: 264, 265, 439, 440, 495, 617. Example: plot() without lw=.
[qe-math-004] — Do not use bold face for matrices or vectors. Count: 22. Lines: 101, 165, 166, 177, 292, 303, 304, 305, 306, 356, …. Example: \mathbf.
[qe-math-014 (proposed)] (reviewer) — Braces {…} for events, parentheses (…) for sets. Count: 9. Lines: 165, 166, 303, 356. Example: every probability in the lecture takes an event as its argument and every one of them is written with parentheses. 165 has \(\mathbf{P}(y_i \leq y)\) and \(\mathbf{P}(\max_{j\neq i} v_j \leq y)\), 166 has \(\prod_{j\neq i}\mathbf{P}(v_j \leq y)\), 303 has \(\mathbf{P}(y_i < v_i)\) and \(\mathbf{P}(y_i > v_i)\), and 356 has four more, \(\mathbf{P}(y_i < v_i)\) and \(\mathbf{P}(y_i \ge v_i)\) twice each. All nine are logical conditions on random variables, which is exactly the case proposed qe-math-014 (proposed) assigns to braces - and there is no named set anywhere in the file, so nothing here should be parenthesised. Written \(\mathbb{P}\{y_i \leq y\}\) they would also pick up the blackboard operator the same lines need for qe-math-010 (proposed).
[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 5. Lines: 73, 79, 116, 145, 253. Example: 73-81 is a seven-item list under “Evidently,” whose first and third items state the same fact from opposite sides, and whose fifth item carries a nested sub-bullet. Item 79 also misnames the central object: “buyer \(i\) wants to know the probability that she wins the auction as a function of her bid \(v_i\)” - \(v_i\) is her valuation, not her bid, and the whole lecture turns on the two being different. 116-129 and 184-186 say the SPSB result three times in three places (“In a SPSB auction bidders optimally choose to bid their values” / “Formally, a dominant strategy profile … has each bidder bidding its value” / “In a SPSB, it is optimal for bidder \(i\) to bid \(v_i\)”), and 92 duplicates bullet 76 in the same way for FPSB. 253 is a 44-word bullet. Four typos: “Wikepedia” (145), “Equibrium” (345), “biders” (389), and 297 mixes prose and math mode in “The expected revenue equals n \(\times\) expected payment of a bidder”.
[qe-writing-003] (reviewer) — Maintain logical flow. Count: 6. Lines: 149, 285, 287, 363, 425, 543. Example: 543-682 “Code summary” is not a summary - it is a verbatim second copy of the working code.
evaluate_largest(576-593) repeats 407-422 line for line,compute_optimal_bid_FPSB(595-625) repeats 470-501, andplot_winner_payment_distribution(627-662) repeats 507-541; then 665-681 runs the class on the same \(\chi^2\) case, with the same seed 1337, that 456-541 has already worked through cell by cell - so the last four cells redraw three figures the reader has just seen, identically. 287 says “Above we computed that the CDF is \(F_n(y) = y^n\) and the PDF is \(f_n = ny^{n-1}\)”, but what was computed above (165-171) is \(\tilde F_{n-1}(y) = y^{n-1}\) and \(\tilde f_{n-1}(y) = (n-1)y^{n-2}\), the distribution of the maximum of the other \(n-1\) bidders; the distribution of the maximum of all \(n\) never appears. 149-155 is an H2 “Setup” whose entire content is “There are \(n\) bidders” and “Each bidder knows that there are \(n-1\) other bidders”, after 66 has already established \(n>2\) buyers. The heading structure doubles back on itself: 51 and 116 open sections on FPSB and SPSB, then 157 and 184 open two more with the same names spelled differently (“First-price sealed-bid auction (FPSB)” against “First price sealed bid auction”), and 122 “Characterization of SPSB auction” is an H2 where its twin at 94 is an H3. 363-376 re-displays{eq}`eq:optbid1`unlabelled and re-defines \(v_i\) and \(y_i\) that 104-108 already defined, with a stray colon at 376 (“\(y_{i} = \): maximum value”). And 425-427 announces the conclusion before the evidence: “We find that theevaluate_largestmethod functions well” precedes the figure that shows it (437-446).[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 5. Lines: 159, 248, 283, 332, 345. Example: the definitions are bolded correctly - surplus (70), payoffs (86), Bayesian game and Bayesian Nash equilibrium (88), Revenue Equivalence Theorem (143), payment (351) - but bold then does two other jobs. It labels six pseudo-headings that should be markdown headings: Protocols: (55, 120), Detailed Setting: (64), Expected Revenue FPSB: (283), Expected Revenue SPSB: (295), Detour: Computing a Bayesian Nash Equibrium for FPSB (345), and at 332 it wraps a raw
<center>tag to fake a table caption. And it is applied to the two acronyms inconsistently - FPSB bolded at 159 and 173 and SPSB at 186, but plain at 139, 141, 223, 279, 313, 318 and 347. The file’s only italic is_winning_at 248, written with underscores rather than the asterisks used everywhere else in the corpus.[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 5. Lines: 200, 266, 323, 332, 488. Example: the clearest object in the lecture, the FPSB/SPSB comparison table at 334-341, is captioned by wrapping a raw
<center>HTML tag in bold (332) instead of using a MyST table caption, so it cannot be numbered or cross-referenced, and no sentence in the lecture refers to it. 323-324 draws the two mean lines of the revenue-equivalence figure in green and red and labels both of them'Mean', so the legend has two identical entries in the one figure whose point is that the two means coincide. 266-267 plots 100,000 SPSB payments atalpha=0.05withmarkersize=0.1, so the payment cloud that 253 exists to explain (“there is a frequency distribution of payments for each valuation”) is close to invisible and its legend marker cannot be seen at all - a 2-d histogram or a subsample would show the distribution the sentence describes. 200 setstext.usetex: Trueglobally, which makes every figure in the lecture depend on a LaTeX installation, andsns.despine()at 272, 329, 446, 501, 540, 623 and 660 strips the spines from all seven. And six of the ten figures are duplicates: 488-501 is redrawn at 614-623, 525-541 at 646-660, and 459-461 at 569-572.[qe-writing-008] — Remove excessive whitespace between words. Count: 64. Lines: 23, 47, 51, 58, 61, 68, 80, 86, 88, 90, …. Example: 2 spaces.
Medium severity#
[qe-code-002] — Use Unicode symbols for Greek letters in code. Count: 4. Lines: 669, 673, 677, 681. Example: spelled-out
chi.[qe-fig-003] — No matplotlib embedded titles. Count: 1. Lines: 445. Example: .set_title.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 137, 179, 292. Example: 292 and 303 give the same quantity two names in adjacent displays: \(\mathbf{R}\) is “expected revenue” for FPSB and \(\mathbf{TR}\) is the SPSB total, both evaluating to \(\frac{n-1}{n+1}\), which is the section’s whole point - one symbol would make the equality visible instead of requiring the reader to match two. The subscripted expectation operators at 303-306 put the subscript inside the command, \(\mathbf{E_{v_i}}\) and \(\mathbf{E_{y_i}}\), so the conditioning variable is bolded along with the operator. 179 writes the evaluation bar as
\bigg{|}with braces around it rather than\bigg|, and applies it to \(\frac{n-1}{n}y_i\) after the ratio on the previous line has already cancelled the integrals, so the bar has nothing left to evaluate. And 137 writes the IID marker as\stackrel{\text{i.i.d.}}{\sim}where\overset{\text{IID}}{\sim}is both the simpler command and the corpus spelling.[qe-math-012 (proposed)] — Multiplication via \cdot or juxtaposition, never *. Count: 3. Lines: 285, 356. Example: * as multiplication.
[qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 4. Lines: 96, 143, 347, 368. Example: mid-sentence ‘Equilibrium’.
[qe-writing-009 (proposed)] — Write “IID” — not “i.i.d.” or “iid”. Count: 2. Lines: 137, 161. Example: i.i.d…
Low severity#
[qe-link-001] — Use markdown style links for lectures in same lecture series. Count: 1. Lines: 16. Example: full URL to own series (python.quantecon.org).
Strengths#
The density/CDF case convention is followed exactly, which is rarer in this corpus than it should be: \(\tilde F_{n-1}(y) = y^{n-1}\) for the CDF of the maximum rival valuation and \(\tilde f_{n-1}(y) = (n-1)y^{n-2}\) for its density (161-171), and the same pairing at 287 - so the derivation at 177-181 can be read without checking which object is which.
The optimal FPSB bid is derived rather than quoted: 163-171 gets the CDF of \(y_i = \max_{j\neq i} v_j\) from independence, 171 differentiates it, and 175-181 then computes \(\mathbf{E}[y_i \mid y_i < v_i]\) as a ratio of two explicit integrals down to \(\frac{n-1}{n}v_i\) - the number the code uses at 219.
The revenue equivalence theorem is used in both directions, which is what makes it worth stating: 279-309 computes the two expected revenues separately and finds them equal, and then 345-359 runs the argument backwards to derive the FPSB bidding strategy from the SPSB payment, closing with \(b(v_i) = \mathbf{E}_{y_i}[y_i \mid y_i < v_i]\).
The numerical method is validated against the case where the answer is known before being applied to the case where it is not: 430-446 plots
evaluate_largestagainst the analytic \(\frac{n-1}{n}v_i\) on a uniform draw, and only then does 449-501 turn it on a \(\chi^2\) distribution for which no closed form is offered.253 explains, before the figure, exactly why the two auctions’ payment plots look different - “Because it equals the valuation of a second-highest bidder, what a winner pays varies even holding fixed the winner’s valuation” - so the scatter at 266 and the single curve at 265 are interpretable rather than puzzling.
The comparison table at 334-341 puts winner, payment, loser payment, dominant strategy, Bayesian Nash equilibrium and seller revenue for both auctions side by side in six rows, which is the most compact statement of the lecture’s content anywhere in the file.
The simulation is seeded (204) and the seed is re-set before each independent experiment (456, 467, 666), so the printed averages at 319-320 and 530-531 are reproducible.
Recommended actions#
Delete the duplicated code in “Code summary” (543-682) or delete the inline cells it copies (387-422, 466-541). As it stands the lecture ships two copies of three functions and draws three figures twice, and the class version has lost the docstring that documents
order.Fix the false back-reference at 287: what was computed at 165-171 is \(\tilde F_{n-1}(y) = y^{n-1}\) for the maximum of the other \(n-1\) bidders, not \(F_n(y) = y^n\). Either derive \(F_n\) or restate the revenue integral at 292 in terms of the distribution that was actually derived.
Put the nine probability arguments in braces (165 twice, 166, 303 twice, 356 four times) - all are events, and there is no named set in the file - and convert
\mathbf{P},\mathbf{E},\mathbf{R}and\mathbf{TR}(22 sites) to\mathbb{P},\mathbb{E}and plain letters, moving the subscripts outside the operator at 303-306.Give the two mean lines at 323-324 distinct labels - both are currently
'Mean'in the legend of the figure whose point is that they are equal - and make the SPSB payment cloud at 266 visible, either as a 2-d histogram or by subsampling instead ofalpha=0.05, markersize=0.1.Rebuild the heading structure: 51/116 and 157/184 are two sets of top-level sections on the same two auctions under three different spellings; 122 is an H2 where its twin at 94 is an H3; 149-155 “Setup” says nothing that 66 has not said; and 283, 295, 345 and 332 are bold paragraphs standing in for headings.
Replace the six bare URLs in “References” (688-693) with
{cite}entries - the lecture already has a working citation at 26 - and turn the fullpython.quantecon.orgURL at 16 into a{doc}reference.Drop the global
text.usetex: Trueat 200, which makes every figure depend on a local LaTeX install, and the sevensns.despine()calls (272, 329, 446, 501, 540, 623, 660); then addmystnbcaption/name metadata to the six un-named figure cells, lowercase the sixteen axis labels, moveset_titleat 445 into a caption, addlw=2to the nine bareplot()calls and drop the eightfigsizeoverrides.Code cleanup: turn the lambda at 219 into a
def, add the comma space at 220, renamebid_price_solutionto CapWords, strip the trailing whitespace on 266, 407, 409, 417, 420, 495, 580, 582 and 617, drop the fourreturn Nonestatements, and align the continuations at 495, 607, 617 and 648.Sweep the remainder: the 64 double spaces, the two “i.i.d.” spellings (137, 161), the three
*multiplications (285, 356), the four mid-sentence capitalisations (96, 143, 347, 368), the stray colon at 376, and the typos “Wikepedia” (145), “Equibrium” (345) and “biders” (389).