from otree.api import *
doc = """
Your app description
"""
class C(BaseConstants):
NAME_IN_URL = 'tsumitate_teigaku_ranking'
PLAYERS_PER_GROUP = 15
NUM_ROUNDS = 10
#決算が好景気(0)不景気(1)
SETTLEMENT = [0, 0, 0, 1, 0, 0, 1, 0, 1, 0]
#決算が好景気の時のメッセージと悪景気の時のメッセージ
SETTLEMENT_MESSAGE = [
'株式市場は好景気で、株式Aの株価は+15%、株式Bの株価は+20%上昇しました',
'株式市場は不景気で、株式Aの株価は+5%、株式Bの株価は+0%上昇しました'
]
#株価を定義
STOCK_PRICE_A = [4000, 4600, 5290, 6083.5, 6387.675, 7345.82625, 8447.700188, 8870.085197, 10200.59798, 10710.62788, 12317.22206]
STOCK_PRICE_B = [4000, 4800, 5760, 6912, 6912, 8294.4, 9953.28, 9953.28, 11943.936, 11943.936, 14332.7232]
#毎月の積立額
TSUMITATE = 30000
#株式Aの割合が少ない順に並べ替えたポートフォリオ
PORTFOLIO = [
'株式Aを0%、株式Bを100%の割合で取得する',
'株式Aを25%、株式Bを75%の割合で取得する',
'株式Aを50%、株式Bを50%の割合で取得する',
'株式Aを75%、株式Bを25%の割合で取得する',
'株式Aを100%、株式Bを0%の割合で取得する'
]
#非合理的なポートフォリオを並べ替えて表示する
#2ラウンド目から表示するので、「ラウンド数-2」個あればOK
HERDING_PORTFOLIO = [1, 3, 2, 3, 2, 1, 1, 1, 2]
#選択肢を表示するためのリスト
CHOICE = [
'ポートフォリオ1',
'ポートフォリオ2',
'ポートフォリオ3',
'ポートフォリオ4',
'ポートフォリオ5',
''
]
#インストラクションのテンプレートを呼び出し
INSTRUCTIONS_TEMPLATE = 'tsumitate_teigaku_ranking/instructions.html'
#「一番選択された」を1ラウンド目で選択させない
INFO = [
'が1つ前の期で最も選択されました。',
''
]
#最終ラウンドまでは含み益、最終ラウンドで最終的な利益と表現されるようにする
GAIN = [
'含み益は、',
'最終的な利益は、'
]
class Subsession(BaseSubsession):
pass
class Group(BaseGroup):
#income_stock_choiceの番号と、choiced_の番号は等しい
choiced_0 = models.IntegerField()
choiced_1 = models.IntegerField()
choiced_2 = models.IntegerField()
choiced_3 = models.IntegerField()
choiced_4 = models.IntegerField()
#一番選択された選択肢の番号
most_choiced = models.IntegerField()
class Player(BasePlayer):
income_stock_choice = models.IntegerField(
choices=[
[0, C.CHOICE[0]],
[1, C.CHOICE[1]],
[2, C.CHOICE[2]],
[3, C.CHOICE[3]],
[4, C.CHOICE[4]]
],
verbose_name='あなたが取得する株式のポートフォリオ番号を選んでください。',
widget=widgets.RadioSelect
)
def set_payoff(player:Player):
number_A = 0
number_B = 0
#株価を求め、定額分の株式数を計算し、その後現在の株価*保有株式数から取得にかかったコスト(定額*ラウンド数)を引くことでコストを求める
#トータルの株式数*株価の計算
for i in range(player.round_number):
#ラウンドiでのプレイヤーを定義
prev_player = player.in_round(i+1)
#現在の株価を求める
stock_price_A = C.STOCK_PRICE_A[prev_player.round_number - 1]
stock_price_B = C.STOCK_PRICE_B[prev_player.round_number - 1]
#ラウンドiにおける選択肢を取得
prev_choice = [
prev_player.group.choiced_0,
prev_player.group.choiced_1,
prev_player.group.choiced_2,
prev_player.group.choiced_3,
prev_player.group.choiced_4
]
#ラウンドiでプレイヤーが保有している株式数を計算
number_A = number_A + C.TSUMITATE * prev_choice[prev_player.income_stock_choice] * 0.25 / stock_price_A
number_B = number_B + C.TSUMITATE * (4 - prev_choice[prev_player.income_stock_choice]) * 0.25 / stock_price_B
#株式AとBの利得を計算
income_A = number_A * C.STOCK_PRICE_A[player.round_number]
income_B = number_B * C.STOCK_PRICE_B[player.round_number]
income_total = income_A + income_B - C.TSUMITATE * player.round_number
player.payoff = income_total
def set_payoffs(group: Group):
#利得の計算を行う
for p in group.get_players():
set_payoff(p)
def set_ranking(group: Group):
if group.round_number == 1:
choice = [4, 3, 2, 1, 0]
group.most_choiced = 5
else:
#プレイヤーをリストに入れる
prev_group = group.in_round(group.round_number - 1)
a = prev_group.get_players()
b = []
#各々のプレイヤーが選択したポートフォリオの選択肢をリストに格納する
for i in range(len(a)):
b.append(a[i-1].income_stock_choice)
#ポートフォリオが選択された数を辞書に入れる
c = {'4': b.count(4), '3': b.count(3), '2': b.count(2), '1': b.count(1), '0': b.count(0)}
#人数が多い順にソートする
c_sorted = sorted(c.items(), key=lambda x:x[1], reverse=True)
#仮の値を入れる
choiced_0 = 0
choiced_1 = 0
choiced_2 = 0
choiced_3 = 0
choiced_4 = 0
choice = [choiced_0, choiced_1, choiced_2, choiced_3, choiced_4]
#一番選択されたポートフォリオにハーディングである非合理的なポートフォリオを代入
choice[int(c_sorted[0][0])] = C.HERDING_PORTFOLIO[group.round_number - 2]
#一番選択されたポートフォリオ以外に、被りなくポートフォリオを代入していく
choice[(int(c_sorted[0][0]) + 1) % 5] = (C.HERDING_PORTFOLIO[group.round_number - 2] + 1) % 5
choice[(int(c_sorted[0][0]) + 2) % 5] = (C.HERDING_PORTFOLIO[group.round_number - 2] + 2) % 5
choice[(int(c_sorted[0][0]) + 3) % 5] = (C.HERDING_PORTFOLIO[group.round_number - 2] + 3) % 5
choice[(int(c_sorted[0][0]) + 4) % 5] = (C.HERDING_PORTFOLIO[group.round_number - 2] + 4) % 5
#一番選択されたポートフォリオをmost_choicedに代入する
group.most_choiced = int(c_sorted[0][0])
#choiceの中身を、choiced_xに代入する
group.choiced_0 = choice[0]
group.choiced_1 = choice[1]
group.choiced_2 = choice[2]
group.choiced_3 = choice[3]
group.choiced_4 = choice[4]
# PAGES
class MyPage(Page):
pass
class Introduction(Page):
def is_displayed(self):
return self.round_number == 1
class ResultsWaitPage(WaitPage):
after_all_players_arrive = set_payoffs
class ResultsWaitPage2(WaitPage):
after_all_players_arrive = set_ranking
class DecisionInvestment(Page):
timeout_seconds = 60
form_model = 'player'
form_fields = [
'income_stock_choice'
]
@staticmethod # 誰か使い方を教えて下さい
def vars_for_template(player: Player):
if player.round_number == 1:
return dict(
info = C.INFO[1],
tsumitate = C.TSUMITATE,
choiced_0 = C.PORTFOLIO[player.group.choiced_0],
choiced_1 = C.PORTFOLIO[player.group.choiced_1],
choiced_2 = C.PORTFOLIO[player.group.choiced_2],
choiced_3 = C.PORTFOLIO[player.group.choiced_3],
choiced_4 = C.PORTFOLIO[player.group.choiced_4],
most_choiced = C.CHOICE[player.group.most_choiced]
)
else:
return dict(
info = C.INFO[0],
tsumitate = C.TSUMITATE,
choiced_0 = C.PORTFOLIO[player.group.choiced_0],
choiced_1 = C.PORTFOLIO[player.group.choiced_1],
choiced_2 = C.PORTFOLIO[player.group.choiced_2],
choiced_3 = C.PORTFOLIO[player.group.choiced_3],
choiced_4 = C.PORTFOLIO[player.group.choiced_4],
most_choiced = C.CHOICE[player.group.most_choiced]
)
class Results(Page):
timeout_seconds = 30
@staticmethod # 誰か使い方を教えて下さい
def vars_for_template(player: Player):
if player.round_number ==10:
return dict(
gain = C.GAIN[1],
my_decision = player.field_display('income_stock_choice'),
market_g_b = C.SETTLEMENT_MESSAGE[C.SETTLEMENT[player.round_number - 1]],
year = player.round_number,
choiced_0 = C.PORTFOLIO[player.group.choiced_0],
choiced_1 = C.PORTFOLIO[player.group.choiced_1],
choiced_2 = C.PORTFOLIO[player.group.choiced_2],
choiced_3 = C.PORTFOLIO[player.group.choiced_3],
choiced_4 = C.PORTFOLIO[player.group.choiced_4]
)
else:
return dict(
gain = C.GAIN[0],
my_decision = player.field_display('income_stock_choice'),
market_g_b = C.SETTLEMENT_MESSAGE[C.SETTLEMENT[player.round_number - 1]],
year = player.round_number,
choiced_0 = C.PORTFOLIO[player.group.choiced_0],
choiced_1 = C.PORTFOLIO[player.group.choiced_1],
choiced_2 = C.PORTFOLIO[player.group.choiced_2],
choiced_3 = C.PORTFOLIO[player.group.choiced_3],
choiced_4 = C.PORTFOLIO[player.group.choiced_4]
)
page_sequence = [Introduction, ResultsWaitPage2, DecisionInvestment, ResultsWaitPage, Results]