The game
A public Goods Game
- Participants can decide how much contribute to a “public” project out of their endowment
- Participants are in a group of N subjects (usually 4)
- What is contributed is multiplied by an efficiency factor $1/N<<1 $
- What is not contributed is kept in a private account
- Private incentives are to contribute nothing to the public account
- But, contributions are efficient
- \(\Rightarrow\) social dilemma
- But, contributions are efficient
Treatments: framing
- We are going to frame the game eiter as a Voluntary Contribution game (VC) or as a Common Pool game (CP)
- Voluntary Contribution game
- Participants explicitly decide how much of their endowment contribute to the public project
- What is not contributed is kept in a private account
- Participants explicitly decide how much of their endowment contribute to the public project
- Common Pool game
- Participants explicitly decide how much to withdraw from the (already existing) public project
- What is withdrawn is put in a private account
- Participants explicitly decide how much to withdraw from the (already existing) public project
Parameters
- The interaction is repeated 10x in a partner fashion
- Total earnings are given by the sum of earnings in each stage
- Groups of 4
- Matched together for the entire expeirment (partner)
- The efficiency factor \(\alpha=.5\)
- The initial endowment is E=100
- The individual payoff function is
- VC
- \(\Pi_i=E-c_i+\alpha \sum_j^N c_j\)
- where, \(j\) are the members of \(i\)’s group (\(i\) include)
- \(\sum_j^N c_j\) is the size of the public project
- CP
- \(\Pi_i=c_i+ \alpha (N*E-\sum_j^N c_j)\)
- The individual payoff function is
- Choices are in integer steps
- \(c_i \in \{0, 100\}\)
Screens
Instructions
- VC
- CP
Choices
- VC
- CP
Results
- CP
- VC
oTree code
models.py
- Set here a few important constants
- Players per group
- Number of rounds
- Individual endowment
- Multiplier for the public project
- \(\alpha=\frac{2=multiplier}{4=group~members}\)
models (ii)
- In class Subsession we defien the matching
- No need to define roles in PGG
class Subsession(BaseSubsession):
def creating_session(self):
#***************************************************************
# Partner matching
#***************************************************************
if self.round_number == 1: # this way we get a fixed role across repetitions
self.group_randomly()
else:
self.group_like_round(1)
#***************************************************************
# Copy treatment for each player, needed for data analysis
#! configurations are not saved in the data
#***************************************************************
for p in self.get_players():# copy the treatment for each subject
p.treatment=self.session.config['treatment']
models (iii)
- In class Group we define the payoffs
- Typical of strategic interaction, while in individual decision making they are defined in Player
class Group(BaseGroup):
total_choices = models.CurrencyField() # for VC is contributions , for CP is withdrawals
individual_share = models.CurrencyField() #the share from public project
total_earnings = models.CurrencyField() # share from public project + private account
#***************************************************************
# Define the method to compute payoff
#***************************************************************
def set_payoffs(self):
# conventional name for the payoff function
players = self.get_players()
# retrieve players in the subsession
choices = [p.choice for p in players]
# store their choices in a list. For CP they are withdrawals, For VC they are contributions
self.total_choices = sum(choices)
# sum the total choices (gives the size of the public project)
if self.session.config['treatment'] == "VC":
# if treatment is VC
self.total_earnings = self.total_choices * Constants.multiplier
# size of the public project
self.individual_share = (
self.total_earnings / Constants.players_per_group
)
# the individual share from the public project
for p in players:
# for all players in the group
p.payoff = Constants.endowment - p.choice + self.individual_share
# write the earnings in the payoff field (each player has automatically one)
# then, we can use participant.payoff to get the sum across rounds
else: # treatment CP
# if treatment is CP
self.total_earnings = ((Constants.endowment*Constants.players_per_group)-self.total_choices) * Constants.multiplier
# size of the public project
self.individual_share = (
self.total_earnings / Constants.players_per_group
)
# the individual share from the public project
for p in players:
# for all players in the group
p.payoff = p.choice + self.individual_share
# write the earnings in the payoff field (each player has automatically one)
# then, we can use participant.payoff to get the sum across rounds
models (iv)
- Variables for players
pages.py
- We have 5 pages
- page_sequence = [Instructions, Contribute, ResultsWaitPage, Results, FinalResults]
- Instructions(Page)
- Displayed only in round 1
- Contribute(Page)
- ResultsWaitPage(WaitPage)
- WaitPage → oTree waits until all players in the group have arrived at that point in the sequence, and then all players are allowed to proceed
- Results(Page)
- FinalResults(Page)
- Displayed only in last round
- Instructions(Page)
pages
- Instructions
class Instructions(Page):
def is_displayed(self):
# define this method to return True if the page should be show
return self.round_number == 1
# show the page only in round 1
def vars_for_template(self):
# to pass variables to the template
return{
'treatment': self.session.config['treatment'],# needed to create the right treatment in the intructions
'common_proj': Constants.endowment*Constants.players_per_group
}
# dictionary with variables needed in the template
pages (ii)
- Contribute
- Different meaning in VC snd CP
class Contribute(Page):
form_model = 'player'
form_fields = ['choice']
#the player will fill out the field choice and it will be saved in player model (see models)
def vars_for_template(self):
return{
'round_number':self.round_number,
'treatment': self.session.config['treatment'],
'endowment': Constants.endowment
}
# dictionary with variables needed in the template
pages (iii)
- This is a WaitPage
pages (iv)
- Results displayed at the end of each round
pages (v)
- Displayed only in the last period
class FinalResults(Page):
def is_displayed(self):
return self.round_number == Constants.num_rounds
# displayed only in last round
def vars_for_template(self):
return{
'final_payoff':self.player.participant.payoff
}
# Each player has a payoff field
# self.participant.payoff automatically stores the sum of payoffs from all subsessions
templates: Instructions
{% extends "global/Page.html" %}
{% load staticfiles otree %}
<!--------------------------->
<!-- Title -->
{% block title %}
<h1> Instructions </h1>
{% endblock %}
<!--------------------------->
<!-- Main body -->
{% block content %}
<div class="container p-3 my-3 border" style="font-size:18pt">
<h2> The interaction</h2>
{% if treatment == "VC" %} <!-- VC -->
<p>In this study, you will be in a randomly formed group of {{ Constants.players_per_group }} participants. </p>
<p>Each participant in the group is given {{ Constants.endowment }}. </p>
<p>Each participant in the group decides how much she or he is going to contribute to a common project.</p>
<p>Contributions could be any integer between 0 to {{ Constants.endowment }}.</p>
<h2> Your payoff </h2>
<p> The earnings from the project are calculated as follows:
<ul>
<li>
The contributions of all {{ Constants.players_per_group }} participants are added up.</li>
<li>
The sum of contributions is multiplied by a factor of {{ Constants.multiplier }}: these are the <i>total returns from the project</i>.
</li>
<li>
<i>Total returns from the project</i> are then evenly split among all {{ Constants.players_per_group }} participants: : these are <i>your earnings from the project</i>.
</li>
</ul>
<p><i>Your payoff</i> is given by your earnings from the project, plus the amount you did not contribute.</p>
{% else %} <!-- CP -->
<p>In this study, you will be in a randomly formed group of {{ Constants.players_per_group }} participants. </p>
<p> Your group is endowed with a common project of {{ common_proj }}. </p>
<p>Each participant in the group decides how much she or he is going to withdraw from the common project.</p>
<p>Withdrawals could be any integer between 0 to {{ Constants.endowment }}.</p>
<h2> Your payoff </h2>
<p> The earnings from the project are calculated as follows:
<ul>
<li>
The withdrawals of all {{ Constants.players_per_group }} participants are added up.</li>
<li>
The sum of withdrawals is subtracted from the common project and the resulting amount is multiplied by a factor of {{ Constants.multiplier }}: these are the <i>total returns from the project</i>.
</li>
<li>
<i>Total returns from the project</i> are then evenly split among all {{ Constants.players_per_group }} participants: these are <i>your earnings from the project</i>.
</li>
</ul>
<p><i>Your payoff</i> is given by your earnings from the project, plus the amount you withdrew from the project.</p>
{% endif %}
</div>
<!-- Continue Button -->
<div class="container" style="font-size:18pt">
<div class="row">
</div>
<div class="row" style="padding-left:135px;">
<div class="col-md-10">
</div>
<div class="col-md-2">
<button name="btn_submit" value="True" class="btn btn-primary btn-large">
<span style="font-size:18pt">Continue</span>
</button>
</div>
</div>
</div>
{% endblock %}
<!--------------------------->
templates: Contribute
{% extends "global/Page.html" %}
{% load staticfiles otree %}
<!--------------------------->
{% block title %}
{% if treatment == "VC" %} <!-- Treatment VC -->
<h1> Contribute ( Round {{ round_number }} of {{Constants.num_rounds}})<h1> <!-- info about treatments -->
{% else %} <!-- CP -->
<h1> Withdrawal ( Round {{ round_number }} of {{Constants.num_rounds}})<h1> <!-- info about treatments -->
{% endif %}
{% endblock %}
<!--------------------------->
{% block content %}
<div class="container p-3 my-3 border" style="font-size:18pt">
{% if treatment == "VC" %}<!-- Treatment VC -->
{% formfield player.choice label="How much do you contribute to the common project?" %}
{% else %}<!-- CP -->
{% formfield player.choice label="How much do you withdraw from the common project?" %}
{% endif %}
<small>An integer number between 0 and {{endowment}}</small>
</div>
<!-- Continue Button -->
<div class="container" style="font-size:18pt">
<div class="row">
</div>
<div class="row" style="padding-left:135px;">
<div class="col-md-10">
</div>
<div class="col-md-2">
<button name="btn_submit" value="True" class="btn btn-primary btn-large">
<span style="font-size:18pt">Continue</span>
</button>
</div>
</div>
</div>
{% endblock %}
<!--------------------------->
templates: Results
{% extends "global/Page.html" %}
{% load staticfiles otree %}
<!--------------------------->
{% block title %}
Results ( Round {{ round_number }} of {{Constants.num_rounds}})
{% endblock %}
<!--------------------------->
{% block content %}
<div class="container p-3 my-3 border" style="font-size:18pt">
{% if treatment == "VC" %}
<table class="table-condensed" style="width:500px; margin-top:20px;">
<tr><td>You contributed:</td><td>{{ player.choice }}</td></tr>
<tr><td>Other participants contributed:</td><td></td></tr>
{% for p in player.get_others_in_group %} <!-- get the list of all players-->
<tr><td></td><td>{{ p.choice }}</td></tr>
{% endfor %}
<tr><td>Total contribution:</td><td>{{ group.total_choices }}</td></tr>
<tr><td colspan="2"><hr/></td></tr>
<tr><td>Total earnings from the project:</td><td>{{ group.total_earnings }}</td></tr>
<tr><td>Your earnings from the project:</td><td>{{ group.individual_share }}</td></tr>
<tr><td colspan="2"><hr/></td></tr>
<tr><td>Thus in total you earned:</td><td>{{ player.payoff }}</td></tr>
</table>
{% else %}
<table class="table-condensed" style="width:500px; margin-top:20px;">
<tr><td>You withdrew:</td><td>{{ player.choice }}</td></tr>
<tr><td>Other participants withdrew:</td><td></td></tr>
{% for p in player.get_others_in_group %} <!-- get the list of all players-->
<tr><td></td><td>{{ p.choice }}</td></tr>
{% endfor %}
<tr><td>Total withdrawals:</td><td>{{ group.total_choices }}</td></tr>
<tr><td colspan="2"><hr/></td></tr>
<tr><td>Total earnings from the project:</td><td>{{ group.total_earnings }}</td></tr>
<tr><td>Your earnings from the project:</td><td>{{ group.individual_share }}</td></tr>
<tr><td colspan="2"><hr/></td></tr>
<tr><td>Thus in total you earned:</td><td>{{ player.payoff }}</td></tr>
</table>
{% endif %}
</div>
<!--------------------------->
<!-- Continue Button -->
<div class="container" style="font-size:18pt">
<div class="row">
</div>
<div class="row" style="padding-left:135px;">
<div class="col-md-10">
</div>
<div class="col-md-2">
<button name="btn_submit" value="True" class="btn btn-primary btn-large">
<span style="font-size:18pt">Continue</span>
</button>
</div>
</div>
</div>
{% endblock %}
<!--------------------------->
FinalResults
- Displayed only in last round
{% extends "global/Page.html" %}
{% load staticfiles otree %}
<!--------------------------->
{% block title %}
<h1> Final Results </h1>
{% endblock %}
<!--------------------------->
{% block content %}
<div class="container p-3 my-3 border" style="font-size:18pt">
Your total earnings in the game are {{final_payoff}}
<div class="container" style="font-size:18pt">
<div class="row">
</div>
<div class="row" style="padding-left:135px;">
<div class="col-md-10">
</div>
<div class="col-md-2">
<button name="btn_submit" value="True" class="btn btn-primary btn-large">
<span style="font-size:18pt">Continue</span>
</button>
</div>
</div>
</div>
{% endblock %}
<!--------------------------->
Thank you
🦄
To contact me just write me an email
or write me on the forum of the course
Appendix
Assignment
- Easy
- Change endowment from 100 to 10000
- Less easy
- Final payment is not the sum of all periods, but a randomly chosen period
- Hint: use the built-in method in_round()