from otree.api import *
doc = """
In a common value auction game, players simultaneously bid on the item being
auctioned.
Prior to bidding, they are given an estimate of the actual value of the item.
This actual value is revealed after the bidding.
Bids are private. The player with the highest bid wins the auction, but
payoff depends on the bid amount and the actual value.
"""
class C(BaseConstants):
NAME_IN_URL = 'common_value_auction'
PLAYERS_PER_GROUP = 2
NUM_ROUNDS = 15
# Baja
BID_MIN_B = cu(0)
BID_MAX_B = cu(15)
# Error margin for the value estimates shown to the players
BID_NOISE_B = cu(1)
# Media
BID_MIN_M = cu(10)
BID_MAX_M = cu(20)
# Error margin for the value estimates shown to the players
BID_NOISE_M = cu(1)
# Sinergia
SYNERGY = cu(10)
# DOT = cu(500)
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
item_value_b = models.CurrencyField(
doc="""Common value of the item to be auctioned, random for treatment"""
)
highest_bid_b = models.CurrencyField()
item_value_m = models.CurrencyField(
doc="""Common value of the item to be auctioned, random for treatment"""
)
highest_bid_m = models.CurrencyField()
synergy = models.CurrencyField()
class Player(BasePlayer):
item_value_estimate_b = models.CurrencyField(
doc="""Estimate of the common value, may be different for each player"""
)
item_value_estimate_m = models.CurrencyField(
doc="""Estimate of the common value, may be different for each player"""
)
bid_amount_B = models.CurrencyField(
min=C.BID_MIN_B,
max=C.BID_MAX_B,
doc="""Amount bidded by the player""",
label="Monto de la oferta",
)
is_winner_b = models.BooleanField(
initial=False, doc="""Indicates whether the player is the winner"""
)
bid_amount_M = models.CurrencyField(
min=C.BID_MIN_M,
max=C.BID_MAX_M,
doc="""Amount bidded by the player""",
label="Monto de la oferta",
)
is_winner_m = models.BooleanField(
initial=False, doc="""Indicates whether the player is the winner"""
)
payoff_b = models.CurrencyField(
doc="""payoff b""",
label="Ganancia total B",
)
payoff_m = models.CurrencyField(
doc="""payoff m""",
label="Ganancia total M",
)
dot = models.CurrencyField(
doc="""dotac""",
label="Dotación",
)
def other_player(self):
return self.get_others_in_group()[0]
# FUNCTIONS
def creating_session(subsession: Subsession):
subsession.group_randomly()
for g in subsession.get_groups():
import random
item_value_b = random.uniform(C.BID_MIN_B, C.BID_MAX_B)
item_value_m = random.uniform(C.BID_MIN_M, C.BID_MAX_M)
synergy = random.uniform(0, C.SYNERGY)
g.item_value_b = round(item_value_b, 1)
g.item_value_m = round(item_value_m, 1)
g.synergy = round(synergy, 1)
def set_winner_b(group: Group):
import random
players = group.get_players()
group.highest_bid_b = max([p.bid_amount_B for p in players])
players_with_highest_bid_b = [p for p in players if p.bid_amount_B == group.highest_bid_b]
winner_b = random.choice(
players_with_highest_bid_b
) # if tie, winner is chosen at random
winner_b.is_winner_b = True
for p in players:
set_payoff(p)
group.highest_bid_m = max([p.bid_amount_M for p in players])
players_with_highest_bid_m = [p for p in players if p.bid_amount_M == group.highest_bid_m]
winner_m = random.choice(
players_with_highest_bid_m
) # if tie, winner is chosen at random
winner_m.is_winner_m = True
for p in players:
set_payoff(p)
def generate_value_estimate_b(group: Group):
import random
estimate_b = group.item_value_b + random.uniform(-C.BID_NOISE_B, C.BID_NOISE_B)
estimate_b = round(estimate_b, 1)
if estimate_b < C.BID_MIN_B:
estimate_b = C.BID_MIN_B
if estimate_b > C.BID_MAX_B:
estimate_b = C.BID_MAX_B
return estimate_b
def generate_value_estimate_m(group: Group):
import random
estimate_m = group.item_value_m + random.uniform(-C.BID_NOISE_M, C.BID_NOISE_M)
estimate_m = round(estimate_m, 1)
if estimate_m < C.BID_MIN_M:
estimate_m = C.BID_MIN_M
if estimate_m > C.BID_MAX_M:
estimate_m = C.BID_MAX_M
return estimate_m
def set_payoff(player: Player):
group_b = player.group
if player.is_winner_b:
player.payoff_b = group_b.item_value_b - player.bid_amount_B
else:
player.payoff_b = 0
group_m = player.group
if player.is_winner_m:
player.payoff_m = group_m.item_value_m - player.bid_amount_M
else:
player.payoff_m = 0
group = player.group
if player.is_winner_b:
if player.is_winner_m:
player.payoff = player.payoff_b + player.payoff_m + group.synergy
else:
player.payoff = player.payoff_b
else:
if player.is_winner_m:
player.payoff = player.payoff_m
else:
player.payoff = 0
# PAGES
class Introduction(Page):
@staticmethod
def before_next_page(player: Player, timeout_happened):
group = player.group
player.item_value_estimate_b = generate_value_estimate_b(group)
player.item_value_estimate_m = generate_value_estimate_m(group)
class Bid(Page):
form_model = 'player'
form_fields = ['bid_amount_B']
class BidM(Page):
form_model = 'player'
form_fields = ['bid_amount_M']
class ResultsWaitPage(WaitPage):
after_all_players_arrive = set_winner_b
class Results(Page):
@staticmethod
def vars_for_template(player: Player):
return dict(is_greedy=player.payoff_b + player.payoff_m < 0)
page_sequence = [Introduction, Bid, BidM, ResultsWaitPage, Results]