from otree.api import *
c = cu
doc = 'In this game, players simultaneously bid on the item being\nauctioned.
\nPrior to bidding, they are given an estimate of the actual value of the item.\nThis actual value is revealed after the bidding.
\nBids are private. The player with the highest bid wins the auction, and will pay the 2nd highest bid. The other bidders pay nothing and earn nothing.
'
class Constants(BaseConstants):
name_in_url = 'Second_Price_Auction'
players_per_group = 3
num_rounds = 3
min_allowable_bid = cu(0)
max_allowable_bid = cu(10)
estimate_error_margin = cu(1)
style_background_color = '#F0F0F0'
style_text_color = '#1F297E'
def creating_session(subsession):
session = subsession.session
subsession.group_randomly()
for p in subsession.get_players():
import random
item_value = random.uniform(
Constants.min_allowable_bid, Constants.max_allowable_bid
)
p.item_value_actual = round(item_value, 2)
p.number_of_opponents = Constants.players_per_group - 1
class Subsession(BaseSubsession):
pass
def set_winner(group):
players = group.get_players()
for p in players: p.number_of_players_tied = 0
# List of players with highest bid
group.highest_bid = max([p.bid_amount for p in players])
players_with_highest_bid = [
p for p in players if p.bid_amount == group.highest_bid
]
# Sort bid amounts in descending order
list_of_bids = [
p.bid_amount for p in players
]
list_of_bids.sort(reverse=True)
# Bid amount to pay is the 2nd highest bid
group.paying_bid = list_of_bids[1]
# num_winners = len(players_with_highest_bid)
#if num_winners > 1 and list_of_bids[0] == list_of_bids[1]:
# First two players tied, highest tied bids are the same
#for p in players_with_highest_bid:
#if len(players_with_highest_bid) == Constants.players_per_group:
#group.paying_bid = group.highest_bid
#else:
#group.paying_bid = list_of_bids[len(players_with_highest_bid)]
#p.is_tied = True
#p.number_of_players_tied = num_winners
#p.payoff = (p.item_value_actual - group.paying_bid) / num_winners *
#else:
# Only one winner
#for p in players_with_highest_bid:
#p.is_winner = True
#p.payoff = p.item_value_actual - group.paying_bid
for p in players:
# condition is 2 top bidders tie or all bidders tie
if (len(players_with_highest_bid) > 1) and list_of_bids[0] == list_of_bids[1] and p.bid_amount == group.highest_bid:
p.number_of_players_tied = len(players_with_highest_bid)
p.is_tied = True
p.payoff = (p.item_value_actual - group.paying_bid)/ p.number_of_players_tied
else:
#no tie, only one winner
p.payoff = 0;
players_with_highest_bid[0].is_winner = True
for p in players_with_highest_bid: p.payoff = p.item_value_actual - group.paying_bid
for p in players:
p.total_earnings= sum([round.payoff for round in p.in_all_rounds()])
class Group(BaseGroup):
highest_bid = models.CurrencyField()
total_earnings = models.CurrencyField()
paying_bid = models.CurrencyField()
def set_payoff(player):
if player.is_winner:
player.payoff = player.item_value_actual - player.bid_amount
elif player.is_tied:
player.payoff = (player.item_value_actual - player.bid_amount)/ player.number_of_players_tied
else:
player.payoff = 0
class Player(BasePlayer):
item_value = models.CurrencyField()
bid_amount = models.CurrencyField(label='Bid amount', min=Constants.min_allowable_bid)
is_winner = models.BooleanField(initial=False)
is_tied = models.BooleanField(initial=False)
number_of_players_tied = models.IntegerField()
item_value_actual = models.CurrencyField()
total_earnings = models.CurrencyField()
number_of_opponents = models.IntegerField()
class Introduction(Page):
form_model = 'player'
@staticmethod
def is_displayed(player):
return player.round_number == 1
class Bid(Page):
form_model = 'player'
form_fields = ['bid_amount']
class ResultsWaitPage(WaitPage):
after_all_players_arrive = 'set_winner'
class Results(Page):
form_model = 'player'
page_sequence = [Introduction, Bid, ResultsWaitPage, Results]