From e9b1e400fad1921828427248581ac0f49d49ea1c Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Sun, 17 Aug 2025 10:46:48 +1000 Subject: [PATCH 1/3] remove warning and make code PEP8 compliant --- lectures/two_auctions.md | 163 ++++++++++++++++++++++++--------------- 1 file changed, 100 insertions(+), 63 deletions(-) diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index 0f2ed02c8..0dc051da9 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -4,7 +4,7 @@ jupytext: extension: .md format_name: myst format_version: 0.13 - jupytext_version: 1.10.3 + jupytext_version: 1.17.1 kernelspec: display_name: Python 3 (ipykernel) language: python @@ -46,9 +46,6 @@ Anders Munk-Nielsen put his code [on GitHub](https://github.com/GamEconCph/Lectu Much of our Python code below is based on his. - - - +++ ## First-Price Sealed-Bid Auction (FPSB) @@ -201,7 +198,7 @@ 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'] +colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] # ensure the notebook generate the same randomess np.random.seed(1337) @@ -215,30 +212,37 @@ The valuations of each bidder is distributed $U(0,1)$. 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) ``` We compute and sort bid price distributions that emerge under both FPSB and SPSB. ```{code-cell} ipython3 -idx = np.argsort(v, axis=0) # Biders' values are sorted in ascending order in each auction. +# 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) # same as np.sort(v, axis=0), except now we retain the 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) # the id for the bidders is created. -ii = np.take_along_axis(ii, idx, axis=0) # the id is sorted according to bid price as well. +# 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) -winning_player = ii[-1,:] # In FPSB and SPSB, winners are those with highest values. +# In FPSB and SPSB, winners are those with highest values. +winning_player = ii[-1, :] -winner_pays_fpsb = b[-1,:] # highest bid -winner_pays_spsb = v[-2,:] # 2nd-highest valuation +# highest bid +winner_pays_fpsb = b[-1, :] +# 2nd-highest valuation +winner_pays_spsb = v[-2, :] ``` Let's now plot the _winning_ bids $b_{(n)}$ (i.e. the payment) against valuations, $v_{(n)}$ for both FPSB and SPSB. @@ -250,8 +254,7 @@ Note that ```{code-cell} ipython3 # We intend to compute average payments of different groups of bidders - -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 @@ -259,8 +262,9 @@ yy = binned.statistic fig, ax = plt.subplots(figsize=(6, 4)) ax.plot(xx, yy, label='SPSB average payment') -ax.plot(v[-1,:], b[-1,:], '--', alpha = 0.8, label = 'FPSB analytic') -ax.plot(v[-1,:], v[-2,:], 'o', alpha = 0.05, markersize = 0.1, label = 'SPSB: actual bids') +ax.plot(v[-1, :], b[-1, :], '--', alpha=0.8, label='FPSB analytic') +ax.plot(v[-1, :], v[-2, :], 'o', alpha=0.05, + markersize=0.1, label='SPSB: actual bids') ax.legend(loc='best') ax.set_xlabel('Valuation, $v_i$') @@ -311,8 +315,9 @@ Thus, while probability distributions of winning bids typically differ across th ```{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') @@ -396,14 +401,25 @@ def evaluate_largest(v_hat, array, order=1): the order for second-largest number beside winner is 2. """ - N,R = array.shape - array_residual=array[1:,:].copy() # drop the first row because we assume first row is the winner's bid + N, R = array.shape + + # drop the first row because we assume first row is the winner's bid + array_residual = array[1:, :].copy() - index=(array_residual Date: Sun, 17 Aug 2025 11:14:14 +1000 Subject: [PATCH 2/3] update lecture --- lectures/two_auctions.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/lectures/two_auctions.md b/lectures/two_auctions.md index 0dc051da9..916696037 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -48,7 +48,7 @@ Much of our Python code below is based on his. +++ -## First-Price Sealed-Bid Auction (FPSB) +## First-price sealed-bid auction (FPSB) +++ @@ -74,7 +74,7 @@ Evidently, - If $i$ bids exactly $v_i$, she pays what she thinks it is worth and gathers no surplus value. - Buyer $i$ will never want to bid more than $v_i$. -- If buyer $i$ bids $b < v_i$ and wins the auction, then she gathers surplus value $b - v_i > 0$. +- If buyer $i$ bids $b < v_i$ and wins the auction, then she gathers surplus value $v_i - b > 0$. - If buyer $i$ bids $b < v_i$ and someone else bids more than $b$, buyer $i$ loses the auction and gets no surplus value. - To proceed, buyer $i$ wants to know the probability that she wins the auction as a function of her bid $v_i$ - this requires that she know a probability distribution of bids $v_j$ made by prospective buyers $j \neq i$ @@ -91,7 +91,7 @@ To complete the specification of the situation, we'll assume that prospective Bidder optimally chooses to bid less than $v_i$. -### Characterization of FPSB Auction +### Characterization of FPSB auction A FPSB auction has a unique symmetric Bayesian Nash Equilibrium. @@ -109,28 +109,28 @@ $$ (eq:optbid2) -A proof for this assertion is available at the [Wikepedia page](https://en.wikipedia.org/wiki/Vickrey_auction) about Vickrey auctions +A proof for this assertion is available at the [Wikipedia page](https://en.wikipedia.org/wiki/Vickrey_auction) about Vickrey auctions +++ -## Second-Price Sealed-Bid Auction (SPSB) +## Second-price sealed-bid auction (SPSB) +++ **Protocols:** In a second-price sealed-bid (SPSB) auction, the winner pays the second-highest bid. -## Characterization of SPSB Auction +## Characterization of SPSB auction In a SPSB auction bidders optimally choose to bid their values. Formally, a dominant strategy profile in a SPSB auction with a single, indivisible item has each bidder bidding its value. -A proof is provided at [the Wikepedia +A proof is provided at [the Wikipedia page](https://en.wikipedia.org/wiki/Vickrey_auction) about Vickrey auctions +++ -## Uniform Distribution of Private Values +## Uniform distribution of private values +++ @@ -181,13 +181,13 @@ $$ \end{aligned} $$ -## Second Price Sealed Bid Auction +## Second price sealed bid auction In a **SPSB**, it is optimal for bidder $i$ to bid $v_i$. +++ -## Python Code +## Python code ```{code-cell} ipython3 import numpy as np @@ -200,7 +200,7 @@ import scipy.interpolate as interp plt.rcParams.update({"text.usetex": True, 'font.size': 14}) colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] -# ensure the notebook generate the same randomess +# ensure the notebook generate the same randomness np.random.seed(1337) ``` @@ -272,7 +272,7 @@ ax.set_ylabel('Bid, $b_i$') sns.despine() ``` -## Revenue Equivalence Theorem +## Revenue equivalence theorem +++ @@ -344,7 +344,7 @@ sns.despine() **Detour: Computing a Bayesian Nash Equibrium for FPSB** -The Revenue Equivalence Theorem lets us an optimal bidding strategy for a FPSB auction from outcomes of a SPSB auction. +The Revenue Equivalence Theorem lets us find an optimal bidding strategy for a FPSB auction from outcomes of a SPSB auction. Let $b(v_{i})$ be the optimal bid in a FPSB auction. @@ -360,11 +360,11 @@ It follows that an optimal bidding strategy in a FPSB auction is $b(v_{i}) = \ma +++ -## Calculation of Bid Price in FPSB +## Calculation of bid price in FPSB +++ -In equations {eq}`eq:optbid1` and {eq}`eq:optbid1`, we displayed formulas for +In equations {eq}`eq:optbid1` and {eq}`eq:optbid2`, we displayed formulas for optimal bids in a symmetric Bayesian Nash Equilibrium of a FPSB auction. $$ @@ -539,7 +539,7 @@ ax.set_ylabel('Density') sns.despine() ``` -## 5 Code Summary +## Code summary +++ From d1af4160d0e2e10d40b6bfc5339baf843b6d34b6 Mon Sep 17 00:00:00 2001 From: Humphrey Yang <39026988+HumphreyYang@users.noreply.github.com> Date: Mon, 18 Aug 2025 11:07:30 +1000 Subject: [PATCH 3/3] Update lectures/two_auctions.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- 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 916696037..ec35a42ac 100644 --- a/lectures/two_auctions.md +++ b/lectures/two_auctions.md @@ -200,7 +200,7 @@ import scipy.interpolate as interp plt.rcParams.update({"text.usetex": True, 'font.size': 14}) colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] -# ensure the notebook generate the same randomness +# ensure the notebook generates the same randomness np.random.seed(1337) ```