import random from otree.api import * author = 'Francisco Klapp' doc = """ This app implements a simulation of bank runs, in which players represent banks which must decide how to allocate their asset portfolios in order to retain solvency and liquidity in order to avoid bank runs. In one treatment, the accounting review is automatic and always correct. In another treatment, the accounting review is done by another participant and is incentivized to be correct but may still be wrong. """ ### TO DO ### # Send with my report: # Note that I gave no payoff for prediction when trade did not occur # Suggest that they get paid for liquid AND solvent together, in the same rounds where other players get paid for allocation # This way everyone has an allocation payoff and a prediction payoff # High priority # # Medium priority # # Floating-point errors can occur in display, esp. history table # Low priority # # Payoffs in history table are given in "points", not dollars # Idea: Maybe make the default price forecast the last period's price? class Constants(BaseConstants): name_in_url = 'BR' players_per_group = 4 # For testing and actual experiment num_rounds = 30 # For testing and actual experiment class Subsession(BaseSubsession): #pass price = models.FloatField() # new price_display = models.FloatField() # new total_offer = models.IntegerField() # new total_bid = models.IntegerField() # new class Group(BaseGroup): state = models.IntegerField() #total_offer = models.IntegerField() original #total_bid = models.IntegerField() original #price = models.FloatField() original #paying_round_allocation = models.IntegerField() # paying_round_prediction = models.IntegerField() class Player(BasePlayer): # These variables are used by bank players region = models.IntegerField() asset = models.IntegerField() cash = models.FloatField() no_trade = models.IntegerField() default_asset = models.IntegerField() default_price = models.FloatField() decision = models.StringField( label="Do you want to buy or sell assets?", widget=widgets.RadioSelectHorizontal, choices=['Buy', 'Sell'], blank=True, ) bid = models.IntegerField( label="Please enter the amount of your offer.", blank=True, ) price_guess = models.FloatField( label="Please enter your prediction of the market price of assets." ) allocation_payoff = models.CurrencyField() prediction_payoff = models.CurrencyField() # These variables are used by accountant players decision_guess = models.StringField( label="Do you expect the bank to buy or sell assets?", widget=widgets.RadioSelectHorizontal, choices=['Buy', 'Sell'], ) bid_guess = models.IntegerField(label="Please enter the amount you expect the bank to offer.") solvent_correct = models.BooleanField() liquid_correct = models.BooleanField() # These variables are used by both, either observed or modified initial_asset = models.IntegerField() initial_cash = models.FloatField() #just for history tables cash_aux = models.FloatField() # To avoid floating-point errors cash_dollars = models.IntegerField() cash_cents = models.IntegerField() impatient = models.IntegerField() liquid = models.BooleanField( label="Do you believe the bank is liquid?", choices=[[True, 'Yes'], [False, 'No']] ) solvent = models.BooleanField( label="Do you believe the bank is solvent?", choices=[[True, 'Yes'], [False, 'No']] ) # Questionnaire variables age = models.IntegerField(min=16, max=99) sex = models.StringField( widget=widgets.RadioSelectHorizontal, choices=['Male', 'Female', 'Non-Binary'], ) major = models.StringField() GPA = models.FloatField(min=0, max=4) risk = models.IntegerField( widget=widgets.RadioSelectHorizontal, choices=['0', '1', '2', '3', '4' , '5' , '6', '7', '8', '9', '10'], ) # FUNCTIONS def creating_session(subsession: Subsession): if subsession.round_number == 1: num_paying_rounds_allocation = subsession.session.config['paying_rounds_allocation'] num_paying_rounds_prediction = subsession.session.config['paying_rounds_prediction'] total_paying_rounds = num_paying_rounds_prediction + num_paying_rounds_allocation #paying_rounds = random.sample(range(1, Constants.num_rounds + 1), total_paying_rounds) cambiado!!! paying_rounds = random.sample(range(1, subsession.session.config['num_rounds'] + 1), total_paying_rounds) subsession.session.vars['paying_rounds_allocation'] = sorted(random.sample( paying_rounds, num_paying_rounds_allocation )) subsession.session.vars['paying_rounds_prediction'] = sorted(list( x for x in paying_rounds if x not in subsession.session.vars['paying_rounds_allocation'] )) # At the end this should yield two disjoint lists of rounds, each of the size set by the config var. # aux = random.random() # print(aux) # if aux < subsession.session.config['prob_s1']: # for group in subsession.get_groups(): # group.state = 1 # else: # for group in subsession.get_groups(): # group.state = 2 #just for double checking #import random #num_paying_rounds_allocation = 2 #num_paying_rounds_prediction = 3 #num_rounds=5 #total_paying_rounds = num_paying_rounds_prediction + num_paying_rounds_allocation #paying_rounds = random.sample(range(1, num_rounds+1 ), total_paying_rounds) # paying_rounds_allocation = random.sample(paying_rounds, num_paying_rounds_allocation) # paying_rounds_prediction= list( # x for x in paying_rounds if x not in paying_rounds_allocation # ) # At the end this should yield two disjoint lists of rounds, each of the size set by the config var. # wait_for_all_groups = True subsession.group_randomly(fixed_id_in_group=True) print(subsession.get_group_matrix()) # outputs the following: #def set_state(group: Group): # if random.random() < 0.5: # group.state = 1 # else: # group.state = 2 def set_state(subsession: Subsession): aux_random = random.random() print(aux_random) if aux_random < subsession.session.config['prob_s1']: for group in subsession.get_groups(): group.state = 1 else: for group in subsession.get_groups(): group.state = 2 print('for round', group.round_number, 'the state of the world is:', group.state) def set_default(player: Player): # Defining default asset investment if player.round_number == 1: player.default_asset = player.session.config['default_asset'] else: player.default_asset = player.in_round(player.round_number - 1).initial_asset return player.default_asset def set_default2(player: Player): # Defining default price forecast if player.round_number == 1: player.default_price = player.session.config['default_price'] else: player.default_price = player.in_round(player.round_number - 1).price_guess return player.default_price def set_impatient(player: Player): if player.group.state == 1: # STATE 1!!! if get_role(player) == 'Region I' or get_role(player) == 'Region I Accountant': player.impatient = player.session.config['impatient_s1_region_I'] # t1=68 or t2= 84 else: player.impatient = player.session.config['deposit'] - player.session.config['impatient_s1_region_I'] # t1=32 or t2=14 else: # STATE 2!!! if get_role(player) == 'Region I' or get_role(player) == 'Region I Accountant': player.impatient = player.session.config['impatient_s2_region_I'] # t1=32 or t2=41 else: player.impatient = player.session.config['deposit']-player.session.config['impatient_s2_region_I'] #t1=68 or t1=59 # Is this a deprecated functionality? Should I redo the roles? def get_role(player: Player): # accountant is always bank + 2 if player.session.config['has_accountant']: if player.id_in_group % 4 == 1: player.region = 1 return 'Region I' elif player.id_in_group % 4 == 2: player.region = 2 return 'Region II' elif player.id_in_group % 4 == 3: player.region = 1 return 'Region I Accountant' else: player.region = 2 return 'Region II Accountant' else: if player.id_in_group % 2 == 1: player.region = 1 return 'Region I' else: player.region = 2 return 'Region II' def get_partner(player: Player): if get_role(player) == 'Region I': target = 'Region I Accountant' elif get_role(player) == 'Region II': target = 'Region II Accountant' elif get_role(player) == 'Region I Accountant': target = 'Region I' else: target = 'Region II' for player in player.get_others_in_group(): if get_role(player) == target: return player def other_players(player: Player): return player.get_others_in_group() # PAGES class InstructionsBank(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 and get_role(player) in ['Region I', 'Region II'] @staticmethod def vars_for_template(player: Player): if player.session.config['has_accountant']: # number_other = int((Constants.players_per_group / 2) - 1) number_other=int((player.session.num_participants/2)-1) else: # number_other = Constants.players_per_group - 1 number_other = player.session.num_participants-1 return dict( has_accountant=player.session.config['has_accountant'], forecast_prize=cu(player.session.config['forecast_prize']).to_real_world_currency( player.session ), number_other=number_other, # endowment=player.session.config['endowment'], multiplier=player.session.config['asset_return'], allocation_prize=cu(player.session.config['allocation_prize']).to_real_world_currency( player.session ), max_payoff=cu(2 * player.session.config['allocation_prize']).to_real_world_currency( player.session ), deposit=player.session.config['deposit'] ) @staticmethod def before_next_page(player: Player, timeout_happened): set_default(player) set_default2(player) class InstructionsAccountant(Page): @staticmethod def is_displayed(player: Player): return player.round_number == 1 and get_role(player) in [ 'Region I Accountant', 'Region II Accountant', ] @staticmethod def vars_for_template(player: Player): return dict( forecast_prize=cu(player.session.config['forecast_prize']).to_real_world_currency( player.session ), # endowment=player.session.config['endowment'], multiplier=player.session.config['asset_return'], allocation_prize=cu(player.session.config['allocation_prize']).to_real_world_currency( player.session ), max_payoff=cu(2 * player.session.config['allocation_prize']).to_real_world_currency( player.session ), accountant_prize=cu(player.session.config['accountant_prize']).to_real_world_currency( player.session ), gamma=player.session.config['gamma'], ) @staticmethod def before_next_page(player: Player, timeout_happened): set_default(player) set_default2(player) class Period1Bank(Page): form_model = 'player' form_fields = ['asset'] @staticmethod def is_displayed(player: Player): return get_role(player) in ['Region I', 'Region II'] @staticmethod def vars_for_template(player: Player): region = get_role(player) return dict( region=region, deposit=player.session.config['deposit'], default_asset=set_default(player), default_cash=player.session.config['deposit'] - player.default_asset, round_number=player.round_number, ) @staticmethod def before_next_page(player: Player, timeout_happened): player.initial_asset = player.asset player.cash = player.session.config['deposit'] - player.asset player.initial_cash = player.session.config['deposit'] - player.asset player.cash_dollars = int(player.cash) player.cash_cents = int((player.cash - player.cash_dollars) * 100) print(player.cash, "=", player.cash_dollars, ".", player.cash_cents) class BetweenPeriods(WaitPage): wait_for_all_groups = True @staticmethod # def after_all_players_arrive(group: Group): # set_state(group.subsession) # for player in group.get_players(): ## set_impatient(player) # if group.session.config['has_accountant'] and get_role(player) in ['Region I Accountant', 'Region II Accountant']: ## partner = get_partner(player) # player.cash = partner.cash # player.cash_dollars = int(player.cash) # player.cash_cents = int((player.cash - player.cash_dollars) * 100) # print(player.cash, "=", player.cash_dollars, ".", player.cash_cents) # player.asset = partner.asset # player.initial_asset = partner.initial_asset # player.initial_cash = partner.initial_cash # def after_all_players_arrive(subsession: Subsession): set_state(subsession) for player in subsession.get_players(): set_impatient(player) if subsession.session.config['has_accountant'] and get_role(player) in ['Region I Accountant', 'Region II Accountant']: partner = get_partner(player) player.cash = partner.cash player.cash_dollars = int(player.cash) player.cash_cents = int((player.cash - player.cash_dollars) * 100) print(player.cash, "=", player.cash_dollars, ".", player.cash_cents) player.asset = partner.asset player.initial_asset = partner.initial_asset player.initial_cash = partner.initial_cash class Period2Bank(Page): @staticmethod def is_displayed(player: Player): return get_role(player) in ['Region I', 'Region II'] @staticmethod def vars_for_template(player: Player): region = get_role(player) return dict( region=region, round_number=player.round_number, cash=player.initial_cash, asset=player.initial_asset, impatient=player.impatient, multiplier=player.session.config['asset_return'], default_price=set_default2(player), ) class Period2Accountant(Page): @staticmethod def is_displayed(player: Player): return get_role(player) in ['Region I Accountant', 'Region II Accountant'] @staticmethod def vars_for_template(player: Player): # Remove the word "Accountant" region = get_role(player)[:-11] return dict( region=region, round_number=player.round_number, cash=player.initial_cash, cash_dollars=player.cash_dollars, cash_cents=player.cash_cents, asset=player.initial_asset, impatient=player.impatient, multiplier=player.session.config['asset_return'], # default_price=set_default2(player), ) class buyOrSell(Page): form_model = 'player' form_fields = ['decision', 'bid', 'price_guess', 'no_trade'] @staticmethod def is_displayed(player: Player): return get_role(player) in ['Region I', 'Region II'] @staticmethod def error_message(player: Player, values): if values['bid'] < 0: return "Your offer cannot be less than 0." elif values['decision'] == 'Buy' and values['bid'] > player.initial_cash: return "You cannot bid more than the " + str(player.cash) + " you have in cash." elif values['decision'] == 'Sell' and values['bid'] > player.initial_asset: return ( "You cannot offer to sell more than the " + str(player.initial_asset) + " you have in assets." ) elif values['price_guess'] < 0: return "You cannot predict a negative price for the asset." @staticmethod def vars_for_template(player: Player): region = get_role(player) return dict( region=region, round_number=player.round_number, deposit=player.session.config['deposit'], cash=player.initial_cash, cash_dollars=player.cash_dollars, cash_cents=player.cash_cents, asset=player.initial_asset, impatient=player.impatient, multiplier=player.session.config['asset_return'], default_price=set_default2(player), allocation_prize=player.session.config['allocation_prize'], player_in_previous_rounds=reversed(player.in_previous_rounds()), ) class DeterminePrice(WaitPage): wait_for_all_groups = True @staticmethod def after_all_players_arrive(subsession): # new #def after_all_players_arrive(group: Group): #original total_bids = 0 total_offers = 0 for player in subsession.get_players(): if get_role(player) in ["Region I", "Region II"]: if player.decision == 'Buy': total_bids += player.bid else: total_offers += player.bid subsession.total_offer = total_offers subsession.total_bid = total_bids if total_bids > 0 and total_offers > 0: subsession.price = (total_bids / total_offers) else: subsession.price = 0 price = subsession.price subsession.price_display = round(subsession.price, 2) for player in subsession.get_players(): if get_role(player) in ["Region I", "Region II"]: if player.decision == 'Buy': your_bid = player.bid if price > 0: #your_new_assets = int(your_bid / price) #your_new_cash = -int(your_bid / price) * price delta_assets = your_bid / price delta_cash = -your_bid else: delta_assets = 0 delta_cash = 0 else: your_offer = player.bid if price > 0: delta_assets = -your_offer delta_cash = your_offer * price else: delta_assets = 0 delta_cash = 0 player.asset += int(round(delta_assets, 0)) player.cash += delta_cash class AssetMarket(Page): @staticmethod def is_displayed(player: Player): return get_role(player) in ["Region I", "Region II"] @staticmethod def vars_for_template(player: Player): price = player.group.subsession.price if player.decision == 'Buy': your_offer = 0 your_bid = player.bid # if price > 0: # #your_new_assets = int(your_bid / price) # #your_new_cash = -int(your_bid / price) * price # your_new_assets = (your_bid / price) # your_new_cash = -your_bid # else: # your_new_assets = 0 # your_new_cash = 0 else: your_offer = player.bid your_bid = 0 # if price > 0: # your_new_assets = -your_offer # your_new_cash = your_offer * price # else: # your_new_assets = 0 # your_new_cash = 0 # your_old_assets = player.asset - your_new_assets # your_old_cash = player.cash - your_new_cash prediction_error = abs(player.price_guess - price) if price > 0: if player.no_trade == 0: player.prediction_payoff = cu( round(player.session.config['forecast_prize'] / (1 + prediction_error), 2) ).to_real_world_currency(player.session) else: player.prediction_payoff = cu( round(0, 2) ).to_real_world_currency(player.session) else: if player.no_trade == 0: player.prediction_payoff = cu( round(0, 2) ).to_real_world_currency(player.session) else: player.prediction_payoff = cu( round(player.session.config['forecast_prize'], 2) ).to_real_world_currency(player.session) return dict( is_accountant=(get_role(player) in ["Region I Accountant", "Region II Accountant"]), your_offer=your_offer, your_bid=your_bid, trade_happens=(price > 0), no_trade=player.no_trade, price=round(price, 2), total_bid=player.group.subsession.total_bid, total_offer=player.group.subsession.total_offer, your_new_assets=abs(round(player.initial_asset-player.asset, 2)), your_new_cash=abs(round(player.initial_cash-player.cash, 2)), your_old_assets=player.initial_asset, your_old_cash=round(player.initial_cash, 2), your_assets=round(player.asset, 2), your_cash=round(player.cash, 2), prediction_error=round(prediction_error, 2), prediction_prize=player.prediction_payoff, ) @staticmethod def before_next_page(player: Player, timeout_happened): if player.session.config['has_accountant']: partner = get_partner(player) partner.asset = player.asset partner.cash = player.cash partner.cash_dollars = int(player.cash) partner.cash_cents = int((player.cash - float(player.cash_dollars)) * 100) print(partner.cash, "=", partner.cash_dollars, ".", partner.cash_cents) partner.decision = player.decision partner.bid = player.bid class buyOrSellAccountant(Page): form_model = 'player' form_fields = ['decision_guess', 'bid_guess', 'liquid', 'solvent'] @staticmethod def is_displayed(player: Player): return get_role(player) in ['Region I Accountant', 'Region II Accountant'] @staticmethod def error_message(player: Player, values): if values['bid_guess'] < 0: return "The offer cannot be less than 0." elif values['decision_guess'] == 'Buy' and values['bid_guess'] > player.initial_cash: return "The bank cannot bid more than the " + str(player.cash) + " they have in cash." elif values['decision_guess'] == 'Sell' and values['bid_guess'] > player.initial_asset: return ( "The bank cannot offer to sell more than the " + str(player.initial_asset) + " they have in assets." ) @staticmethod def vars_for_template(player: Player): region = get_role(player)[:-11] return dict( region=region, price=player.group.subsession.price, price_aux=round(player.group.subsession.price, 2), round_number=player.round_number, deposit=player.session.config['deposit'], cash=player.cash, cash_dollars=player.cash_dollars, cash_cents=player.cash_cents, asset=player.asset, impatient=player.impatient, multiplier=player.session.config['asset_return'], allocation_prize=player.session.config['allocation_prize'], player_in_previous_rounds=reversed(player.in_previous_rounds()), initial_cash=player.initial_cash, initial_asset=player.initial_asset, ) class WaitForAccountant(WaitPage): @staticmethod def vars_for_template(player: Player): return dict() def after_all_players_arrive(group: Group): for player in group.get_players(): if get_role(player) in ["Region I Accountant", "Region II Accountant"]: partner = get_partner(player) print("Should be assigning liquidity decision from player", player.id_in_group, 'with id', player.id_in_subsession, "to", partner.id_in_group, 'with id', partner.id_in_subsession, 'in group', player.group.id_in_subsession) # You tell them whether they are solvent partner.solvent = player.solvent partner.liquid = player.liquid # They tell you what they bid in the market player.decision = partner.decision player.bid = partner.bid class WaitForResults(WaitPage): @staticmethod def vars_for_template(player: Player): return dict() def after_all_players_arrive(group: Group): for player in group.get_players(): player.cash_aux = round(player.cash, 2) player.cash_dollars = int(player.cash) player.cash_cents = int((player.cash - player.cash_dollars) * 100) print(player.cash, "=", player.cash_dollars, ".", player.cash_cents) if get_role(player) in ["Region I", "Region II"]: if player.session.config['has_accountant']: # player.liquid = get_partner(player).liquid # when accountant is present he detemines solvency, but liquidity still the same player.liquid = int(player.cash) >= player.impatient player.solvent = get_partner(player).solvent else: player.liquid = int(player.cash) >= player.impatient player.solvent = ( player.cash + player.session.config['asset_return'] * player.asset >= player.session.config['deposit'] ) round_payoff = ( player.session.config['allocation_prize'] * (( player.cash + player.session.config['asset_return'] * player.asset - player.impatient ) / (100 - player.impatient)-1) ) if not player.liquid or not player.solvent: round_payoff = 0 round_payoff = cu(round_payoff).to_real_world_currency(player.session) player.allocation_payoff = cu(round_payoff).to_real_world_currency(player.session) class Results(Page): @staticmethod def is_displayed(player: Player): return get_role(player) in ['Region I', 'Region II'] @staticmethod def vars_for_template(player: Player): return dict( has_accountant=player.session.config['has_accountant'], assets=round(player.asset, 2), cash=round(player.cash, 2), cash_dollars=round(player.cash_dollars,2), cash_cents=round(player.cash_cents,2), no_trade=player.no_trade, round=player.round_number, impatient=player.impatient, player_in_previous_rounds=reversed(player.in_previous_rounds()), player_in_all_rounds=reversed(player.in_all_rounds()), prediction_payoff=cu(player.prediction_payoff).to_real_world_currency(player.session), solvent=player.solvent, liquid=player.liquid, allocation_payoff=cu(player.allocation_payoff).to_real_world_currency(player.session), ) class ResultsAccountant(Page): @staticmethod def is_displayed(player: Player): return get_role(player) in ['Region I Accountant', 'Region II Accountant'] @staticmethod def vars_for_template(player: Player): truly_liquid = player.cash >= player.impatient truly_solvent = ( player.cash + player.session.config['asset_return'] * player.asset >= player.session.config['deposit'] ) player.liquid_correct = player.liquid == truly_liquid player.solvent_correct = player.solvent == truly_solvent player.allocation_payoff = 0 if player.liquid_correct: player.allocation_payoff += player.session.config['accountant_prize'] if player.solvent_correct: player.allocation_payoff += player.session.config['accountant_prize'] player.allocation_payoff = cu(player.allocation_payoff).to_real_world_currency( player.session ) if player.decision == player.decision_guess: prediction_error = abs(player.bid - player.bid_guess) else: prediction_error = player.bid + player.bid_guess player.prediction_payoff = cu( player.session.config['forecast_prize'] / (1 + player.session.config['gamma']*prediction_error) ).to_real_world_currency(player.session) return dict( round=player.round_number, bid_guess=player.bid_guess, bid=player.bid, decision_guess=player.decision_guess.lower(), decision=player.decision.lower(), prediction_error=prediction_error, prediction_payoff=player.prediction_payoff, assets=player.asset, cash=round(player.cash,2), cash_dollars=player.cash_dollars, cash_cents=player.cash_cents, impatient=player.impatient, liquid=player.liquid, solvent=player.solvent, truly_liquid=truly_liquid, truly_solvent=truly_solvent, liquid_correct=player.liquid_correct, solvent_correct=player.solvent_correct, accountant_prize=cu(player.session.config['accountant_prize']).to_real_world_currency( player.session ), payoff=cu(player.allocation_payoff).to_real_world_currency(player.session), player_in_all_rounds=reversed(player.in_all_rounds()), ) class WaitforFinalResults(WaitPage): @staticmethod def is_displayed(player: Player): #return player.round_number == Constants.num_rounds Cambiado!!!! return player.round_number == player.session.config['num_rounds'] # def after_all_players_arrive(group: Group): # group.paying_round_allocation = random.randint(1, Constants.num_rounds-1) # group.paying_round_prediction = random.randint(group.paying_round_allocation, Constants.num_rounds) # alternativa # group.paying_round_allocation = group.session.vars['paying_rounds_allocation'] # group.paying_round_prediction = group.session.vars['paying_rounds_prediction'] class Questionnaire(Page): @staticmethod def is_displayed(player: Player): return player.round_number == player.session.config['num_rounds'] form_model = 'player' form_fields = ['age', 'sex', 'major', 'GPA', 'risk'] class FinalResults(Page): @staticmethod def is_displayed(player: Player): #return player.round_number == Constants.num_rounds Cambiado!! return player.round_number == player.session.config['num_rounds'] @staticmethod def vars_for_template(player: Player): #earnings_prediction = player.in_round(player.group.paying_round_prediction).prediction_payoff #earnings_allocation = player.in_round(player.group.paying_round_allocation).allocation_payoff ##player.in_round(player.group.paying_round_prediction).payoff = player.in_round(player.group.paying_round_prediction).prediction_payoff #this seems like an error....not an error #player.in_round(player.group.paying_round_allocation).payoff = player.in_round(player.group.paying_round_allocation).allocation_payoff+player.in_round(player.group.paying_round_prediction).prediction_payoff #num_paying_rounds_allocation = player.session.config['paying_rounds_allocation'] #num_paying_rounds_prediction = player.session.config['paying_rounds_prediction'] #ALTERNATIVA for x in player.session.vars['paying_rounds_allocation']: player.in_round(x).payoff = player.in_round(x).allocation_payoff earnings_allocation = sum(player.in_round(x).allocation_payoff for x in player.session.vars['paying_rounds_allocation']) for x in player.session.vars['paying_rounds_prediction']: player.in_round(x).payoff = player.in_round(x).prediction_payoff earnings_prediction = sum(player.in_round(x).prediction_payoff for x in player.session.vars['paying_rounds_prediction']) num_paying_rounds_allocation = player.session.config['paying_rounds_allocation'] num_paying_rounds_prediction = player.session.config['paying_rounds_prediction'] return dict( num_paying_rounds_allocation= num_paying_rounds_allocation, num_paying_rounds_prediction = num_paying_rounds_prediction, is_accountant=(get_role(player) in ['Region I Accountant', 'Region II Accountant']), paying_rounds_allocation=player.session.vars['paying_rounds_allocation'], paying_rounds_prediction=player.session.vars['paying_rounds_prediction'], player_in_all_rounds=player.in_all_rounds(), earnings_prediction=cu(earnings_prediction).to_real_world_currency(player.session), earnings_allocation=cu(earnings_allocation).to_real_world_currency(player.session), total_earnings=cu(player.participant.payoff).to_real_world_currency(player.session), show_up_fee=player.session.config['participation_fee'], total_payoff=player.participant.payoff_plus_participation_fee(), ) page_sequence = [ InstructionsBank, InstructionsAccountant, Period1Bank, BetweenPeriods, # Period2Bank, # Period2Accountant, buyOrSell, DeterminePrice, AssetMarket, buyOrSellAccountant, WaitForAccountant, WaitForResults, Results, ResultsAccountant, WaitforFinalResults, Questionnaire, FinalResults, ]