from otree.api import Currency as c, currency_range import csv import pandas as pd import numpy as np import pickle import json import random from ._builtin import Page, WaitPage from .models import Constants class PortInstructions(Page): def vars_for_template(self): conf=pickle.load(open("three_asset_ests2.p","rb")) ret_s_mean=[1.235, 1.5257, 1.8833, 2.3294, 2.8814] ret_s_bottom=[0.5247, 0.416, 0.3531, 0.3104, 0.279] ret_s_top=[2.1496, 3.0564, 4.0583, 5.2066, 6.5235] ret_b_mean=[1.0832,1.1735,1.2712,1.377,1.4917] ret_b_bottom=[.5988,.4846,.4115,.3586,.3179] ret_b_top=[1.6694,2.0646,2.4289,2.7884,3.1458] rf=[1.03, 1.0609, 1.092727, 1.12550881, 1.159274] rets={ "ret_s":{ "mean":ret_s_mean, "bottom":ret_s_bottom, "top":ret_s_top, }, "ret_b":{ "mean":ret_b_mean, "bottom":ret_b_bottom, "top":ret_b_top, }, "rf":rf, } return { "conf":json.dumps(conf), "round":0, "value":100, "prev_values":[100], "rets":rets } form_model="player" def is_displayed(self): return self.round_number==1 class Port_first(Page): def vars_for_template(self): conf=pickle.load(open("three_asset_ests2.p","rb")) ret_s_mean=[1.235, 1.5257, 1.8833, 2.3294, 2.8814] ret_s_bottom=[0.5247, 0.416, 0.3531, 0.3104, 0.279] ret_s_top=[2.1496, 3.0564, 4.0583, 5.2066, 6.5235] ret_b_mean=[1.0832,1.1735,1.2712,1.377,1.4917] ret_b_bottom=[.5988,.4846,.4115,.3586,.3179] ret_b_top=[1.6694,2.0646,2.4289,2.7884,3.1458] rf=[1.03, 1.0609, 1.092727, 1.12550881, 1.159274] rets={ "ret_s":{ "mean":ret_s_mean, "bottom":ret_s_bottom, "top":ret_s_top, }, "ret_b":{ "mean":ret_b_mean, "bottom":ret_b_bottom, "top":ret_b_top, }, "rf":rf, } ret_rf=1.03 round_5=(self.round_number) % 5 or 5 if self.round_number<6: starter=0 elif self.round_number<11: starter=5 else: starter=10 # print(gamma,eta) prev_values=[100] if self.round_number in [1,6,11]: A=self.player.port_value else: prev_values.extend([x.port_value for x in self.player.in_previous_rounds()[starter:]]) A=self.player.in_previous_rounds()[-1].port_value return { "rets":rets, "value":A, "round": round_5, "prev_values":prev_values, "conf":json.dumps(conf), } form_model='player' form_fields=['port_1_first', 'port_2_first', 'port_3_first', 'first_mean', 'first_bot', 'first_top', 'first_mean_final', 'first_bot_final', 'first_top_final', ] def error_message(self, values): # print('values is', values) if values["port_1_first"] + values["port_2_first"] + values["port_3_first"] != 100: return 'The numbers must add up to 100' def before_next_page(self): if self.participant.vars["advisor_type"][self.round_number-1]==0: self.player.port_1=self.player.port_1_first self.player.port_2=self.player.port_2_first self.player.port_3=self.player.port_3_first class Port(Page): def vars_for_template(self): if self.round_number==1: ad_type=random.sample([0,1,1,2,2],5) ad_type.extend(random.sample([0,1,1,2,2],5)) ad_type.extend(random.sample([0,1,1,2,2],5)) self.participant.vars["advisor_type"]=ad_type # sp=pd.read_csv("../FundData/SP500.csv") # sp['ret_s']=sp['Adj Close']/sp['Adj Close'].shift(1) # # bd=pd.read_csv("../FundData/ICE US Investment Grade.csv") # bd.columns=['Date','BondPrice'] # bd['ret_b']=bd['BondPrice']/bd['BondPrice'].shift(1) ret_s_mean=[1.235, 1.5257, 1.8833, 2.3294, 2.8814] ret_s_bottom=[0.5247, 0.416, 0.3531, 0.3104, 0.279] ret_s_top=[2.1496, 3.0564, 4.0583, 5.2066, 6.5235] ret_b_mean=[1.0832,1.1735,1.2712,1.377,1.4917] ret_b_bottom=[.5988,.4846,.4115,.3586,.3179] ret_b_top=[1.6694,2.0646,2.4289,2.7884,3.1458] rf=[1.03, 1.0609, 1.092727, 1.12550881, 1.159274] rets={ "ret_s":{ "mean":ret_s_mean, "bottom":ret_s_bottom, "top":ret_s_top, }, "ret_b":{ "mean":ret_b_mean, "bottom":ret_b_bottom, "top":ret_b_top, }, "rf":rf, } ret_rf=1.03 gamma=self.participant.vars['gamma'] eta=self.participant.vars['eta'] # # gamma=-.9426 # eta=13 self.player.gamma=gamma self.player.eta=eta # print(gamma,eta, "176") # gamma=-1 # eta=12 round_5=(self.round_number) % 5 or 5 if self.round_number<6: starter=0 elif self.round_number<11: starter=5 else: starter=10 # print(gamma,eta) prev_values=[100] if self.round_number in [1,6,11]: A=self.player.port_value/100 else: prev_values.extend([x.port_value for x in self.player.in_previous_rounds()[starter:]]) A=self.player.in_previous_rounds()[-1].port_value/100 percs=(0,0) s_rets=np.exp(np.random.normal(.06*(6-round_5),np.sqrt(.55*(6-round_5)),size=10000)) b_rets=np.exp(np.random.normal(0,np.sqrt((6-round_5)*.4**2),size=10000)) rf_rets=[1.03]*len(s_rets) df=pd.DataFrame({"rf":rf_rets,"stock":s_rets,"bond":b_rets}) df_np=df.to_numpy() best_port = None starting_w=[ (1,0,0), (0,1,0), (0,0,1), (.5,.5,0), (.5,0,.5), (0,.5,.5), ] for k in starting_w: w=k x=np.apply_along_axis(self.player.util,1,df_np,w,A,gamma,eta) eU=np.mean(x) if k[0]==1: best_port = w + (eU,) elif eU > best_port[3]: best_port = w + (eU,) elif eU < best_port[3]: break tested=[] count=0 while True: w1=(best_port[0]+.05,best_port[1]-.05, best_port[2]) w2=(best_port[0]+.05,best_port[1], best_port[2]-.05) w3=(best_port[0]-.05,best_port[1]+.05, best_port[2]) w4=(best_port[0],best_port[1]+.05, best_port[2]-.05) w5=(best_port[0]-.05,best_port[1], best_port[2]+.05) w6=(best_port[0],best_port[1]-.05, best_port[2]+.05) test_w=[w1,w2,w3,w4,w5,w6] BP=best_port[3] for i in test_w: if sum(n<0 for n in i)==0 and i not in tested: x=np.apply_along_axis(self.player.util,1,df_np,i,A,gamma,eta) eU=np.mean(x) if eU>best_port[3]: best_port = i+(eU,) tested.extend(test_w) if BP==best_port[3]: break count+=1 if count>12: break best_port=(round(best_port[0],2),round(best_port[1],2),round(best_port[2],2),) # print(best_port) # print(eU) conf1=pickle.load(open("three_asset_ests2.p","rb")) # print(self.round_number,round_5,conf[int(best_port[1]*20)]) conf=conf1[int(best_port[0]*20)][1][int(best_port[1]*20)] # print(conf) # print(best_port) best_conf={ "mean":round(conf[1][5-round_5]*A*100,2), "bot10":round(conf[2][5-round_5]*A*100,2), "top10":round(conf[3][5-round_5]*A*100,2), } self.player.best_mean_final = best_conf['mean'] self.player.best_bot_final = best_conf['bot10'] self.player.best_top_final = best_conf['top10'] self.player.port_1_best = best_port[0]*100 self.player.port_2_best = best_port[1]*100 self.player.port_3_best = best_port[2]*100 return { "rets":rets, "value":round(A*100,2), "round": round_5, "prev_values":prev_values, "best_conf":best_conf, "conf":json.dumps(conf1), "best_port":(round(best_port[0]*100,0),round(best_port[1]*100,0),round(best_port[2]*100,0)), "ad_type":self.participant.vars["advisor_type"][self.round_number-1] } form_model='player' form_fields=['port_1', 'port_2', 'port_3', 'port_mean', 'port_bot', 'port_top', 'port_mean_final', 'port_bot_final', 'port_top_final',] # 'port_4', # 'port_5',] def error_message(self, values): # print('values is', values) if values["port_1"] + values["port_2"] + values["port_3"] != 100: return 'The numbers must add up to 100' # def is_displayed(self): # return self.round_number>=15 def before_next_page(self): self.player.advisor_type = self.participant.vars["advisor_type"][self.round_number-1] self.player.port_return() class PortPerformance(Page): def vars_for_template(self): values1=None values2=None values3=None if self.round_number>=5: values1=self.player.in_all_rounds()[0:5] if self.round_number>=10: values2=self.player.in_all_rounds()[5:10] if self.round_number>=15: values3=self.player.in_all_rounds()[10:15] payoffs=self.participant.vars['payoffs'] payoffs.extend([values2[-1].port_value,values3[-1].port_value]) self.participant.vars['payoffs']=payoffs return { "values":{ "first":values1, "second":values2, "third":values3 }, } def is_displayed(self): x = self.round_number in [5,10,15] return x page_sequence = [ PortInstructions, Port_first, Port, PortPerformance ]