from otree.api import * author = 'Nathaniel Lawrence, LEMMA, Université Panthéon-Assas' doc = """ This app provides a consumption simultion app, combined with surveys on demographics; financial knowledge, behavior, and attitude; and numeracy; as well as tests of time and risk preferences, loss aversion, impulsivity, and learning rates. Sliders provided courtesy of Max R. P. Grossmann, https://gitlab.com/gr0ssmann/otree_slider and Van Pelt, V. F. J. (2020, February 19). Sliders with feedback and without anchoring. Accounting Experiments, Available at: https://www.accountingexperiments.com/post/sliders/. """ ### Define constants here, in all-caps class C(BaseConstants): NAME_IN_URL = 'pda' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 TIME_LIMIT = 3 SLIDER_TEST = -73 QUESTION_PRICE = 1000 TABLE_1 = __name__ + '/table_1.html' TABLE_2 = __name__ + '/table_2.html' class Subsession(BaseSubsession): pass class Group(BaseGroup): pass ### define the questions a player must answer here class Player(BasePlayer): ### choices = [[value,label],[value,label]] ### Instructions - Test understanding of slider slider = models.FloatField() ### Level of knowledge of previous inflation rates (Macchia et al., 2018) infK_1 = models.FloatField() infK_2 = models.FloatField() infK_3 = models.FloatField() infK_4 = models.FloatField() infK_5 = models.FloatField() infK_6 = models.FloatField() ### Level of knowledge of calculation of impact of compound interest (Macchia et al., 2018) infCI_1 = models.FloatField( label = 'If inflation is 10% a year, and a product currently costs {}, how much will it cost in one year’s time?'.format(cu(C.QUESTION_PRICE)), min = 0, max = 9999 ) infCI_2 = models.FloatField( label = 'If inflation is 50% a year, and a product currently costs {}, how much will it cost in two year’s time?'.format(cu(C.QUESTION_PRICE)), widget = widgets.RadioSelect ) infCI_3 = models.FloatField( label = 'If inflation is 3% a year, and a product currently costs {}, how much will it cost in five year’s time?'.format(cu(C.QUESTION_PRICE)), widget = widgets.RadioSelect ) infCI_4 = models.FloatField( label = 'If inflation is 100% a year, and a product currently costs {}, how much will it cost in five year’s time?'.format(cu(C.QUESTION_PRICE)), min = 0, max = 999999 ) ### Inflation Awareness inf_4 = models.IntegerField( choices = [[1,'Augmenté'],[-1,'Baissé'],[0,'Resté constant'],[5,'Pas concerné'],[9,'Je ne sais pas']], label = 'Votre pouvoir d’achat a-t-il augmenté, baissé, resté constant pendant les 12 derniers mois ?', widget = widgets.RadioSelect ) inf_5 = models.IntegerField( choices = [[1,'Augmenté'],[-1,'Baissé'],[0,'Resté constant'],[5,'Pas concerné'],[9,'Je ne sais pas']], label = 'Votre salarie a-t-il été augmenté, baissé, resté constant pendant les 12 derniers mois ?', widget = widgets.RadioSelect ) inf_6 = models.FloatField( # label = 'Si votre salaire a été augmenté ou baissé cette année, de combien (%) ?' ) inf_7 = models.IntegerField( choices = [[1,'Augmenté'],[-1,'Baissé'],[0,'Resté constant'],[5,'Pas concerné'],[9,'Je ne sais pas']], label = 'Attendez-vous que votre salaire soit augmenté, baissé, resté constant dans les 12 prochains mois ?', widget = widgets.RadioSelect ) inf_8 = models.FloatField( # label = 'Si vous attendez une augmentation ou une baisse cette année, de combien (%) ?' ) inf_9_cheaper = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Substitution of current products you buy with cheaper versions', widget = widgets.RadioSelect ) inf_9_quantity = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'The quantity of current products you buy', widget = widgets.RadioSelect ) inf_9_stockMaintained = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'The size of the stock you maintain of products whose price changes', widget = widgets.RadioSelect ) inf_9_leisure = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Spending on leisure activities', widget = widgets.RadioSelect ) inf_9_subscription = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Cancel subscriptions', widget = widgets.RadioSelect ) inf_9_insurance = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Investment in life insurance', widget = widgets.RadioSelect ) inf_9_realEstate = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Investment in real estate', widget = widgets.RadioSelect ) inf_9_livret = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Investment in savings accounts', widget = widgets.RadioSelect ) inf_9_mutualFunds = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Investment in mutual funds', widget = widgets.RadioSelect ) inf_9_stocks = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Investment in stocks', widget = widgets.RadioSelect ) inf_9_indexedBonds = models.IntegerField( choices = [[1,'Increase'],[0,'No change'],[-1,'Decrease']], label = 'Investment in indexed bonds', widget = widgets.RadioSelect ) inf_9_move = models.IntegerField( choices = [[1,'Yes'],[-1,'No'],[0,'Maybe']], label = 'Move to an apartment with lower rent', widget = widgets.RadioSelect ) inf_9_income = models.IntegerField( choices = [[1,'Yes'],[-1,'No'],[0,'Maybe']], label = 'Seek additional sources of income', widget = widgets.RadioSelect ) inf_9_job = models.IntegerField( choices = [[1,'Yes'],[-1,'No'],[0,'Maybe']], label = 'Seek a new job', widget = widgets.RadioSelect ) inf_10 = models.BooleanField( choices = [[True,'Yes'],[False,'No']], label = 'Have you done any of that in the past 12 months?', widget = widgets.RadioSelect ) inf_11 = models.BooleanField( choices = [[True,'Yes'],[False,'No']], label = 'Do you think inflation can be controlled?', widget = widgets.RadioSelect ) inf_12 = models.IntegerField( choices = [[1,'Private businesses'],[2,'Politicians'],[3,'Central banks'],[3,'Private banks'],[4,'No one'],[9,"I don't know"]], label = 'In your opinion, who should fix inflation?', widget = widgets.RadioSelect ) # def infCI_1_choices(player): # import random # choices = [ # [1,'US$1,100'], # [2,'More than US$1,100'], # [3,'Less than US$1,100'] # ] # random.shuffle(choices) # return choices def infCI_2_choices(player): import random choices = [ [1,'{}'.format(cu(C.QUESTION_PRICE * 2))], [2,'More than {}'.format(cu(C.QUESTION_PRICE * 2))], [3,'Less than {}'.format(cu(C.QUESTION_PRICE * 2))] ] random.shuffle(choices) return choices def infCI_3_choices(player): import random choices = [ [1,'{}'.format(cu(C.QUESTION_PRICE + 15))], [2,'More than {}'.format(cu(C.QUESTION_PRICE + 15))], [3,'Less than {}'.format(cu(C.QUESTION_PRICE + 15))] ] random.shuffle(choices) return choices # PAGES class InflationInstructions(Page): form_model = 'player' form_fields = ['slider'] @staticmethod def error_message(player, values): solutions = dict( slider=C.SLIDER_TEST ) error_messages = dict() for field_name in solutions: if values[field_name] != solutions[field_name]: error_messages[field_name] = 'That is incorrect. Please, correct your answer by selecting the appropriate value on the Slider.' return error_messages class InflationKnowledge_1(Page): form_model = 'player' form_fields = ['infK_1'] timeout_seconds = C.TIME_LIMIT class InflationTimerStart(Page): pass class InflationKnowledge_2(Page): form_model = 'player' form_fields = ['infK_2'] timeout_seconds = C.TIME_LIMIT class InflationKnowledge_3(Page): form_model = 'player' form_fields = ['infK_3'] timeout_seconds = C.TIME_LIMIT class InflationKnowledge_4(Page): form_model = 'player' form_fields = ['infK_4'] timeout_seconds = C.TIME_LIMIT class InflationKnowledge_5(Page): form_model = 'player' form_fields = ['infK_5'] timeout_seconds = C.TIME_LIMIT class InflationKnowledge_6(Page): form_model = 'player' form_fields = ['infK_6'] timeout_seconds = C.TIME_LIMIT class InflationNumeracy(Page): form_model = 'player' form_fields = ['infCI_1','infCI_2','infCI_3','infCI_4'] class InflationTimerEnd(Page): pass class InflationAwareness_1(Page): form_model = 'player' form_fields = ['inf_4','inf_5'] class InflationAwareness_2(Page): form_model = 'player' form_fields = ['inf_6'] @staticmethod def is_displayed(player): return player.inf_5 == 1 or player.inf_5 == -1 class InflationAwareness_3(Page): form_model = 'player' form_fields = ['inf_7'] class InflationAwareness_4(Page): form_model = 'player' form_fields = ['inf_8'] @staticmethod def is_displayed(player): return player.inf_7 == 1 or player.inf_7 == -1 class InflationAwareness_5(Page): form_model = 'player' form_fields = [ 'inf_9_cheaper', 'inf_9_quantity', 'inf_9_stockMaintained', 'inf_9_subscription', 'inf_9_leisure', 'inf_9_insurance', 'inf_9_realEstate', 'inf_9_livret', 'inf_9_mutualFunds', 'inf_9_stocks', 'inf_9_indexedBonds', ] class InflationAwareness_6(Page): form_model = 'player' form_fields = [ 'inf_9_move', 'inf_9_income', 'inf_9_job', ] class InflationAwareness_7(Page): form_model = 'player' form_fields = [ 'inf_10', 'inf_11', 'inf_12' ] class ResultsWaitPage(WaitPage): pass class Results(Page): pass page_sequence = [InflationInstructions, InflationTimerStart, InflationKnowledge_1, InflationKnowledge_2, InflationKnowledge_3, InflationTimerEnd, InflationNumeracy, InflationAwareness_1, InflationAwareness_2, InflationAwareness_3, InflationAwareness_4, InflationAwareness_5, InflationAwareness_6, InflationAwareness_7, InflationTimerStart, InflationKnowledge_4, InflationKnowledge_5, InflationKnowledge_6, InflationTimerEnd]