from otree.api import (
Page,
WaitPage,
models,
BaseConstants,
BaseSubsession,
BaseGroup,
BasePlayer,
Currency as c,
currency_range,
)
doc = """
In a second price auction game, players simultaneously bid on the item being
auctioned.
Prior to bidding, they are given their personal value of the item.
The winner of the auction is the player who places the highest bid, but the price payed by the winner is equal to the
value of the second highest bid.
Bids are private. The payoff depends on the value of the item for the winner and the price payed by the winner.
The first half of rounds utilizes a fixed grouping and grouping is random for the second half.
"""
# Defining constants
class Constants(BaseConstants):
name_in_url = 'second_price_auction'
players_per_group = 3
num_rounds = 6
instructions_template = 'common_value_auction/instructions.html'
min_allowable_bid = c(0)
max_allowable_bid = c(100)
# Error margin for the value estimates shown to the players
estimate_error_margin = c(1)
class Subsession(BaseSubsession):
pass
# Define group based terms
class Group(BaseGroup):
highest_bid = models.CurrencyField()
second_highest_bid = models.CurrencyField()
winner = models.IntegerField()
item_value = models.CurrencyField()
# Define player based terms
class Player(BasePlayer):
# Define each player's personal value
value = models.CurrencyField()
price = models.CurrencyField()
# Create a field for the bid placed by each player
bid = models.CurrencyField(
min=Constants.min_allowable_bid,
max=Constants.max_allowable_bid,
doc="""Amount bidded by the player""",
label="Bid amount",)
# Define whether or not the are winner
is_winner = models.BooleanField()
# Define price
price = models.CurrencyField()
# Functions
# Establishes a total earnings variable for each participant and initiate to 0 at the beginning of session.
def creating_session(subsession):
import random
# group randomly halfway through the rounds
if subsession.round_number >= 4:
subsession.group_randomly()
print('in creating session')
for p in subsession.get_players():
p.value = random.uniform(0, 1) * 100
p.is_winner = False
if subsession.round_number == 1:
p.participant.vars['totalEarnings'] = 0
# How to get into groups.
# for g in subsession.get_groups():
# if subsession.round_number <=3
# stable group?
# else
# import random
def auction_outcome(group: Group):
# Get players in the group
players = group.get_players()
# Get bids from the players
bids = [p.bid for p in players]
# Now we have to sort the bids in descending order (largest is first)
bids.sort(reverse=True)
# Define the highest and second highest bids to their respective group variables
group.highest_bid = bids[0]
group.second_highest_bid = bids[1]
group.item_value = bids[1]
for p in group.get_players():
p.price = group.second_highest_bid
# TIE BREAKER CONDITION
# The first get the set of players IDs who bid the highest for the round.
highest_bidders = []
for p in players:
if p.bid == group.highest_bid:
highest_bidders.append(p.id_in_group)
# Next randomly select one of the players in the tie
import random
group.winner = random.choice(highest_bidders)
# Finally get the player model of the winning bidder and flag as the winner
winning_player = group.get_player_by_id(group.winner)
winning_player.is_winner = True
# Set payoffs for round
for p in players:
if p.is_winner:
p.payoff = p.value - group.second_highest_bid
if p.payoff < 0:
p.payoff = 0
else:
p.payoff = 0
# PAGES
class Introduction(Page):
def is_displayed(player):
return player.round_number == 1
# Page for placing bids of the rounds with randomly selected players
class PlaceBid(Page):
form_model = 'player'
form_fields = ['bid']
@staticmethod
def get_timeout_seconds(player: Player):
return 120
def before_next_page(player, timeout_happened):
if timeout_happened:
player.bid = 0
# Page for placing bids of the rounds with same players
#class PlaceBid2(Page):
# form_model = 'player'
# form_fields = ['bid']
# waiting page between rounds
class ResultsWaitPage(WaitPage):
after_all_players_arrive = 'auction_outcome'
body_text = "Please wait for everyone to submit their bids."
class Results(Page):
@staticmethod
def vars_for_template(player: Player):
group = player.group
return dict(is_greedy = player.bid - group.item_value < 0)
# def vars_for_template(player: Player):
# group = player.group
page_sequence = [Introduction, PlaceBid, ResultsWaitPage, Results]