from otree.api import * class C(BaseConstants): NAME_IN_URL = 'treatment_1.5' PLAYERS_PER_GROUP = None NUM_ROUNDS = 5 INSTRUCTIONS_TEMPLATE = 'Instructions_Pages/instructions_round11_15.html' ENDOWMENT = 100 TXN_COST = 0.05 PRICE = [1,1.05,1.10,1.15,1.25,1.30,1.35,1.40,1.45,1.50,1.55,1.60,1.65,1.70,1.75] DELTA = [1000,1000,500,500,250,250,125,125,62.5,62.5] PC = [1000,2000,2500,3000,3250,3500,3625,3750,3812.5,3875] class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): initial_bid_forex = models.IntegerField( min=0, label="Initial Bid for Currency Exchange" ) second_bid_forex = models.FloatField( min=0, label="Second Bid for Currency Exchange" ) initial_bid_quantity = models.IntegerField( min=0, max=100, label="Initial Bid for Good A" ) second_bid_fiat = models.IntegerField( min=0, label="Second Bid for Good A (Tokens)" ) second_bid_private = models.IntegerField( min=0, label="Second Bid for Good A (Tickets)" ) # FUNCTIONS def calculate_money_balance_fiat(player): participant = player.participant beginning_fiat_balance = participant.money_balance_fiat + C.ENDOWMENT participant.fiat_money_balance_before_forex = beginning_fiat_balance return beginning_fiat_balance def calculate_exchange_rate(player): group = player.group round_number = player.round_number delta_this_round = C.DELTA[round_number + 4] allplayers = group.get_players() total_bids_private_currency = sum([(p.initial_bid_forex) for p in allplayers]) exchange_rate = total_bids_private_currency / delta_this_round exchange_rate_display = round((total_bids_private_currency / delta_this_round), 2) exchange_rate_display = float(exchange_rate_display) return exchange_rate, exchange_rate_display def second_bid_forex_max(player): fiat_balance = calculate_money_balance_fiat(player) exchange_rate, exchange_rate_display = calculate_exchange_rate(player) maximum_bid = fiat_balance / exchange_rate maximum_bid = round(float(maximum_bid), 2) return maximum_bid def second_bid_fiat_max(player): import math round_number = player.round_number price_this_round = C.PRICE[round_number + 9] fiat_balance = calculate_money_balance_fiat(player) exchange_rate, exchange_rate_display = calculate_exchange_rate(player) quantity_exchanged = float(player.second_bid_forex) * float(exchange_rate) new_fiat_balance = fiat_balance - quantity_exchanged max_quantity = math.floor((new_fiat_balance / (price_this_round))) if max_quantity >= 100: max_quantity = 100 elif max_quantity <= 0: max_quantity = 0 else: max_quantity = max_quantity return max_quantity def second_bid_private_max(player): import math participant = player.participant round_number = player.round_number price_this_round = C.PRICE[round_number + 9] exchange_rate, exchange_rate_display = calculate_exchange_rate(player) private_currency_balance = participant.money_balance_private + player.second_bid_forex max_quantity = math.floor((float(private_currency_balance) * float(exchange_rate)) / (price_this_round + C.TXN_COST)) if max_quantity >= 100: max_quantity = 100 elif max_quantity <= 0: max_quantity = 0 else: max_quantity = max_quantity return max_quantity # PAGES class Introduction(Page): @staticmethod def before_next_page(player, timeout_happened): player.initial_bid_forex = None player.second_bid_forex = None player.initial_bid_quantity = None player.second_bid_fiat = None player.second_bid_private = None @staticmethod def vars_for_template(player): round_number = player.round_number round_number = round_number + 10 return dict(round_number=round_number) class Forex1(Page): form_model = 'player' form_fields = ['initial_bid_forex'] @staticmethod def vars_for_template(player): round_number = player.round_number price_this_round = C.PRICE[round_number + 9] price_last_round = C.PRICE[round_number + 8] delta_this_round = C.DELTA[round_number + 4] pc_supply_this_round = C.PC[round_number + 4] fiat_balance = calculate_money_balance_fiat(player) fiat_inflation = ((price_this_round-price_last_round)/(price_last_round))*100 fiat_inflation = round(float(fiat_inflation), 2) fiat_balance = round(float(fiat_balance), 2) return dict(fiat_balance=fiat_balance, fiat_inflation=fiat_inflation, delta_this_round=delta_this_round, pc_supply_this_round=pc_supply_this_round) class ForexWaitPage(WaitPage): pass class Forex2(Page): form_model = 'player' form_fields = ['second_bid_forex'] @staticmethod def vars_for_template(player): import math exchange_rate, exchange_rate_display = calculate_exchange_rate(player) initial_fiat_balance_bid = player.initial_bid_forex maximum_exchange = math.floor(initial_fiat_balance_bid/exchange_rate) maximum_exchange = float(maximum_exchange) return dict(initial_fiat_balance_bid=initial_fiat_balance_bid, maximum_exchange=maximum_exchange, exchange_rate=exchange_rate_display) class Bid1(Page): form_model = 'player' form_fields = ['initial_bid_quantity'] @staticmethod def vars_for_template(player): participant = player.participant exchange_rate, exchange_rate_display = calculate_exchange_rate(player) fiat_money_balance = calculate_money_balance_fiat(player) new_fiat_money_balance = float(fiat_money_balance) - (float(player.second_bid_forex) * float(exchange_rate)) private_money_balance = participant.money_balance_private + player.second_bid_forex new_fiat_money_balance = round(float(new_fiat_money_balance), 2) private_money_balance = round(float(private_money_balance), 2) return dict(new_fiat_money_balance=new_fiat_money_balance, private_money_balance=private_money_balance) class BidWaitPage(WaitPage): pass class Bid2(Page): form_model = 'player' form_fields = ['second_bid_fiat', 'second_bid_private'] @staticmethod def vars_for_template(player): import math participant = player.participant round_number = player.round_number price_this_round = C.PRICE[round_number + 9] exchange_rate, exchange_rate_display = calculate_exchange_rate(player) money_balance_fiat = calculate_money_balance_fiat(player) new_fiat_money_balance = float(money_balance_fiat) - (float(player.second_bid_forex) * float(exchange_rate)) money_balance_private = participant.money_balance_private + player.second_bid_forex price_in_private_currency = price_this_round / exchange_rate txn_cost_in_private_currency = C.TXN_COST / exchange_rate maximum_quantity_fiat = max(math.floor((new_fiat_money_balance / (price_this_round))), 0) maximum_quantity_private = max(math.floor(((money_balance_private) / (price_in_private_currency + txn_cost_in_private_currency))), 0) sum_total_quantity = maximum_quantity_fiat + maximum_quantity_private if sum_total_quantity >= 100: sum_total_quantity = 100 elif sum_total_quantity <= 0: sum_total_quantity = 0 else: sum_total_quantity = sum_total_quantity if maximum_quantity_fiat >= 100: maximum_quantity_fiat = 100 elif maximum_quantity_fiat <= 0: maximum_quantity_fiat = 0 else: maximum_quantity_fiat = maximum_quantity_fiat if maximum_quantity_private >= 100: maximum_quantity_private = 100 elif maximum_quantity_private <= 0: maximum_quantity_private = 0 else: maximum_quantity_private = maximum_quantity_private price_in_private_currency = round(float(price_in_private_currency), 2) txn_cost_in_private_currency = round(float(txn_cost_in_private_currency), 2) new_fiat_money_balance = round(float(new_fiat_money_balance), 2) money_balance_private = round(float(money_balance_private), 2) return dict(price_in_private_currency=price_in_private_currency, txn_cost_in_private_currency=txn_cost_in_private_currency, maximum_quantity_fiat=maximum_quantity_fiat, maximum_quantity_private=maximum_quantity_private, sum_total_quantity=sum_total_quantity, new_fiat_money_balance=new_fiat_money_balance, money_balance_private=money_balance_private, price_this_round=price_this_round) @staticmethod def error_message(player, values): print('values is', values) if values['second_bid_fiat'] + values['second_bid_private'] > 100: return "You cannot purchase more than 100 units of Good A!" class ResultsWaitPage(WaitPage): pass class Results(Page): @staticmethod def vars_for_template(player): participant = player.participant group = player.group round_number = player.round_number price_this_round = C.PRICE[round_number + 9] pc_supply_this_round = C.PC[round_number + 4] participant.exchange_rate, exchange_rate_display = calculate_exchange_rate(player) total_second_bid_before_round = participant.sum_total_quantity participant.sum_total_quantity = total_second_bid_before_round + player.second_bid_fiat + player.second_bid_private txn_cost_in_round_fiat = 0 total_txn_cost_fiat_before_round = participant.total_txn_cost_fiat participant.total_txn_cost_fiat = total_txn_cost_fiat_before_round + txn_cost_in_round_fiat txn_cost_in_round_private = player.second_bid_private * (float(C.TXN_COST)/participant.exchange_rate) total_txn_cost_private_before_round = participant.total_txn_cost_private participant.total_txn_cost_private = total_txn_cost_private_before_round + txn_cost_in_round_private market_price_private_currency = price_this_round / participant.exchange_rate fiat_money_balance = calculate_money_balance_fiat(player) participant.money_balance_fiat = float(fiat_money_balance) - (float(player.second_bid_forex) * float(participant.exchange_rate)) - ((float(player.second_bid_fiat)) * (price_this_round)) private_money_balance = participant.money_balance_private participant.money_balance_private = private_money_balance + player.second_bid_forex - (float(player.second_bid_private) * (market_price_private_currency)) - txn_cost_in_round_private allplayers = group.get_players() num_players = len(allplayers) beginning_money_supply = participant.fiat_money_supply new_money_supply = beginning_money_supply + (num_players * C.ENDOWMENT) total_bids_fiat = sum([p.second_bid_fiat for p in allplayers]) govt_purchases = (price_this_round - 1) * total_bids_fiat new_money_created = govt_purchases * price_this_round money_supply_fiat = new_money_supply + new_money_created participant.fiat_money_supply = money_supply_fiat market_price_private_currency = round(float(market_price_private_currency), 2) txn_cost_in_round_fiat = round(float(txn_cost_in_round_fiat), 2) txn_cost_in_round_private = round(float(txn_cost_in_round_private), 2) participant.total_txn_cost_fiat = round(float(participant.total_txn_cost_fiat), 2) participant.total_txn_cost_private = round(float(participant.total_txn_cost_private), 2) participant.money_balance_fiat = round(float(participant.money_balance_fiat), 2) participant.money_balance_private = round(float(participant.money_balance_private), 2) return dict(txn_cost_in_round_fiat=txn_cost_in_round_fiat, txn_cost_in_round_private=txn_cost_in_round_private, market_price_private_currency=market_price_private_currency, price_this_round=price_this_round, pc_supply_this_round=pc_supply_this_round) page_sequence = [Introduction, Forex1, ForexWaitPage, Forex2, Bid1, BidWaitPage, Bid2, ResultsWaitPage, Results]