# -*- coding: utf8 -*- # import otree.models import otree.constants from otree.api import (models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,Currency as c, currency_range ) import random doc = """ Forecast game in which participants forecast future (net) output at different horizons """ # parameters that do not change: to refer to them constants.something, no need for self. as not part of the hierarchy class Constants(otree.constants.BaseConstants): players_per_group = None # as we have only one group of players num_rounds = 70 show_up_fee = 0 current=0 rho = 0.95 beta=1 a1 = 2 a2 = -1 a3 =0 theta_init=0 sigma_eta=10 sigma_epsilon=1 sigma_u=1 base=0 score_param=20 name_in_url = 'Forecast' class Subsession(otree.models.BaseSubsession): def creating_session(self): count = -1 for p in self.get_players(): count += 1 p.timeseries = str(count) ind = 0 list_of_lists = [] with open('forecasting/ser'+str(count)+'.txt', encoding='utf-8') as f: for line in f: inner_list = [float(elt.strip()) for elt in line.split(',')] list_of_lists.append(inner_list) ind += 1 by_cols = list(zip(*list_of_lists)) p.participant.vars['epsilon_init'] = by_cols[5][:Constants.num_rounds] # From normal Distribution p.participant.vars['eta_init'] = by_cols[3][:Constants.num_rounds] p.participant.vars['u_init'] = by_cols[4][:Constants.num_rounds] p.participant.vars['epsilon'] = by_cols[5][Constants.num_rounds:] p.participant.vars['eta'] = by_cols[3][Constants.num_rounds:] p.participant.vars['u'] = by_cols[4][Constants.num_rounds:] # self.participant.vars['epsilon_init'] = [random.normalvariate(0, Constants.sigma_epsilon) for i in # range(Constants.num_rounds)] # From normal Distribution # self.participant.vars['eta_init'] = [random.normalvariate(0, Constants.sigma_eta) for i in # range(Constants.num_rounds)] # self.participant.vars['u_init'] = [random.normalvariate(0, Constants.sigma_u) for i in # range(Constants.num_rounds)] # # self.participant.vars['epsilon'] = [random.normalvariate(0, Constants.sigma_epsilon) for i in # range(Constants.num_rounds)] # From normal Distribution # self.participant.vars['eta'] = [random.normalvariate(0, Constants.sigma_eta) for i in # range(Constants.num_rounds)] # self.participant.vars['u'] = [random.normalvariate(0, Constants.sigma_u) for i in # range(Constants.num_rounds)] p.participant.vars['theta_init'] = [0] * (Constants.num_rounds) p.participant.vars['x1_init'] = [0] * (Constants.num_rounds) p.participant.vars['x2_init'] = [0] * (Constants.num_rounds) p.participant.vars['y_init'] = [0] * (Constants.num_rounds) for i in range(1, (Constants.num_rounds)): p.participant.vars['theta_init'][i] = Constants.rho * p.participant.vars['theta_init'][i - 1] + \ p.participant.vars['eta_init'][i] p.participant.vars['x1_init'][i] = Constants.base + Constants.a1 * p.participant.vars['theta_init'][i] + \ p.participant.vars['u_init'][i] p.participant.vars['x2_init'][i] = Constants.base + Constants.a2 * p.participant.vars['theta_init'][i] p.participant.vars['y_init'][i] = Constants.beta * ( -Constants.base + p.participant.vars['x1_init'][i] + p.participant.vars['x2_init'][i] + p.participant.vars['epsilon_init'][i]) #debt = models.BooleanField() #horizon = models.IntegerField() #consensus = models.BooleanField() # definition of the treatment # def creating_session(self): # # randomize to treatments # for player in self.get_groups(): # player.color = random.choice(['blue', 'red']) # ISA: create a whole sequence of shocks, check that use of keys and dictionary is ok! #def creating_session(self): # random.seed(10) 1 no need for randomness in the shocks # if self.session.config['treatment']=='debt4': # self.horizon=2 # self.debt=True # self.consensus=False # elif self.session.config['treatment'] == 'debt8': # self.horizon = 6 # self.debt = True # self.consensus = False # if self.session.config['treatment']=='nodebt4': # self.horizon=2 # self.debt=False # self.consensus = False # elif self.session.config['treatment'] == 'nodebt8': # self.horizon = 6 # self.debt = False # self.consensus = False # elif self.session.config['treatment'] == 'consen_med': # self.horizon = 6 # self.debt = False # self.consensus = True # elif self.session.config['treatment'] == 'consen_best': # self.horizon = 6 # self.debt = False # self.consensus = True # elif self.session.config['treatment'] == 'revision': # self.horizon = 6 # self.debt = False # self.consensus = False #random.seed(10) # the main thing of the experiment is in group: class Group(otree.models.BaseGroup): pass class Player(otree.models.BasePlayer): prolific_id = models.StringField(default=str(" ")) theta = models.FloatField() x1 = models.FloatField() x2 = models.FloatField() y = models.FloatField() eta = models.FloatField() epsilon = models.FloatField() u = models.FloatField() token = models.StringField() timeseries = models.StringField() # it is a function set_payoffs, self is the argument (group in this case), function called from the views file # # group = models.ForeignKey(Group, null=True) # subsession = models.ForeignKey(Subsession) # # save the players' forecasts nowcast = models.FloatField( initial=1000, doc=""" Each player's forecast: """ # {} # """.format(Constants.guess_max) ) forecast = models.FloatField( initial=1000, doc=""" Each player's forecast: """ # {} # """.format(Constants.guess_max) ) que1 = models.StringField( initial='10' ) que2 = models.StringField( initial='10' ) que3 = models.StringField( initial='10' ) attemp = models.IntegerField( initial='0' ) consent = models.BooleanField(widget=widgets.CheckboxInput(), initial=False ) # for the time out no_decision_timeout = models.BooleanField(initial=False) forecast_2lag = models.FloatField(min=0, initial=None) nowcast_lag = models.FloatField(min=0, initial=None) paid_forc = models.FloatField(min=0, initial=None) abs_FE = models.FloatField(min=0, initial=None) # forecast error in a period score_FE = models.FloatField(min=0, initial=None) # payoff in a period abs_NE = models.FloatField(min=0, initial=None) # forecast error in a period score_NE = models.FloatField(min=0, initial=None) # payoff in a period cum_score_y = models.FloatField(min=0, initial = 0) # cumulative payoff tot_score = models.FloatField(min=0, initial = 0) discounted_cum_score = models.FloatField(min=0, initial = 0) real_cum_score_y = models.CurrencyField(min=0, initial = 0) # cumulative payoff in terms of euros FE_selected = models.IntegerField() def model(self): #random.seed(None) if self.subsession.round_number == 1: self.theta = Constants.rho * self.participant.vars['theta_init'][Constants.num_rounds - 1] + \ self.participant.vars['eta'][ self.subsession.round_number - 1] else: self.theta = Constants.rho * self.in_previous_rounds()[-1].theta + self.participant.vars['eta'][ self.subsession.round_number - 1] self.x1 = Constants.base + Constants.a1 * self.theta + self.participant.vars['u'][self.subsession.round_number - 1] self.x2 = Constants.base + Constants.a2 * self.theta self.y = Constants.beta * (-Constants.base + self.x1 + self.x2 + self.participant.vars['epsilon'][ self.subsession.round_number - 1]) self.epsilon = self.participant.vars['epsilon'][self.subsession.round_number - 1] self.u = self.participant.vars['u'][self.subsession.round_number - 1] self.eta = self.participant.vars['eta'][self.subsession.round_number - 1] def set_payoffs(self): if self.subsession.round_number == 1: # Initialize, remember round_number starts from 1 and not 0!! self.forecast_2lag = 1000 self.nowcast_lag = 1000 self.score_NE = 0 self.score_FE = 0 self.tot_score = 0 self.FE_selected = 0 self.cum_score_y = self.score_NE elif self.subsession.round_number == 2: self.forecast_2lag = 1000 self.nowcast_lag = self.in_previous_rounds()[-1].nowcast self.abs_NE = abs(self.y - self.in_previous_rounds()[-1].nowcast) self.score_NE = round(100 * max(0, (1 - self.abs_NE / Constants.score_param))) self.score_FE = 0 self.tot_score = self.score_NE self.FE_selected = 0 self.cum_score_y = self.score_NE else: self.forecast_2lag = self.in_previous_rounds()[-2].forecast self.nowcast_lag = self.in_previous_rounds()[-1].nowcast self.abs_NE = abs(self.y - self.in_previous_rounds()[-1].nowcast) self.score_NE = round(100 * max(0, (1 - self.abs_NE / Constants.score_param))) self.abs_FE = abs(self.y - self.in_previous_rounds()[-2].forecast) self.score_FE = round(100 * max(0, (1 - self.abs_FE / Constants.score_param))) if random.random() < 0.5: self.tot_score = self.score_NE self.FE_selected = 0 else: self.tot_score = self.score_FE self.FE_selected = 1 self.cum_score_y = self.tot_score + self.in_previous_rounds()[-1].cum_score_y def set_fin_payoff(self): cum_score_ne = self.score_NE cum_score_fe = self.score_FE for r in self.in_previous_rounds(): cum_score_ne += r.score_NE cum_score_fe += r.score_FE if cum_score_ne > -1 and cum_score_fe > -1: self.payoff = self.cum_score_y else: self.payoff = 0 # below are for the end-of-experiment questionnaire # q_age = models.PositiveIntegerField(verbose_name='What is your age?', # choices=range(18, 100), # initial=None) # q_gender = models.StringField(initial=None, # choices=['Male', 'Female'], # verbose_name='What is your gender?', # widget=widgets.RadioSelect()) # q_study = models.StringField( # verbose_name='What is the highest level of educational degree that you hold?', # choices=['Graduate school (e.g. Masters, Ph.D., Post-doctoral degrees)','Bachelors','College','High school','Below high school','Other'], widget=widgets.RadioSelect()) q_experience = models.StringField(initial=None, choices=['Yes', 'No'], verbose_name='Have you taken statistics classes?', widget=widgets.RadioSelect()) question1 = models.StringField( choices=['Red process', 'Light blue process', 'Purple process', 'Light blue and purple processes', 'Light blue and red processes', 'Purple and red processes', 'All three processes'], widget=widgets.RadioSelect(), verbose_name='Which of the following best applies to you: when I made my decision, I mainly considered recent observations of the') q_change = models.StringField( choices=['Red process', 'Light blue process', 'Purple process', 'Light blue and purple processes', 'Light blue and red processes', 'Purple and red processes', 'The way I made predictions remained constant over time'], widget=widgets.RadioSelect(), verbose_name='Which of the following best applies to you: as the rounds passed by, I felt myself attaching more weight to recent observations of the' ) q_conf = models.StringField( choices=['Not confident at all', 'Not very confident', 'Somewhat condfident', 'Quite confident', 'Very condfident'], widget=widgets.RadioSelect(), verbose_name='During the experiemnt, how confident were you that you were submitting good precitions given the information that was provided to you?') comment = models.StringField(blank=True, verbose_name='If you want to leave us a comment, please do so here.')