from otree.api import * from settings import SESSION_CONFIG_DEFAULTS 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 preferences and compulsivity/learning rates. """ ### Define constants here, in all-caps class C(BaseConstants): NAME_IN_URL = 'fl' PLAYERS_PER_GROUP = None NUM_ROUNDS = 1 NUM_QUESTIONS = 15 + 1 CONVERSION_FACTOR = SESSION_CONFIG_DEFAULTS['conversion_factor'] CORRECT_ANSWER_FEE = cu(SESSION_CONFIG_DEFAULTS['correct_answer_fee'] * CONVERSION_FACTOR) class Subsession(BaseSubsession): pass class Group(BaseGroup): pass ### define the questions a player must answer here class Player(BasePlayer): ## Session indices day = models.IntegerField() app_sequence = models.IntegerField() inf_sequence = models.IntegerField() intervention = models.IntegerField() ### Financial Knowledge ### choices = [[value,label],[value,label],...] finK_1 = models.IntegerField( choices = [[-1,'Moins de 1 100 euros',],[0,'Exactement 1 100 euros'],[1,'Plus de 1 100 euros'],[9,'Je ne sais pas']], label = 'Prenons l’hypothèse que vous ayez déposé 1.000 euros sur un compte épargne ayant un rendement de 2 % par an. Selon vous, au bout de cinq ans, combien détiendrez-vous sur votre compte épargne, si vous n’avez pas touché à votre dépôt initial ?', widget = widgets.RadioSelect ) finK_2 = models.IntegerField( choices = [[1,'Plus qu’aujourd’hui',],[0,'Autant qu’aujourd’hui'],[-1,'Moins qu’aujourd’hui'],[9,'Je ne sais pas']], label = 'Imaginez que le taux d’intérêt auquel est rémunérée votre épargne, placée sur un compte, soit de 1 % et l’inflation de 2 % par an. Selon vous, au bout d’un an, avec l’argent sur ce compte, vous serez en mesure d’acheter ?', widget = widgets.RadioSelect ) finK_3 = models.IntegerField( choices = [[1,'1 - Le moins risqué'],[2,'2 - Le deuxième moins risqué'],[3,'3 - Le deuxième plus risqué'],[4,'4 - Le plus risqué']], label = 'Livret d’épargne', widget = widgets.RadioSelect ) finK_4 = models.IntegerField( choices = [[1,'1 - Le moins risqué'],[2,'2 - Le deuxième moins risqué'],[3,'3 - Le deuxième plus risqué'],[4,'4 - Le plus risqué']], label = 'Actions', widget = widgets.RadioSelect ) finK_5 = models.IntegerField( choices = [[1,'1 - Le moins risqué'],[2,'2 - Le deuxième moins risqué'],[3,'3 - Le deuxième plus risqué'],[4,'4 - Le plus risqué']], label = 'Obligations', widget = widgets.RadioSelect ) finK_6 = models.IntegerField( choices = [[1,'1 - Le moins risqué'],[2,'2 - Le deuxième moins risqué'],[3,'3 - Le deuxième plus risqué'],[4,'4 - Le plus risqué']], label = 'SICAV/Fond commun de placement (FCP)', widget = widgets.RadioSelect ) finK_7 = models.BooleanField( choices = [[True,'True'],[False,'False']], label = 'An investment with a high return is likely to be high risk, true or false?', widget = widgets.RadioSelect ) finK_8 = models.BooleanField( choices = [[True,'True'],[False,'False']], label = 'High inflation means that the cost of living is increasing rapidly, true or false?', widget = widgets.RadioSelect ) finK_9 = models.BooleanField( choices = [[True,'True'],[False,'False']], label = 'It is usually possible to reduce the risk of investing in the stock market by buying a wide range of stocks and shares, true or false?', widget = widgets.RadioSelect ) ### Financial Behavior finB_1 = models.IntegerField( choices = [[0,'Me'],[1,'My parents'],[2,'My partner'],[3,'I am not sure']], label = 'Who is responsible for making day-to-day financial decisions in your household?', widget = widgets.RadioSelect ) finB_2 = models.IntegerField( choices = [[0,"Je n'ai pas de compte bancaire"], [1,'Tous les jours'], [2,'Deux à trois fois par semaine'], [3,'Une fois par semaine'], [4,'Tous les quinze jours'], [5,'Une fois par mois'], [6,"Rarement (moins d'une fois par mois)"], [7,"Seulement si j'ai besoin d'une grosse somme"], [9,"Jamais"], [10,"Ne sait pas"], [11,"Ne souhaite pas répondre"]], label = 'Si vous avez au moins un compte bancaire, à quelle fréquence en vérifiez-vous le solde ?', widget = widgets.RadioSelect ) finB_3 = models.IntegerField( choices = [[0,"Je n'ai pas de compte bancaire"], [1,'Oui, mais pas précisément'], [2,'Oui (à ± 5 %)'], [3,'Non, je ne sais pas'], [11,'Ne souhaite pas répondre']], label = 'Si vous avez un compte bancaire, savez-vous quel est son solde actuel ?', widget = widgets.RadioSelect ) finB_4 = models.BooleanField( choices = [[True,'Oui'],[False,'Non']], label = 'Faites-vous vos comptes régulièrement ?', widget = widgets.RadioSelect ) finB_5 = models.BooleanField( choices = [[True,'Oui'],[False,'Non']], label = 'Étiez-vous déjà à découvert cette année ?', widget = widgets.RadioSelect ) ### Fiancial Attitude finAtt_1 = models.BooleanField( choices = [[True,'True'],[False,'False']], label = 'I find it more satisfying to spend money than to save it for the long term', widget = widgets.RadioSelect ) # Functions # PAGES class Finance_Intro(Page): counter_questions = 0 class FinancialKnowledge_1(Page): form_model = 'player' form_fields = ['finK_1','finK_2'] counter_questions = Finance_Intro.counter_questions + 1 ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(FinancialKnowledge_1.counter_questions / C.NUM_QUESTIONS * 100,) ) class FinancialKnowledge_2(Page): form_model = 'player' form_fields = ['finK_3','finK_4','finK_5','finK_6'] counter_questions = FinancialKnowledge_1.counter_questions + len(FinancialKnowledge_1.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(FinancialKnowledge_2.counter_questions / C.NUM_QUESTIONS * 100,) ) @staticmethod def error_message(player, values): print('values is', values) if values['finK_3'] + values['finK_4'] + values['finK_5'] + values['finK_6'] != 10: return 'Veuillez confirmer que vous avez bien distingué les risque de chaque produits de 1 à 4 (du moins risqué au plus risqué)' class FinancialKnowledge_3(Page): form_model = 'player' form_fields = ['finK_7','finK_8','finK_9'] counter_questions = FinancialKnowledge_2.counter_questions + len(FinancialKnowledge_2.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(FinancialKnowledge_3.counter_questions / C.NUM_QUESTIONS * 100,) ) class FinancialBehavior(Page): form_model = 'player' form_fields = ['finB_1','finB_2','finB_3','finB_4','finB_5'] counter_questions = FinancialKnowledge_3.counter_questions + len(FinancialKnowledge_3.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(FinancialBehavior.counter_questions / C.NUM_QUESTIONS * 100,) ) class FinancialAttitude(Page): form_model = 'player' form_fields = ['finAtt_1'] counter_questions = FinancialBehavior.counter_questions + len(FinancialBehavior.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(FinancialAttitude.counter_questions / C.NUM_QUESTIONS * 100,) ) class Results(Page): counter_questions = FinancialAttitude.counter_questions + len(FinancialAttitude.form_fields) ## For progress bars @staticmethod def vars_for_template(player: Player): return dict( percentage=round(Results.counter_questions / C.NUM_QUESTIONS * 100,) ) page_sequence = [ Finance_Intro, FinancialKnowledge_1, FinancialKnowledge_2, FinancialKnowledge_3, FinancialBehavior, FinancialAttitude, Results ]