from otree.api import (
models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
Currency as c, currency_range
)
import random
doc = """
In a lemon market of
Akerlof (1970)
, 2 buyers and 1 seller interact for 3 periods. The implementation is
based on
Holt (1999)
.
"""
class Constants(BaseConstants):
name_in_url = 'lemon_market'
players_per_group = 3
num_rounds = 3
instructions_template = 'lemon_market/Instructions.html'
initial_endowment = c(50)
buyer_extra_value = c(5)
buy_choices = []
for i in range(1, players_per_group):
choice = [i, 'Buy from seller {}'.format(i)]
buy_choices.append(choice)
buy_choices.append([0, 'Buy nothing'])
quality_production_costs = {
# Level: ProductionCost
'High': 30,
'Medium': 20,
'Low': 10
}
quality_level_names = list(quality_production_costs.keys())
class Subsession(BaseSubsession):
def vars_for_admin_report(self):
group = self.get_groups()[0]
series = []
transaction_prices = [g.sale_price for g in group.in_all_rounds()]
series.append({
'name': 'Transaction Price',
'data': transaction_prices})
for player in group.get_players():
payoffs = [p.payoff for p in player.in_all_rounds()]
series.append(
{'name': 'Earnings for {}'.format(player.role()),
'data': payoffs})
return {
'highcharts_series': series,
'round_numbers': list(range(1, Constants.num_rounds + 1))
}
class Group(BaseGroup):
sale_price = models.CurrencyField()
sale_quality = models.StringField()
seller_id = models.IntegerField(
choices=Constants.buy_choices,
widget=widgets.RadioSelect,
doc="""0 means no purchase made"""
)
def set_payoff(self):
for p in self.get_players():
p.payoff = Constants.initial_endowment
if self.seller_id != 0:
seller = self.get_player_by_id(self.seller_id)
buyer = self.get_player_by_role('buyer')
self.sale_price = seller.seller_proposed_price
self.sale_quality = seller.seller_proposed_quality
quality_production_cost = Constants.quality_production_costs[self.sale_quality]
buyer.payoff += quality_production_cost + Constants.buyer_extra_value - self.sale_price
seller.payoff += self.sale_price - quality_production_cost
class Player(BasePlayer):
seller_proposed_price = models.CurrencyField(
min=0, max=Constants.initial_endowment
)
seller_proposed_quality = models.StringField(
choices=Constants.quality_level_names,
widget=widgets.RadioSelectHorizontal
)
def role(self):
if self.id_in_group == Constants.players_per_group:
return 'buyer'
return 'seller {}'.format(self.id_in_group)