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)
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 %s' % player.role().capitalize(),
'data': payoffs})
return {
'highcharts_series': series,
'round_numbers': list(range(1, Constants.num_rounds + 1))
}
class Group(BaseGroup):
sale_price = models.CurrencyField()
seller_id = models.IntegerField(
choices=[(i, 'Buy from seller %i' % i) for i in
range(1, Constants.players_per_group)] + [
(0, 'Buy nothing')],
widget=widgets.RadioSelect,
doc="""0 means no purchase made"""
) # seller index
def set_payoff(self):
for p in self.get_players():
p.payoff = Constants.initial_endowment
if self.seller_id != 0:
seller = self.get_seller()
self.sale_price = seller.seller_proposed_price
buyer = self.get_player_by_role('buyer')
buyer.payoff += seller.seller_proposed_quality + Constants.buyer_extra_value - seller.seller_proposed_price
seller.payoff += seller.seller_proposed_price - seller.seller_proposed_quality
def get_seller(self):
for p in self.get_players():
if 'seller' in p.role() and p.seller_id() == self.seller_id:
return p
class Player(BasePlayer):
# seller
seller_proposed_price = models.CurrencyField(
min=0, max=Constants.initial_endowment
)
seller_proposed_quality = models.CurrencyField(
choices=[
(30, 'High'),
(20, 'Medium'),
(10, 'Low')],
widget=widgets.RadioSelectHorizontal)
def seller_id(self):
# player 1 is the buyer, so seller 1 is actually player 2
return (self.id_in_group - 1)
def role(self):
if self.id_in_group == 1:
return 'buyer'
return 'seller {}'.format(self.seller_id())