from otree.api import ( models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer, Currency as c, currency_range, ) import math import random author = 'Nishtha' doc = """ Studying saving behavior during the retirement phase """ class Constants(BaseConstants): name_in_url = 'Retirement_Savings_T2_Task2' players_per_group = None num_rounds = 40 savings_start = 145350 sequence_length = 10 min_age = 62 ssb_benefits_period9 = 144014 min_consumption = 14887 annual_benefit = 14887 interest_rate = 1.027 task_length = 40 task = 2 RandomList = random.sample(range(1, 100), 40) cutofflist = [96, 96, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 91, 91, 90, 89, 88, 87, 86, 85, 83, 82, 80, 79, 77, 75, 73, 71, 70, 68, 67, 0] difflist = [x1 - x2 for (x1, x2) in zip(cutofflist, RandomList)] class Subsession(BaseSubsession): paying_round = models.IntegerField() paying_task = models.IntegerField() cutoff = models.IntegerField() draw = models.IntegerField() def payingTask(self): A = self.in_round(1) self.cutoff = Constants.cutofflist[self.round_number - 1] self.draw = Constants.RandomList[self.round_number - 1] if self.round_number == 1: self.paying_round = next(i for i, v in enumerate(Constants.difflist) if v < 0) + 1 print(self.paying_round) else: self.paying_round = A.paying_round class Group(BaseGroup): pass class Player(BasePlayer): last_round = models.IntegerField() last_balance = models.FloatField() starting_balance = models.FloatField() ending_balance = models.FloatField() consumption = models.FloatField(min = Constants.min_consumption) ssb_choice = models.BooleanField(label="Do you want to claim benefits this period?", widget=widgets.RadioSelect) is_claimed = models.BooleanField() ssb_benefits_low_balance = models.FloatField() ssb_chosen = models.FloatField() is_balance_low = models.BooleanField() default_consumption = models.FloatField() max_consumption = models.FloatField() ssb = models.FloatField() intermediate_balance = models.FloatField() period_payoff = models.FloatField() cumulative_payoff = models.FloatField() task2_payoff = models.FloatField() def set_claim(self): if self.round_number>1: A = self.in_round(self.round_number-1) else: A = self.in_round(self.round_number) if self.round_number==1: self.is_claimed=0 elif self.round_number==2: self.is_claimed=A.ssb_choice elif A.is_claimed==1: self.is_claimed=1 else: self.is_claimed=A.ssb_choice def set_ssb_benefits(self): if self.round_number == 2: self.ssb_benefits_low_balance = 15447+Constants.annual_benefit elif self.round_number == 3: self.ssb_benefits_low_balance = 31506+Constants.annual_benefit elif self.round_number == 4: self.ssb_benefits_low_balance = 48219+Constants.annual_benefit elif self.round_number == 5: self.ssb_benefits_low_balance = 65637+Constants.annual_benefit elif self.round_number == 6: self.ssb_benefits_low_balance = 83838+Constants.annual_benefit elif self.round_number == 7: self.ssb_benefits_low_balance = 102893+Constants.annual_benefit elif self.round_number == 8: self.ssb_benefits_low_balance = 122915+Constants.annual_benefit else: self.ssb_benefits_low_balance = 144014+Constants.annual_benefit A1 = self.in_round(1) A2 = self.in_round(2) A3 = self.in_round(3) A4 = self.in_round(4) A5 = self.in_round(5) A6 = self.in_round(6) A7 = self.in_round(7) A8 = self.in_round(8) A9 = self.in_round(9) if A1.ssb_choice==1: self.ssb_chosen=14887 elif A2.ssb_choice==1: self.ssb_chosen = 15447+Constants.annual_benefit elif A3.ssb_choice==1: self.ssb_chosen = 31506+Constants.annual_benefit elif A4.ssb_choice==1: self.ssb_chosen = 48219+Constants.annual_benefit elif A5.ssb_choice==1: self.ssb_chosen = 65637+Constants.annual_benefit elif A6.ssb_choice==1: self.ssb_chosen = 83838+Constants.annual_benefit elif A7.ssb_choice==1: self.ssb_chosen = 102893+Constants.annual_benefit elif A8.ssb_choice==1: self.ssb_chosen = 122915+Constants.annual_benefit else: self.ssb_chosen = 144014+Constants.annual_benefit def set_ssb(self): if self.round_number == 1: if self.ssb_choice == 1: self.ssb = 14887 else: self.ssb = 0 else: if self.is_claimed or self.in_round(self.round_number - 1).ssb > 0: self.ssb = Constants.annual_benefit elif self.ssb_choice == 1 and self.round_number == 2: self.ssb = 15447+Constants.annual_benefit elif self.ssb_choice == 1 and self.round_number == 3: self.ssb = 31506+Constants.annual_benefit elif self.ssb_choice == 1 and self.round_number == 4: self.ssb = 48219+Constants.annual_benefit elif self.ssb_choice == 1 and self.round_number == 5: self.ssb = 65637+Constants.annual_benefit elif self.ssb_choice == 1 and self.round_number == 6: self.ssb = 83838+Constants.annual_benefit elif self.ssb_choice == 1 and self.round_number == 7: self.ssb = 102893+Constants.annual_benefit elif self.ssb_choice == 1 and self.round_number == 8: self.ssb = 122915+Constants.annual_benefit elif self.is_balance_low: self.ssb = self.ssb_benefits_low_balance elif self.round_number == 9: self.ssb = Constants.ssb_benefits_period9+Constants.annual_benefit else: self.ssb = 0 def set_balances(self): if self.round_number > 1: A = self.in_round(self.round_number - 1) else: A = self.in_round(self.round_number) # Defining starting_balance if self.round_number == 1: self.starting_balance = Constants.savings_start else: self.starting_balance = A.ending_balance * Constants.interest_rate self.starting_balance = round(self.starting_balance, 2) if self.round_number == 1: self.last_balance = 0 else: self.last_balance = self.in_round(self.round_number - 1).ending_balance # If balance is low if self.starting_balance < 14887: self.is_balance_low = 1 else: self.is_balance_low = 0 def set_intermediate_balance(self): if self.round_number > 1: A = self.in_round(self.round_number - 1) else: A = self.in_round(self.round_number) # Defining default consumption if self.round_number == 1: self.default_consumption = Constants.min_consumption elif A.consumption < self.starting_balance + self.ssb: self.default_consumption = A.consumption else: self.default_consumption = self.starting_balance + self.ssb self.intermediate_balance = self.starting_balance + self.ssb def set_end_balance(self): self.ending_balance = self.starting_balance + self.ssb - self.consumption self.ending_balance = round(self.ending_balance, 2) # Defining payoff def set_payoffs(self): self.period_payoff = (1 - math.exp(-(self.consumption - 14887) / 20000)) * 3 self.period_payoff = round(self.period_payoff, 2) if self.round_number == 1: self.cumulative_payoff = self.period_payoff else: l = self.in_round(self.round_number - 1) self.cumulative_payoff = l.cumulative_payoff + self.period_payoff self.cumulative_payoff = round(self.cumulative_payoff, 2) self.payoff = 0 x = self.in_round(self.subsession.paying_round) self.task2_payoff = x.cumulative_payoff if Constants.task == self.subsession.paying_task: x.payoff = x.cumulative_payoff else: x.payoff = 0 @property def payoff(self): return self._payoff @payoff.setter def payoff(self, value): if value is None: value = 0 delta = value - self._payoff self._payoff += delta self.participant.payoff += delta # should save it because it may not be obvious that modifying # player.payoff also changes a field on a different model self.participant.save() if delta == 0: return print( f'Setting payoff to: {value}. player:\t{self._payoff}, participant:\t{self.participant.payoff}, participant.code:{self.participant.code} ({Constants.name_in_url}, round {self.round_number})')