from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants #------------------------------------- # Welcome screens and instructions before the start of the experiment: #------------------------------------- class Instructions_WelcomeScreen(Page): template_name = 'MRE1/Instructions_WelcomeScreen.html' form_model = 'player' form_fields = ['browser_first', 'prolific_id'] def error_message(self,value): # print('prolific id is', value) # print(len(value)) if (value['prolific_id'] == None): return('Please enter your Prolific ID. Currently, the ID field is empty') elif (len(value['prolific_id']) != 24): id_len = len(value['prolific_id']) return('You Prolific ID is not correct! The ID you inserted has {} characters. The Prolific ID is 24 characters long'.format(id_len)) def vars_for_template(self): if self.player.participant.vars["goal_treatment"] == 1: return {'depends': 'an investment decision'} elif self.player.participant.vars["goal_treatment"] == 3: return {'depends': 'an investment decision'} else: return {'depends': 'a return prediction'} def is_displayed(self): return self.round_number == 1 class Demographics_BeforeExperiment(Page): # template_name = 'MRE1/Demographics_BeforeExperiment.html' form_model = 'player' form_fields = ['Demographics_Age','Demographics_Sex'] def is_displayed(self): return self.round_number == 1 class Instructions_Payment(Page): template_name = 'MRE1/Instructions_Payment.html' def vars_for_template(self): # randomize the payoff example import random inv_asset1 = c(random.randint(0,10)*(10**3)) # turn the interger into currency inv_asset2 = c(10000) - inv_asset1 r_asset1 = random.randint(-3,3)/10 r_asset2 = 0 #Cash has zero interest total_r = (1+r_asset1)*inv_asset1 + (1+r_asset2)*inv_asset2 bonus_pay = c(total_r/10000) total_pay = bonus_pay + c(2.5) your_resp = random.randint(6,18) real_resp = random.randint(6,18) payoff = max(1.5 -(abs(your_resp - real_resp) * c(0.10)),c(0)) mult = abs(your_resp-real_resp) deduction = min(abs(your_resp - real_resp) * c(0.10),1.5) your_resp1 = random.randint(0,100) real_resp1 = min(max(your_resp1 + random.randint(-33,33),0),100) payoff1 =max(1.5 - (abs(your_resp1 - real_resp1) * c(0.05)),c(0)) mult1 = abs(your_resp1 - real_resp1) deduction1 = c(min(abs(your_resp1 - real_resp1) * c(0.05), 1.5)) # return percentage to right form def percent_format(d): rendite1 = ' + ' + str("%.1f"% (d * 100)).rstrip('0').rstrip('.')+'%' if d < 0: rendite1 = ' - ' + str("%.1f"% (d * 100))[1:].rstrip('0').rstrip('.')+'%' return rendite1 import re def thousand_format(c): c_str = str(c) # currency to string c_space = re.sub(r"\B(?=(?:\d{3})+\.)", "\xa0", c_str) # add spacec with regex return c_space.rstrip('0').rstrip('.') # print(thousand_format(inv_asset1)) return {'inv_asset1': thousand_format(inv_asset1), 'inv_asset2': thousand_format(inv_asset2), 'total_r': thousand_format(total_r), 'r_asset1': percent_format(r_asset1), 'r_asset2': percent_format(r_asset2), 'r_plus11': 1+r_asset1, 'r_plus12': 1+r_asset2, 'bonus_pay': bonus_pay, 'total_pay': total_pay, 'your_resp': your_resp, 'real_resp':real_resp, 'payoff':payoff, 'your_resp1': your_resp1, 'real_resp1':real_resp1, 'payoff1':payoff1, 'deduction': deduction, 'mult' : mult, 'mult1': mult1, 'deduction1': deduction1 } def is_displayed(self): return self.round_number == 1 # class Instructions_InvestmentDecision(Page): # template_name = 'MRE1/Instructions_InvestmentDecision.html'z # def is_displayed(self): # return self.round_number == 1 #------------------------------------- # Experiment: #------------------------------------- class Instructions_Round1(Page): template_name = 'MRE1/Instructions_Round1.html' def vars_for_template(self): return {'depends': 'Next, you will see a return simulation of 20 possible returns for the asset. This simulation will give you an impression of the asset returns. The returns are drawn at random from the return distribution of the asset.'} def is_displayed(self): return self.round_number == 1 # NOT USED class Treatment(Page): template_name = 'MRE1/Treatment.html' def vars_for_template(self): return {'title': 'Table_information', 'array': self.player.participant.vars['distributions'][self.round_number-1], 'image_path':'MRE1/Empty.png' } class Treatment_show_all(Page): template_name = 'MRE1/Treatment_show_all.html' def vars_for_template(self): def set_color(numb): if(numb < 0): return 'negative' else: return 'positive' def format_percent(numb): return str(round(numb*100))+'%' # create a list containing all information of each row in HTML table table_inputs = [] i = 1 for pair in self.player.participant.vars['distributions'][self.round_number-1]: table_inputs.append({'color1': set_color(pair[0]), 'r1':format_percent(pair[0]), 'color2': set_color(pair[1]), 'r2': format_percent(pair[1]), 'sample_number': i}) i += 1 return {'inputs' : table_inputs} def is_displayed(self): return self.player.participant.vars["goal_treatment"] <= 2 class Task_InvestmentDecision(Page): template_name = 'MRE1/Task_InvestmentDecision.html' form_model = 'player' form_fields = ['InvestmentAsset1'] def vars_for_template(self): variable_for_2 = (self.participant.id_in_session - 1) % 4 + 1 return {'var' : variable_for_2} def error_message(self, values): if values["InvestmentAsset1"] > 10000: return 'The two investments have to add up to exactly £10\xa0000.' def is_displayed(self): return self.participant.vars["goal_treatment"] == 1 or self.participant.vars["goal_treatment"] == 3 class Task_InvestmentDecision1(Page): template_name = 'MRE1/Task_InvestmentDecision.html' form_model = 'player' form_fields = ['InvestmentAsset1'] def vars_for_template(self): variable_for_2 = (self.participant.id_in_session - 1) % 4 + 1 return {'var' : variable_for_2} def error_message(self, values): if values["InvestmentAsset1"] > 10000: return 'The two investments have to add up to exactly £10\xa0000.' def is_displayed(self): return self.participant.vars["goal_treatment"] == 2 or self.participant.vars["goal_treatment"] == 4 # class Task_BeliefsDependence(Page): # template_name = 'MRE1/Task_BeliefsDependence.html' # form_model = 'player' # form_fields = ['BeliefsDependence_Overall', 'BeliefsDependence_FreqComove1', 'BeliefsDependence_FreqOutperf'] class Task_BeliefsAssets(Page): template_name = 'MRE1/Task_BeliefsAssets.html' form_model = 'player' form_fields = ['BeliefsDependence_Mu1', 'BeliefsAssets_Risk1'] def vars_for_template(self): variable_for_2 = (self.participant.id_in_session - 1) % 4 + 1 return {'var' : variable_for_2} # class Task_BeliefsPortfolio(Page): # template_name = 'MRE1/Task_BeliefsPortfolio.html' # form_model = 'player' # form_fields = ['BeliefsPortfolio_Mu', 'BeliefsPortfolio_PLoss', 'BeliefsPortfolio_SubjRisk'] class Instructions_Round2(Page): template_name = 'MRE1/Instructions_Round2.html' def is_displayed(self): return self.round_number == 1 # return self.round_number == Constants.num_page def vars_for_template(self): return {'depends': 'Next, you will see a return simulation of 20 possible returns for the asset. This simulation will give you an impression of the asset returns. The returns are drawn at random from the return distribution of the asset. Take as much time as you need to view this return simulation.'} # class Task_RoundComparison(Page): # template_name = 'MRE1/Task_RoundComparison.html' # form_model = 'player' # form_fields = ['ComparisonRounds_Risk', 'ComparisonRounds_Return'] # def is_displayed(self): # return self.round_number == Constants.num_rounds #------------------------------------- # Questionnaire after experiment: #------------------------------------- class Task_ReasonsForDecision(Page): template_name = 'MRE1/Task_ReasonsForDecision.html' form_model = 'player' form_fields = ['GenReasons_Mu_Consider', 'GenReasons_SigmaPL_Consider', 'GenReasons_PD_Consider' ] def is_displayed(self): return self.round_number == Constants.num_rounds #NB: added to separate the Reasons questions into two pages class Task_ReasonsContinue(Page): template_name = 'MRE1/Task_ReasonsContinue.html' form_model = 'player' # select the questions asked based on the Task_ReasonsForDecision answers def get_form_fields(self): form_fields = [] player = self.player if player.GenReasons_Mu_Consider == 2: form_fields.append('GenReasons_Mu_Direction') if player.GenReasons_SigmaPL_Consider == 2 : form_fields.append('GenReasons_SigmaPL_Direction') if player.GenReasons_Rho_Consider==2: form_fields.append('GenReasons_Rho_Direction') if player.GenReasons_PD_Consider == 2: form_fields.append('GenReasons_PD_Direction') return form_fields def is_displayed(self): right_round = self.round_number == Constants.num_rounds player = self.player right_ans = player.GenReasons_Mu_Consider==2 or player.GenReasons_SigmaPL_Consider==2 or player.GenReasons_Rho_Consider==2 or player.GenReasons_PD_Consider==2 return (right_round and right_ans) class Demographics_1(Page): # template_name = 'MRE1/Demographics_1.html' form_model = 'player' form_fields = ['Demographics_FinInterest', 'Demographics_Investor', 'Demographics_FinanceProf', 'Demographics_RiskAffinity', 'Demographics_Statistics'] def is_displayed(self): return self.round_number == Constants.num_rounds class Demographics_2(Page): # template_name = 'MRE1/Demographics_2.html' form_model = 'player' form_fields = ['DJ30PF_Return', 'DJ30PF_Risk'] # calls set_payoffs() on player before next page [MU: is this the right place???] # NB: [MP to MU: Yes, it has to be on some page after return simulation and before payoff] def before_next_page(self): self.player.set_payoffs() def is_displayed(self): return self.round_number == Constants.num_rounds #------------------------------------- # Payment and link to Prolific: #------------------------------------- class FinalPaymentInformation(Page): template_name = 'MRE1/FinalPaymentInformation.html' form_model = 'player' form_fields = ['Satisfaction','OpenFeedback'] def is_displayed(self): return self.round_number == Constants.num_rounds def vars_for_template(self): # return percentage to right form if (self.participant.vars["goal_treatment"] == 1 or self.participant.vars["goal_treatment"] == 3): rendite1 = ' + ' + str("%.1f"% (self.player.paid_rendite1 * 100)).rstrip('0').rstrip('.') if self.player.paid_rendite1 < 0: rendite1 = ' - ' + str("%.1f"% (self.player.paid_rendite1 * 100))[1:].rstrip('0').rstrip('.') rendite2 = ' + ' +str("%.1f"% (self.player.paid_rendite2 * 100)).rstrip('0').rstrip('.') if self.player.paid_rendite2 < 0: rendite2 = ' - ' +str("%.1f"% (self.player.paid_rendite2 * 100))[1:].rstrip('0').rstrip('.') else: rendite1 = None rendite2 = None # Change currency to right form import re def right_form(c): c_str = str(c) # currency to string c_space = re.sub(r"\B(?=(?:\d{3})+\.)", " ", c_str) # add spacec with regex return c_space.rstrip('0').rstrip('.') # remove trailing zeros portfolio_val = right_form(self.player.payoff_100) payoff_val = self.player.payoff input1 = right_form(self.player.paid_input1) input2 = right_form(self.player.paid_input2) total_pay = c(2.50) + payoff_val response = "" real_response = "" if self.player.goal_treatment == 2 or 4: questions = [self.player.in_round(self.player.in_round(1).paid_subsection).BeliefsDependence_Mu1] answers = [self.player.in_round(self.player.in_round(1).paid_subsection).BeliefsDependence_Mu1_Res] index_temp = self.player.in_round(1).random_question_index response = questions[index_temp - 1] if index_temp == 1: response_fix = str(round(response,2)) + '%' else: response_fix = str(int(response)) + '/100' real_response = answers[index_temp - 1] if index_temp == 1: real_response_fix = str(round(real_response,2)) + '%' else: real_response_fix = str(int(real_response)) + '/100' return {'runde': self.player.pay_round_num, 'percent_1': rendite1, 'percent_2': rendite2, 'payoff': payoff_val, 'payoff_100': portfolio_val, 'paid_input1': input1, 'paid_input2': input2, 'total_pay': total_pay, 'goal_treatment': self.participant.vars["goal_treatment"], 'random_question_index': self.player.in_round(1).random_question_index, 'random_question_round': self.player.in_round(1).paid_subsection, 'short_q': self.player.in_round(1).short_q, 'your_resp': response_fix, 'real_res': real_response_fix } class LinkToProlific(Page): template_name = 'MRE1/LinkToProlific.html' def is_displayed(self): return self.round_number == Constants.num_rounds #------------------------------------- # Page sequence #------------------------------------- page_sequence = ( Instructions_WelcomeScreen, Demographics_BeforeExperiment, Instructions_Payment, #Instructions_InvestmentDecision, Instructions_Round1, Treatment, Treatment_show_all, Task_InvestmentDecision, #Task_BeliefsDependence, Task_BeliefsAssets, Task_InvestmentDecision1, #Task_BeliefsPortfolio, #Instructions_Round2, #Task_RoundComparison, Task_ReasonsForDecision, Task_ReasonsContinue, Demographics_1, Demographics_2, FinalPaymentInformation, LinkToProlific )