From fa069dc2b5ca9622389a1e61ac069d6afcdfbab0 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Sat, 18 Jul 2026 18:56:34 +1000 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=94=84=20resync=20two=5Fauctions.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .translate/state/two_auctions.md.yml | 6 + lectures/two_auctions.md | 217 ++++++++++++++++----------- 2 files changed, 138 insertions(+), 85 deletions(-) create mode 100644 .translate/state/two_auctions.md.yml diff --git a/.translate/state/two_auctions.md.yml b/.translate/state/two_auctions.md.yml new file mode 100644 index 00000000..8e54f039 --- /dev/null +++ b/.translate/state/two_auctions.md.yml @@ -0,0 +1,6 @@ +source-sha: 6e967af4856b8164815524fe56c7df5ce59a6138 +synced-at: "2026-07-18" +model: claude-sonnet-5 +mode: RESYNC +section-count: 13 +tool-version: 0.17.0 diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index 9a46e029..7939914a 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -9,6 +9,23 @@ kernelspec: display_name: Python 3 (ipykernel) language: python name: python3 +translation: + title: 一价和二价拍卖 + headings: + First-price sealed-bid auction (FPSB): 第一价格密封拍卖(FPSB) + First-price sealed-bid auction (FPSB)::Characterization of FPSB auction: 一价密封拍卖的特征 + Second-price sealed-bid auction (SPSB): 二价密封拍卖(SPSB) + Characterization of SPSB auction: 二价密封拍卖的特征 + Uniform distribution of private values: 私人价值的均匀分布 + Setup: 设置 + First price sealed bid auction: 第一价格密封投标拍卖 + Second price sealed bid auction: 第二价格密封拍卖 + Python code: Python代码 + Revenue equivalence theorem: 收入等价定理 + Calculation of bid price in FPSB: FPSB中出价的计算 + $\chi^2$ Distribution: $\chi^2$ 分布 + Code summary: 代码总结 + References: 参考文献 --- # 一价和二价拍卖 @@ -72,8 +89,7 @@ Anders Munk-Nielsen 将他的代码放在了[GitHub](https://github.com/GamEconC - 如果$i$的出价恰好是$v_i$,她支付的正是她认为物品值得的价格,不会获得任何剩余价值。 - 买家$i$永远不会想要出价高于$v_i$。 - -- 如果买家 $i$ 出价 $b < v_i$ 并赢得拍卖,她获得的剩余价值为 $b - v_i > 0$。 +- 如果买家 $i$ 出价 $b < v_i$ 并赢得拍卖,她获得的剩余价值为 $v_i - b > 0$。 - 如果买家 $i$ 出价 $b < v_i$ 而其他人出价高于 $b$,买家 $i$ 就会输掉拍卖且没有剩余价值。 - 要继续进行,买家 $i$ 需要知道她的出价 $v_i$ 作为函数时赢得拍卖的概率 - 这要求她知道其他潜在买家 $j \neq i$ 的出价 $v_j$ 的概率分布 @@ -170,7 +186,6 @@ $$ $$ \begin{aligned} \mathbf{E}(y_{i} | y_{i} < v_{i}) &= \frac{\int_{0}^{v_{i}} y_{i}\tilde{f}_{n-1}(y_{i})dy_{i}}{\int_{0}^{v_{i}} \tilde{f}_{n-1}(y_{i})dy_{i}} \\ - &= \frac{\int_{0}^{v_{i}}(n-1)y_{i}^{n-1}dy_{i}}{\int_{0}^{v_{i}}(n-1)y_{i}^{n-2}dy_{i}} \\ &= \frac{n-1}{n}y_{i}\bigg{|}_{0}^{v_{i}} \\ &= \frac{n-1}{n}v_{i} @@ -188,20 +203,15 @@ $$ ```{code-cell} ipython3 import numpy as np import matplotlib.pyplot as plt -import matplotlib as mpl - import seaborn as sns import scipy.stats as stats import scipy.interpolate as interp -# 用于绘图 +# for plots +plt.rcParams.update({"text.usetex": True, 'font.size': 14}) colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] -FONTPATH = "fonts/SourceHanSerifSC-SemiBold.otf" -mpl.font_manager.fontManager.addfont(FONTPATH) -plt.rcParams['font.family'] = ['Source Han Serif SC'] - -# 确保笔记本生成相同的随机数 +# ensure the notebook generates the same randomness np.random.seed(1337) ``` @@ -213,31 +223,37 @@ np.random.seed(1337) N = 5 R = 100_000 -v = np.random.uniform(0,1,(N,R)) +v = np.random.uniform(0, 1, (N, R)) -# 第一价格密封拍卖的贝叶斯纳什均衡 +# BNE in first-price sealed bid -b_star = lambda vi,N :((N-1)/N) * vi +b_star = lambda vi, N: ((N-1)/N) * vi b = b_star(v,N) ``` 我们计算并排序在一价密封拍卖(FPSB)和二价密封拍卖(SPSB)下产生的出价分布。 ```{code-cell} ipython3 -idx = np.argsort(v, axis=0) # 在每次拍卖中,竞买人的估值按升序排列。 -# 我们记录这个顺序是因为我们要将其应用于出价价格和竞买人ID。 +# Bidders' values are sorted in ascending order in each auction. +# We record the order because we want to apply it to bid price and their id. +idx = np.argsort(v, axis=0) -v = np.take_along_axis(v, idx, axis=0) # 与np.sort(v, axis=0)相同,但保留了idx +# same as np.sort(v, axis=0), except now we retain the idx +v = np.take_along_axis(v, idx, axis=0) b = np.take_along_axis(b, idx, axis=0) -ii = np.repeat(np.arange(1,N+1)[:,None], R, axis=1) # 创建竞买人的ID。 -ii = np.take_along_axis(ii, idx, axis=0) # ID也按照出价价格进行排序。 - -winning_player = ii[-1,:] # 在FPSB和SPSB中,最高估值者为赢家。 +# the id for the bidders is created. +ii = np.repeat(np.arange(1, N+1)[:, None], R, axis=1) +# the id is sorted according to bid price as well. +ii = np.take_along_axis(ii, idx, axis=0) -winner_pays_fpsb = b[-1,:] # 最高出价 -winner_pays_spsb = v[-2,:] # 第二高估值 +# In FPSB and SPSB, winners are those with highest values. +winning_player = ii[-1, :] +# highest bid +winner_pays_fpsb = b[-1, :] +# 2nd-highest valuation +winner_pays_spsb = v[-2, :] ``` 让我们绘制_获胜_出价 $b_{(n)}$(即支付金额)与估值 $v_{(n)}$ 的关系图,分别针对FPSB和SPSB。 @@ -249,8 +265,7 @@ winner_pays_spsb = v[-2,:] # 第二高估值 ```{code-cell} ipython3 # 我们打算计算不同群组投标者的平均支付金额 - -binned = stats.binned_statistic(v[-1,:], v[-2,:], statistic='mean', bins=20) +binned = stats.binned_statistic(v[-1, :], v[-2, :], statistic='mean', bins=20) xx = binned.bin_edges xx = [(xx[ii]+xx[ii+1])/2 for ii in range(len(xx)-1)] yy = binned.statistic @@ -258,8 +273,9 @@ yy = binned.statistic fig, ax = plt.subplots(figsize=(6, 4)) ax.plot(xx, yy, label='SPSB平均支付金额') -ax.plot(v[-1,:], b[-1,:], '--', alpha = 0.8, label = 'FPSB解析解') -ax.plot(v[-1,:], v[-2,:], 'o', alpha = 0.05, markersize = 0.1, label = 'SPSB:实际出价') +ax.plot(v[-1, :], b[-1, :], '--', alpha=0.8, label='FPSB解析解') +ax.plot(v[-1, :], v[-2, :], 'o', alpha=0.05, + markersize=0.1, label='SPSB:实际出价') ax.legend(loc='best') ax.set_xlabel('估值, $v_i$') @@ -297,7 +313,6 @@ $$ &= n\mathbf{E_{v_i}}\left[\mathbf{E_{y_i}}[y_{i}|y_{i} < v_{i}]\tilde{F}_{n-1}(v_{i})\right] \\ &= n\mathbf{E_{v_i}}[\frac{n-1}{n} \times v_{i} \times v_{i}^{n-1}] \\ &= (n-1)\mathbf{E_{v_i}}[v_{i}^{n}] \\ - &= \frac{n-1}{n+1} \end{aligned} $$ @@ -309,8 +324,9 @@ $$ ```{code-cell} ipython3 fig, ax = plt.subplots(figsize=(6, 4)) -for payment,label in zip([winner_pays_fpsb, winner_pays_spsb], ['FPSB', 'SPSB']): - print('The average payment of %s: %.4f. Std.: %.4f. Median: %.4f'% (label,payment.mean(),payment.std(),np.median(payment))) +for payment, label in zip([winner_pays_fpsb, winner_pays_spsb], ['FPSB', 'SPSB']): + print('The average payment of %s: %.4f. Std.: %.4f. Median: %.4f' % ( + label, payment.mean(), payment.std(), np.median(payment))) ax.hist(payment, density=True, alpha=0.6, label=label, bins=100) ax.axvline(winner_pays_fpsb.mean(), ls='--', c='g', label='Mean') @@ -357,7 +373,7 @@ $$ +++ -在方程{eq}`eq:optbid1`和{eq}`eq:optbid1`中,我们展示了FPSB拍卖中对称贝叶斯纳什均衡的最优出价公式。 +在方程{eq}`eq:optbid1`和{eq}`eq:optbid2`中,我们展示了FPSB拍卖中对称贝叶斯纳什均衡的最优出价公式。 $$ \mathbf{E}[y_{i} | y_{i} < v_{i}] @@ -365,7 +381,6 @@ $$ 其中 - $v_{i} = $ 投标者$i$的价值 - - $y_{i} = $:除了竞标者$i$以外所有竞标者的最大值,即$y_{i} = \max_{j \neq i} v_{j}$ 我们之前已经为私人价值呈均匀分布的情况下分析计算出了FPSB拍卖中的最优出价。 @@ -392,25 +407,37 @@ def evaluate_largest(v_hat, array, order=1): 除获胜者外第二大数的顺序是2。 """ - N,R = array.shape - array_residual=array[1:,:].copy() # 删除第一行,因为我们假设第一行是获胜者的出价 + N, R = array.shape + + # 删除第一行,因为我们假设第一行是获胜者的出价 + array_residual = array[1:, :].copy() - index=(array_residual Date: Sat, 18 Jul 2026 19:12:51 +1000 Subject: [PATCH 2/6] Restore target-side localisation dropped by whole-file resync Re-applies Chinese code comments / print strings / plot labels that the resync reverted to English while the surrounding code is unchanged (action-translation#107 field validation, Track B wave). Co-Authored-By: Claude Fable 5 --- lectures/two_auctions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index 7939914a..93b958f2 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -236,16 +236,16 @@ b = b_star(v,N) ```{code-cell} ipython3 # Bidders' values are sorted in ascending order in each auction. # We record the order because we want to apply it to bid price and their id. -idx = np.argsort(v, axis=0) +idx = np.argsort(v, axis=0) # 在每次拍卖中,竞买人的估值按升序排列。 # same as np.sort(v, axis=0), except now we retain the idx -v = np.take_along_axis(v, idx, axis=0) +v = np.take_along_axis(v, idx, axis=0) # 与np.sort(v, axis=0)相同,但保留了idx b = np.take_along_axis(b, idx, axis=0) # the id for the bidders is created. ii = np.repeat(np.arange(1, N+1)[:, None], R, axis=1) # the id is sorted according to bid price as well. -ii = np.take_along_axis(ii, idx, axis=0) +ii = np.take_along_axis(ii, idx, axis=0) # ID也按照出价价格进行排序。 # In FPSB and SPSB, winners are those with highest values. winning_player = ii[-1, :] @@ -635,7 +635,7 @@ class bid_price_solution: idx = np.argsort(self.value_mat, axis=0) # same as np.sort(v, axis=0), except now we retain the idx - self.v = np.take_along_axis(self.value_mat, idx, axis=0) + self.v = np.take_along_axis(self.value_mat, idx, axis=0) # 与np.sort(v, axis=0)相同,但保留了idx self.b = np.take_along_axis(self.b, idx, axis=0) N, R = self.value_mat.shape From 88d855b05def58d0d1eec227d4e1492c7540f554 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Sat, 18 Jul 2026 19:14:39 +1000 Subject: [PATCH 3/6] Restore Chinese inline comments dropped alongside code reformatting (action-translation#107 field validation, Track B wave.) Co-Authored-By: Claude Fable 5 --- lectures/two_auctions.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index 93b958f2..8ac6967a 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -243,17 +243,17 @@ v = np.take_along_axis(v, idx, axis=0) # 与np.sort(v, axis=0)相同,但保 b = np.take_along_axis(b, idx, axis=0) # the id for the bidders is created. -ii = np.repeat(np.arange(1, N+1)[:, None], R, axis=1) +ii = np.repeat(np.arange(1, N+1)[:, None], R, axis=1) # 创建竞买人的ID。 # the id is sorted according to bid price as well. ii = np.take_along_axis(ii, idx, axis=0) # ID也按照出价价格进行排序。 # In FPSB and SPSB, winners are those with highest values. -winning_player = ii[-1, :] +winning_player = ii[-1, :] # 在FPSB和SPSB中,最高估值者为赢家。 # highest bid -winner_pays_fpsb = b[-1, :] +winner_pays_fpsb = b[-1, :] # 最高出价 # 2nd-highest valuation -winner_pays_spsb = v[-2, :] +winner_pays_spsb = v[-2, :] # 第二高估值 ``` 让我们绘制_获胜_出价 $b_{(n)}$(即支付金额)与估值 $v_{(n)}$ 的关系图,分别针对FPSB和SPSB。 @@ -410,7 +410,7 @@ def evaluate_largest(v_hat, array, order=1): N, R = array.shape # 删除第一行,因为我们假设第一行是获胜者的出价 - array_residual = array[1:, :].copy() + array_residual = array[1:, :].copy() # 删除第一行,因为我们假设第一行是获胜者的出价 winning_auctions_mask = (array_residual < v_hat).all(axis=0) @@ -523,9 +523,9 @@ ii = np.take_along_axis(ii, idx, axis=0) winning_player = ii[-1, :] # highest bid -winner_pays_fpsb = b[-1, :] +winner_pays_fpsb = b[-1, :] # 最高出价 # 2nd-highest valuation -winner_pays_spsb = v[-2, :] +winner_pays_spsb = v[-2, :] # 第二高估值 ``` ```{code-cell} ipython3 @@ -645,9 +645,9 @@ class bid_price_solution: winning_player = self.ii[-1, :] # highest bid - winner_pays_fpsb = self.b[-1, :] + winner_pays_fpsb = self.b[-1, :] # 最高投标 # 2nd-highest valuation - winner_pays_spsb = self.v[-2, :] + winner_pays_spsb = self.v[-2, :] # 第二高估值 fig, ax = plt.subplots(figsize=(6, 4)) From b6bfae2166d1a5a49b30fb6cb9d29b519679516e Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Sat, 18 Jul 2026 21:21:05 +1000 Subject: [PATCH 4/6] Restore CJK font configuration dropped by the resync The resynced file keeps Chinese plot labels but reverted the import cell to the source's exact form, losing the Source Han Serif setup - Chinese in figures would render as missing glyphs. Residual #107 class found in the merge review; applied wave-wide. Co-Authored-By: Claude Fable 5 --- lectures/two_auctions.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index 8ac6967a..ae6c718a 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -203,6 +203,10 @@ $$ ```{code-cell} ipython3 import numpy as np import matplotlib.pyplot as plt +import matplotlib as mpl +FONTPATH = "fonts/SourceHanSerifSC-SemiBold.otf" +mpl.font_manager.fontManager.addfont(FONTPATH) +plt.rcParams['font.family'] = ['Source Han Serif SC'] import seaborn as sns import scipy.stats as stats import scipy.interpolate as interp From fce71f2b37772033e6744fe3da6ad9237e3c6d35 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Sun, 19 Jul 2026 11:33:20 +1000 Subject: [PATCH 5/6] Restore trailing newline (engine issue tracked in QuantEcon/action-translation#116) Co-Authored-By: Claude Fable 5 --- lectures/two_auctions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index ae6c718a..78426409 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -700,4 +700,4 @@ chi_squ_case.plot_winner_payment_distribution() 3. Chandra Chekuri的算法博弈论讲义:https://chekuri.cs.illinois.edu/teaching/spring2008/Lectures/scribed/Notes20.pdf 4. Tim Salmon的ECO 4400补充讲义:关于拍卖的一切:https://s2.smu.edu/tsalmon/auctions.pdf 5. 拍卖理论-收益等价定理:https://michaellevet.wordpress.com/2015/07/06/auction-theory-revenue-equivalence-theorem/ -6. 顺序统计量:https://online.stat.psu.edu/stat415/book/export/html/834 \ No newline at end of file +6. 顺序统计量:https://online.stat.psu.edu/stat415/book/export/html/834 From 96bb1c3f140ed78812fb568cc7f21a610075626a Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Sun, 19 Jul 2026 11:59:24 +1000 Subject: [PATCH 6/6] Drop text.usetex so Chinese plot labels render (LaTeX Unicode error) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream sets text.usetex=True with English plot labels; the resync faithfully kept usetex but translated the labels to Chinese (估值/出价/ 解析解/...), which are unwrapped and have no CJK LaTeX package loaded, so under usetex LaTeX raised 'Unicode character 估 (U+4F30)' and figure drawing failed. Main had no usetex here. Rather than wrap ~20 labels in a CJK environment, drop usetex to match the zh edition's font-manager convention (font.family=Source Han Serif already set above; simple math like $v_i$ renders via mathtext). The earlier green build used cached cell outputs, masking this until the cold rebuild. Co-Authored-By: Claude Fable 5 --- lectures/two_auctions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index 78426409..be246290 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -212,7 +212,7 @@ import scipy.stats as stats import scipy.interpolate as interp # for plots -plt.rcParams.update({"text.usetex": True, 'font.size': 14}) +plt.rcParams.update({'font.size': 14}) colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] # ensure the notebook generates the same randomness