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]