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]