from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants from utils import composer_fc #Throws error in IDE but works ;) import math class Forecasting(Page): def vars_for_template(self): self.player.treatment = self.participant.vars['treatment'] product_order = self.participant.vars['product_order'] product_number = product_order[self.round_number-1] self.player.product_id = product_number print("Current product number " + str(product_number)) demand_table, algorithm_advice, actual_demand, demand_data, mu, sigma, min_level, max_level, reg_a, reg_b, reg_p = composer_fc.get_demand_table(product_number) nn_table = composer_fc.build_nn_table(demand_data) self.player.mu = mu self.player.sigma = sigma self.player.algorithm_advice = algorithm_advice self.player.actual_demand = actual_demand series = [] series.append({ 'name': ' ', 'data': demand_data }) sign = "" if reg_b>0: sign = "+" return{ 'round_number' : self.round_number, 'treatment' : self.player.treatment, 'demand_table' : demand_table, 'nn_table' : nn_table, 'initial_judgement' : self.participant.vars['initial_judgement_' + str(product_order[self.round_number-1])], 'algorithm_advice' : algorithm_advice, 'reg_a' : reg_a, 'reg_b' : reg_b, 'sign' : sign, 'reg_p' : int(round(reg_p*100, 0)), 'highcharts_series' : series, 'min_level' : min_level, 'max_level' : max_level, 'demand_p1' : demand_data[0], 'demand_p2' : demand_data[1], 'demand_p3' : demand_data[2], 'demand_p4' : demand_data[3], 'demand_p5' : demand_data[4], 'demand_p6' : demand_data[5], 'demand_p7' : demand_data[6], 'demand_p8' : demand_data[7], 'demand_p9' : demand_data[8], 'demand_p10' : demand_data[9] } form_model = 'player' form_fields = ['second_judgement'] def before_next_page(self): #Save answers and KPIs for later on use in the experiment product_order = self.participant.vars['product_order'] self.player.initial_judgement = int(self.participant.vars['initial_judgement_' + str(product_order[self.round_number-1])]) self.participant.vars['second_judgement_' + str(product_order[self.round_number-1])] = self.player.second_judgement self.participant.vars['actual_demand_' + str(product_order[self.round_number-1])] = self.player.actual_demand #Weight on Advice (Winsorized) weight_on_advice = 0 weight_on_advice_winsor = 0 if self.player.initial_judgement != self.player.algorithm_advice: weight_on_advice = (self.player.initial_judgement - self.player.second_judgement) / (self.player.initial_judgement - self.player.algorithm_advice) weight_on_advice_winsor = min(max(0, weight_on_advice), 1) self.player.weight_on_advice = weight_on_advice self.player.weight_on_advice_winsor = weight_on_advice_winsor self.participant.vars['woa_' + str(product_order[self.round_number-1])] = weight_on_advice self.participant.vars['woa_winsor_' + str(product_order[self.round_number-1])] = weight_on_advice_winsor #Last round: compute total WoA if self.round_number == self.participant.vars['number_products']: total_woa = 0 total_woa_winsor = 0 for r in range(1,self.participant.vars['number_products']+1): total_woa += float(self.participant.vars['woa_' + str(r)]) total_woa_winsor += float(self.participant.vars['woa_winsor_' + str(r)]) total_woa = total_woa/self.participant.vars['number_products'] total_woa_winsor = total_woa_winsor/self.participant.vars['number_products'] self.player.total_weight_on_advice = total_woa self.player.total_weight_on_advice_winsor = total_woa_winsor #Forecast Error (APE) forecast_error_raw = abs(self.player.second_judgement-self.player.actual_demand)/self.player.actual_demand self.participant.vars['forecast_error_raw_' + str(product_order[self.round_number-1])] = forecast_error_raw self.player.forecast_error = min(max(forecast_error_raw, 0),1) self.participant.vars['forecast_error_' + str(product_order[self.round_number-1])] = self.player.forecast_error #Last round: compute total ForecastError (APE) if self.round_number == self.participant.vars['number_products']: total_fca = 0 for r in range(1,self.participant.vars['number_products']+1): total_fca += float(self.participant.vars['forecast_error_raw_' + str(r)]) total_fca = total_fca/self.participant.vars['number_products'] self.player.total_forecast_error = total_fca #Forecast Error (MSE) self.participant.vars['forecast_error_mse_' + str(product_order[self.round_number-1])] = (self.player.actual_demand-self.player.second_judgement)*(self.player.actual_demand-self.player.second_judgement) #Last round: compute total ForecastError (MSE) if self.round_number == self.participant.vars['number_products']: total_fca_mse = 0 for r in range(1,self.participant.vars['number_products']+1): total_fca_mse += float(self.participant.vars['forecast_error_mse_' + str(r)]) total_fca_mse = total_fca_mse/self.participant.vars['number_products'] self.player.total_forecast_error_mse = total_fca_mse #Payoff self.player.payoff = self.session.config['max_payoff_per_product'] * (1-self.player.forecast_error) self.participant.vars['payoff_' + str(product_order[self.round_number-1])] = self.player.payoff page_sequence = [Forecasting]