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]