import itertools from otree.api import * from scipy.stats import qmc doc = """ Some really accurate description """ class C(BaseConstants): NAME_IN_URL = 'survey_experiment' GAMBLE_CHART = "experiment/chartKPI.html" STAKE = 1000 MAX_RET = 0.25 MAX_RISK = 0.5 NUM_ROUNDS = 10 PLAYERS_PER_GROUP = None class Subsession(BaseSubsession): pass class Group(BaseGroup): pass class Player(BasePlayer): allocation = models.IntegerField(choices=list(range(21))) ret_perc = models.FloatField() risk_perc = models.FloatField() def get_sample(size, lower, upper): sample = qmc.LatinHypercube(d=len(lower)).random(n=size) sample = qmc.scale(sample, lower, upper) return sample.round(decimals=3) def creating_session(subsession: Subsession): if subsession.round_number == 1: groups = itertools.cycle([False, True]) for p in subsession.get_players(): part = p.participant part.group = next(groups) part.sample = get_sample(10, [0, 0], [0.25, 0.5]) def get_vars(ret_b, risk_b, asset_name, round_num, temp=True): exp_a = C.STAKE*C.MAX_RET exp_b = C.STAKE*ret_b max_a = (C.MAX_RET*C.STAKE + C.MAX_RISK*C.STAKE*0.5) / 0.5 min_a = -C.MAX_RISK*C.STAKE max_b = (ret_b*C.STAKE + risk_b*C.STAKE*0.5) / 0.5 min_b = -risk_b*C.STAKE if temp: vars_temp = dict ( ret_b = ret_b, risk_b = risk_b, exp_a = round(exp_a, 2), exp_b = round(exp_b, 2), max_a = round(max_a, 2), min_a = round(min_a, 2), max_b = round(max_b, 2), min_b = round(min_b, 2), name = asset_name, current_round = round_num, total_rounds = int(C.NUM_ROUNDS) ) return vars_temp if not temp: vars_js = dict( max_a = max_a, min_a = min_a, max_b = max_b, min_b = min_b, ) return vars_js return None # PAGES class Explainer(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1 and not player.participant.group: return True else: return False class ExplainerSus(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1 and player.participant.group: return True else: return False class TestAlloc(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1 and not player.participant.group: return True else: return False @staticmethod def vars_for_template(player: Player): ret_b = 0.1 risk_b = 0.1 return get_vars(ret_b, risk_b, "Asset B", 0, True) @staticmethod def js_vars(player: Player): ret_b = 0.1 risk_b = 0.1 return get_vars(ret_b, risk_b, "", 0, False) form_model = 'player' form_fields = ['allocation'] class TestAllocSus(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 1 and player.participant.group: return True else: return False @staticmethod def vars_for_template(player: Player): ret_b = 0.1 risk_b = 0.1 return get_vars(ret_b, risk_b, "Asset S", 0, True) @staticmethod def js_vars(player: Player): ret_b = 0.1 risk_b = 0.1 return get_vars(ret_b, risk_b, "", 0, False) form_model = 'player' form_fields = ['allocation'] class AllocateAssets(Page): @staticmethod def is_displayed(player: Player): if not player.participant.group: return True else: return False @staticmethod def vars_for_template(player: Player): ret_b = player.participant.sample[player.round_number-1][0] risk_b = player.participant.sample[player.round_number-1][1] player.ret_perc = ret_b player.risk_perc = risk_b return get_vars(ret_b, risk_b, "Asset B", player.round_number, True) @staticmethod def js_vars(player: Player): ret_b = player.participant.sample[player.round_number-1][0] risk_b = player.participant.sample[player.round_number-1][1] return get_vars(ret_b, risk_b, "", 0, False) form_model = 'player' form_fields = ['allocation'] class AllocateAssetsSus(Page): @staticmethod def is_displayed(player: Player): if player.participant.group: return True else: return False @staticmethod def vars_for_template(player: Player): ret_b = player.participant.sample[player.round_number-1][0] risk_b = player.participant.sample[player.round_number-1][1] player.ret_perc = ret_b player.risk_perc = risk_b return get_vars(ret_b, risk_b, "Asset S", player.round_number, True) @staticmethod def js_vars(player: Player): ret_b = player.participant.sample[player.round_number-1][0] risk_b = player.participant.sample[player.round_number-1][1] return get_vars(ret_b, risk_b, "", 0, False) form_model = 'player' form_fields = ['allocation'] class Results(Page): @staticmethod def is_displayed(player: Player): if player.round_number == 10: return True else: return False page_sequence = [Explainer, TestAlloc, AllocateAssets, ExplainerSus, TestAllocSus, AllocateAssetsSus, Results]