Пример #1
0
    def penalty_cost(self, m):
        """Calculate and return the penalty cost of GHG levels below 280. The penalties in previous nodes
		in the path leading to the current node is summed and added to current period's penalty, given by

			max(0, min((280-GHG level)/GHG level, max_penalty)

		The method returns a `BigStorageTree` object with penalties for every period where utilities are calculated. 

		Parameters
		----------
		m : ndarray or list
			array of mitigation
		
		Returns
		-------
		`BigStorageTree`
			penalties in every period where utilities are calculated

		"""
        penalty_cost = BigStorageTree(self.period_len, self.decision_times)
        if not self.add_penalty_cost:
            return penalty_cost

        ghg_levels = self.damage.ghg_level(m, periods=self.tree.num_periods)
        interval_length = self.decision_times[1:] - self.decision_times[:-1]

        sum_size = 1
        prev_ghg_level = ghg_levels[0]

        for i in range(1, len(self.tree.decision_times)):
            time_period = self.tree.decision_times[i]
            prev_time_period = self.tree.decision_times[i - 1]
            prev_penalty_cost = penalty_cost[prev_time_period]
            len_arr = len(penalty_cost[time_period])

            ghg_level = ghg_levels[sum_size:sum_size + len_arr]
            increment = self.period_len
            total_increment = time_period - prev_time_period
            if prev_ghg_level.shape != ghg_level.shape:
                prev_ghg_level = np.repeat(prev_ghg_level, 2)
                prev_penalty_cost = np.repeat(prev_penalty_cost, 2)

            while prev_time_period < time_period:
                prev_time_period += self.period_len
                this_period_ghg = prev_ghg_level + (
                    increment / total_increment) * (ghg_level - prev_ghg_level)
                this_period_ghg[
                    this_period_ghg ==
                    0] = 1.0  # doesn't really matter if we put 1.0 or a value closer to 0
                penalty_cost.set_value(
                    prev_time_period, prev_penalty_cost +
                    self._interval_penalty(this_period_ghg) / self.period_len)

                prev_penalty_cost = penalty_cost[prev_time_period]
                increment += self.period_len

            prev_ghg_level = ghg_level
            sum_size += len_arr

        return penalty_cost
Пример #2
0
    def marginal_utility(self, m, utility_tree, cons_tree, cost_tree, ce_tree):
        """Calculating marginal utility for sensitivity analysis, e.g. in the SSC decomposition.

		Parameters
		----------
		m : ndarray
			array of mitigations
		utility_tree : `BigStorageTree` object 
			utility values from using mitigation `m`
		cons_tree : `BigStorageTree` object
			consumption values from using mitigation `m`
		cost_tree : `SmallStorageTree` object
			cost values from using mitigation `m`
		ce_tree : `BigStorageTree` object
			certain equivalence values from using mitigation `m`

		Returns
		-------
		tuple
			marginal utility tree

		Examples
		--------
		Assuming we have declared a EZUtility object as 'ezu' and have a mitigation array 'm'.
		>>> 
		>>> utility_tree, cons_tree, cost_tree, ce_tree = ezu.utility(m, return_trees=True)
		>>> mu_0_tree, mu_1_tree, mu_2_tree = ezu.marginal_utility(m, utility_tree, cons_tree, cost_tree, ce_tree)
		>>> mu_0_tree[0] # value at period 0
		array([ 0.33001256])
		>>> mu_1_tree[0] # value at period 0
		array([ 0.15691619])
		>>> mu_2_tree[0] # value at period 0
		array([ 0.13948175])

		"""
        #could add ce_tree to parameter list.
        mu_tree_0 = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        mu_tree_1 = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        mu_tree_2 = SmallStorageTree(decision_times=self.decision_times)

        self._end_period_marginal_utility(mu_tree_0, mu_tree_1, ce_tree,
                                          utility_tree, cons_tree)
        periods = utility_tree.periods[::-1]

        for period in periods[2:]:
            mu_0, mu_1, mu_2 = self._period_marginal_utility(
                mu_tree_0.get_next_period_array(period),
                mu_tree_1.get_next_period_array(period), m, period,
                utility_tree, cons_tree, ce_tree)
            mu_tree_0.set_value(period, mu_0)
            mu_tree_1.set_value(period, mu_1)
            if mu_2 is not None:
                mu_tree_2.set_value(period, mu_2)

        return mu_tree_0, mu_tree_1, mu_tree_2
Пример #3
0
    def utility(self, m, return_trees=False):
        """Calculating utility for the specific mitigation decisions 'm'.

		Args:
			m (ndarray): Array of mitigations.
			return_trees (bool): True if method should return trees calculculated in producing the utility.

		Returns:
			tuple of ndarrays if return_trees else float of period 0's utility.

		"""
        # can we make this smarter and not create these every time we call the utility?
        utility_tree = BigStorageTree(subinterval_len=self.period_len,
                                      decision_times=self.decision_times)
        cons_tree = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        ce_tree = BigStorageTree(subinterval_len=self.period_len,
                                 decision_times=self.decision_times)
        cost_tree = SmallStorageTree(decision_times=self.decision_times)

        self._end_period_utility(m, utility_tree, cons_tree, cost_tree)
        it = self._utility_generator(m, utility_tree, cons_tree, cost_tree,
                                     ce_tree)
        for u, period in it:
            utility_tree.set_value(period, u)

        if return_trees:
            return utility_tree, cons_tree, cost_tree, ce_tree
        return utility_tree[0]
Пример #4
0
def numerical_scc(m, utility, delta_m):
    utility_t, cons_t, cost_t, ce_t = utility.utility(m, return_trees=True)
    m_copy = m.copy()
    m_copy[0] += delta_m
    delta_utility_t, delta_cons_t, delta_cost_t, delta_ce_t = utility.utility(
        m_copy, return_trees=True)
    delta_utility = (delta_utility_t[0] - utility_t[0])
    node_eps = BigStorageTree(5.0, [0, 15, 45, 85, 185, 285, 385])
    scc = 0
    for period in cons_t.decision_times[1:]:
        cons_t.tree[period] = (delta_cons_t[period] - cons_t[period])
        for node in range(len(cons_t[period])):
            node_eps.tree[period][node] = delta_m
            adj_utiity = utility.adjusted_utility(m, node_cons_eps=node_eps)
            node_eps.tree[period][node] = 0.0
            cons_t.tree[period][node] = (cons_t[period][node] / (delta_m)) * (
                (adj_utiity - utility_t[0]) / cons_t[period][node])
            cons_t.tree[period][node] = np.nan_to_num(cons_t[period][node])
        scc += cons_t.tree[period].sum()
    scc = scc * (
        (delta_cons_t[0] - cons_t[0]) / delta_utility) * delta_m * m[0]
    return scc
Пример #5
0
    def marginal_utility(self, m, utility_tree, cons_tree, cost_tree, ce_tree):
        """Calculating marginal utility for sensitivity analysis, e.g. in the SSC decomposition.

		Args:
			m (ndarray): 1D-array of mitigations.
			period_cons_eps (optionla, ndarray): Array of increases in consumption per period. #77
			node_cons_eps (optional, ndarray): Array of increases in consumption per node. #(big_storage)
			final_cons_eps (optional, float): Number to increase the final utility.
			first_period_consadj (optional, float): Adjustment of consumption at time 0.
			return_trees (bool): True if method should return trees calculculated in producing the utility.

		Returns:
			tuple of ndarrays if return_trees else float of period 0's utility.

		"""
        #could add ce_tree to parameter list.
        mu_tree_0 = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        mu_tree_1 = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        mu_tree_2 = SmallStorageTree(decision_times=self.decision_times)
        #ce_tree = BigStorageTree(subinterval_len=self.period_len, decision_times=self.decision_times)
        self._end_period_marginal_utility(mu_tree_0, mu_tree_1, ce_tree,
                                          utility_tree, cons_tree)
        periods = utility_tree.periods[::-1]

        for period in periods[2:]:
            mu_0, mu_1, mu_2 = self._period_marginal_utility(
                mu_tree_0.get_next_period_array(period),
                mu_tree_1.get_next_period_array(period), m, period,
                utility_tree, cons_tree, ce_tree)
            mu_tree_0.set_value(period, mu_0)
            mu_tree_1.set_value(period, mu_1)
            if mu_2 is not None:
                mu_tree_2.set_value(period, mu_2)

        return mu_tree_0, mu_tree_1, mu_tree_2
Пример #6
0
    def utility(self, m, return_trees=False):
        """Calculating utility for the specific mitigation decisions `m`.

		Parameters
		----------
		m : ndarray or list
			array of mitigations
		return_trees : bool
			True if methid should return trees calculated in producing the utility

		Returns
		-------
		ndarray or tuple 
			tuple of `BaseStorageTree` if return_trees else ndarray with utility at period 0

		Examples:
		---------
		Assuming we have declared a EZUtility object as 'ezu' and have a mitigation array 'm'
		
		>>> ezu.utility(m)
		array([ 9.83391921])
		>>> utility_tree, cons_tree, cost_tree, ce_tree = ezu.utility(m, return_trees=True)

		"""
        utility_tree = BigStorageTree(subinterval_len=self.period_len,
                                      decision_times=self.decision_times)
        cons_tree = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        ce_tree = BigStorageTree(subinterval_len=self.period_len,
                                 decision_times=self.decision_times)
        cost_tree = SmallStorageTree(decision_times=self.decision_times)
        penalty_cost = self.penalty_cost(m)

        self._end_period_utility(m, utility_tree, cons_tree, cost_tree,
                                 penalty_cost)
        it = self._utility_generator(m, utility_tree, cons_tree, cost_tree,
                                     ce_tree, penalty_cost)
        for u, period in it:
            utility_tree.set_value(period, u)

        if return_trees:
            return utility_tree, cons_tree, cost_tree, ce_tree
        return utility_tree[0]
Пример #7
0
    def adjusted_utility(self,
                         m,
                         period_cons_eps=None,
                         node_cons_eps=None,
                         final_cons_eps=0.0,
                         first_period_consadj=0.0,
                         return_trees=False):
        """Calculating adjusted utility for sensitivity analysis. Used e.g. to find zero-coupon bond price.
		Values in parameters are used to adjusted the utility in different ways.

		Parameters
		----------
		m : ndarray 
			array of mitigations
		period_cons_eps : ndarray, optional
			array of increases in consumption per period
		node_cons_eps : `SmallStorageTree`, optional 
			increases in consumption per node
		final_cons_eps : float, optional
			value to increase the final utilities by
		first_period_consadj : float, optional 
			value to increase consumption at period 0 by
		return_trees : bool, optional 
			True if method should return trees calculculated in producing the utility

		Returns
		-------
		ndarray or tuple 
			tuple of `BaseStorageTree` if return_trees else ndarray with utility at period 0

		Examples
		---------
		Assuming we have declared a EZUtility object as 'ezu' and have a mitigation array 'm'
		
		>>> ezu.adjusted_utility(m, final_cons_eps=0.1)
		array([ 9.83424045])
		>>> utility_tree, cons_tree, cost_tree, ce_tree = ezu.adjusted_utility(m, final_cons_eps=0.1, return_trees=True)
		
		>>> arr = np.zeros(int(ezu.decision_times[-1]/ezu.period_len) + 1)
		>>> arr[-1] = 0.1
		>>> ezu.adjusted_utility(m, period_cons_eps=arr)
		array([ 9.83424045])
		
		>>> bst = BigStorageTree(5.0, [0, 15, 45, 85, 185, 285, 385])
		>>> bst.set_value(bst.last_period, np.repeat(0.01, len(bst.last)))
		>>> ezu.adjusted_utility(m, node_cons_eps=bst)
		array([ 9.83391921])

		The last example differs from the rest in that the last values of the `node_cons_eps` will never be
		used. Hence if you want to update the last period consumption, use one of these two methods. 

		>>> ezu.adjusted_utility(m, first_period_consadj=0.01)
		array([ 9.84518772])

		"""
        utility_tree = BigStorageTree(subinterval_len=self.period_len,
                                      decision_times=self.decision_times)
        cons_tree = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        ce_tree = BigStorageTree(subinterval_len=self.period_len,
                                 decision_times=self.decision_times)
        cost_tree = SmallStorageTree(decision_times=self.decision_times)

        periods = utility_tree.periods[::-1]
        if period_cons_eps is None:
            period_cons_eps = np.zeros(len(periods))
        if node_cons_eps is None:
            node_cons_eps = BigStorageTree(subinterval_len=self.period_len,
                                           decision_times=self.decision_times)

        penalty_cost = self.penalty_cost(m)
        self._end_period_utility(m, utility_tree, cons_tree, cost_tree,
                                 penalty_cost)

        it = self._utility_generator(m, utility_tree, cons_tree, cost_tree,
                                     ce_tree, penalty_cost,
                                     first_period_consadj)
        i = len(utility_tree) - 2
        for u, period in it:
            if period == periods[1]:
                mu_0 = (1.0 - self.b) * (u / cons_tree[period])**(1.0 - self.r)
                next_term = self.b * (1.0 - self.b) / (
                    1.0 - self.b * self.growth_term**self.r)
                mu_1 = (u**(1.0 - self.r)) * next_term * (cons_tree.last
                                                          **(self.r - 1.0))
                u += (final_cons_eps + period_cons_eps[-1] +
                      node_cons_eps.last) * mu_1
                u += (period_cons_eps[i] + node_cons_eps.tree[period]) * mu_0
                utility_tree.set_value(period, u)
            else:
                mu_0, m_1, m_2 = self._period_marginal_utility(
                    mu_0, mu_1, m, period, utility_tree, cons_tree, ce_tree)
                u += (period_cons_eps[i] + node_cons_eps.tree[period]) * mu_0
                utility_tree.set_value(period, u)
            i -= 1

        if return_trees:
            return utility_tree, cons_tree, cost_tree, ce_tree
        return utility_tree.tree[0]
Пример #8
0
def save_sensitivity_analysis(m,
                              utility,
                              utility_tree,
                              cons_tree,
                              cost_tree,
                              ce_tree,
                              prefix=None,
                              return_delta_utility=False):
    """Calculate and save sensitivity analysis based on the optimal mitigation. For every sub-period, i.e. the 
	periods given by the utility calculations, the function calculates and saves:
		
		* discount prices
		* net expected damages
		* expected damages
		* risk premium
		* expected SDF
		* cross SDF & damages
		* discounted expected damages
		* cov term
		* scaled net expected damages
		* scaled risk premiums
	
	into the file  `prefix` + 'sensitivity_output' in the 'data' directory in the current working directory. 

	Furthermore, for every node the function calculates and saves:
	
		* SDF 
		* delta consumption
		* forward marginal utility  
		* up-node marginal utility
		* down-node marginal utility
	
	into the file `prefix` + 'tree' in the 'data' directory in the current working directory. If there is no 'data' 
	directory, one is created. 

	Parameters
	----------
	m : ndarray or list
		array of mitigation
	utility : `Utility` object
		object of utility class
	utility_tree : `BigStorageTree` object
		utility values from optimal mitigation values
	cons_tree : `BigStorageTree` object
		consumption values from optimal mitigation values
	cost_tree : `SmallStorageTree` object
		cost values from optimal mitigation values
	ce_tree : `BigStorageTree` object
		certain equivalence values from optimal mitigation values
	prefix : str, optional
		prefix to be added to file_name

	"""
    from tools import write_columns_csv, append_to_existing

    sdf_tree = BigStorageTree(utility.period_len, utility.decision_times)
    sdf_tree.set_value(0, np.array([1.0]))

    discount_prices = np.zeros(len(sdf_tree))
    net_expected_damages = np.zeros(len(sdf_tree))
    expected_damages = np.zeros(len(sdf_tree))
    risk_premiums = np.zeros(len(sdf_tree))
    expected_sdf = np.zeros(len(sdf_tree))
    cross_sdf_damages = np.zeros(len(sdf_tree))
    discounted_expected_damages = np.zeros(len(sdf_tree))
    net_discount_damages = np.zeros(len(sdf_tree))
    cov_term = np.zeros(len(sdf_tree))

    discount_prices[0] = 1.0
    cost_sum = 0

    end_price = find_term_structure(m, utility, 0.01)
    perp_yield = perpetuity_yield(end_price, sdf_tree.periods[-2])

    delta_cons_tree, delta_cost_array, delta_utility = delta_consumption(
        m, utility, cons_tree, cost_tree, 0.01)
    mu_0, mu_1, mu_2 = utility.marginal_utility(m, utility_tree, cons_tree,
                                                cost_tree, ce_tree)
    sub_len = sdf_tree.subinterval_len
    i = 1
    for period in sdf_tree.periods[1:]:
        node_period = sdf_tree.decision_interval(period)
        period_probs = utility.tree.get_probs_in_period(node_period)
        expected_damage = np.dot(delta_cons_tree[period], period_probs)
        expected_damages[i] = expected_damage

        if sdf_tree.is_information_period(period - sdf_tree.subinterval_len):
            total_probs = period_probs[::2] + period_probs[1::2]
            mu_temp = np.zeros(2 * len(mu_1[period - sub_len]))
            mu_temp[::2] = mu_1[period - sub_len]
            mu_temp[1::2] = mu_2[period - sub_len]
            sdf = (np.repeat(total_probs, 2) / period_probs) * (
                mu_temp / np.repeat(mu_0[period - sub_len], 2))
            period_sdf = np.repeat(sdf_tree.tree[period - sub_len], 2) * sdf
        else:
            sdf = mu_1[period - sub_len] / mu_0[period - sub_len]
            period_sdf = sdf_tree[period - sub_len] * sdf

        expected_sdf[i] = np.dot(period_sdf, period_probs)
        cross_sdf_damages[i] = np.dot(period_sdf,
                                      delta_cons_tree[period] * period_probs)
        cov_term[i] = cross_sdf_damages[i] - expected_sdf[i] * expected_damage

        discount_prices[i] = expected_sdf[i]
        sdf_tree.set_value(period, period_sdf)

        if i < len(delta_cost_array):
            net_discount_damages[i] = -(expected_damage + delta_cost_array[
                i, 1]) * expected_sdf[i] / delta_cons_tree[0]
            cost_sum += -delta_cost_array[
                i, 1] * expected_sdf[i] / delta_cons_tree[0]
        else:
            net_discount_damages[
                i] = -expected_damage * expected_sdf[i] / delta_cons_tree[0]

        risk_premiums[i] = -cov_term[i] / delta_cons_tree[0]
        discounted_expected_damages[
            i] = -expected_damage * expected_sdf[i] / delta_cons_tree[0]
        i += 1

    damage_scale = utility.cost.price(
        0, m[0], 0) / (net_discount_damages.sum() + risk_premiums.sum())
    scaled_discounted_ed = net_discount_damages * damage_scale
    scaled_risk_premiums = risk_premiums * damage_scale

    if prefix is not None:
        prefix += "_"
    else:
        prefix = ""

    write_columns_csv([
        discount_prices, net_discount_damages, expected_damages, risk_premiums,
        expected_sdf, cross_sdf_damages, discounted_expected_damages, cov_term,
        scaled_discounted_ed, scaled_risk_premiums
    ], prefix + "sensitivity_output", [
        "Year", "Discount Prices", "Net Expected Damages", "Expected Damages",
        "Risk Premium", "Expected SDF", "Cross SDF & Damages",
        "Discounted Expected Damages", "Cov Term",
        "Scaled Net Expected Damages", "Scaled Risk Premiums"
    ], [sdf_tree.periods.astype(int) + 2015])

    append_to_existing(
        [[end_price], [perp_yield], [scaled_discounted_ed.sum()],
         [scaled_risk_premiums.sum()], [utility.cost.price(0, m[0], 0)],
         cost_sum],
        prefix + "sensitivity_output",
        header=[
            "Zero Bound Price", "Perp Yield", "Expected Damages",
            "Risk Premium", "SCC", "Sum Delta Cost"
        ],
        start_char='\n')

    store_trees(prefix=prefix,
                SDF=sdf_tree,
                DeltaConsumption=delta_cons_tree,
                MU_0=mu_0,
                MU_1=mu_1,
                MU_2=mu_2)

    if return_delta_utility:
        return delta_utility
Пример #9
0
def save_sensitivity_analysis(m, utility, utility_tree, cons_tree, cost_tree,
                              ce_tree, new_cons_tree, cost_array,
                              start_filename):
    """ create_output in dlw_optimization. Maybe we only want to use gradient desecent here"""
    from tools import write_columns_csv

    sdf_tree = BigStorageTree(utility.period_len, utility.decision_times)
    sdf_tree.set_value(0, np.array([1.0]))

    discount_prices = np.zeros(len(sdf_tree))
    net_expected_damages = np.zeros(len(sdf_tree))
    expected_damages = np.zeros(len(sdf_tree))
    risk_premiums = np.zeros(len(sdf_tree))
    expected_sdf = np.zeros(len(sdf_tree))
    cross_sdf_damages = np.zeros(len(sdf_tree))
    discounted_expected_damages = np.zeros(len(sdf_tree))
    net_discount_damages = np.zeros(len(sdf_tree))
    cov_term = np.zeros(len(sdf_tree))

    discount_prices[0] = 1.0
    cost_sum = 0

    end_price = find_term_structure(m, utility, len(utility_tree), 0.01)
    perp_yield = perpetuity_yield(end_price, sdf_tree.periods[-2])
    print("Zero coupon bond maturing in {} has price {} and yield {}".format(
        sdf_tree.periods[-2], end_price, perp_yield))

    #grad = utility.numerical_gradient(m)
    #years_to_maturity = utility_tree.last_period - utility_tree.subinterval_len
    mu_0, mu_1, mu_2 = utility.marginal_utility(m, utility_tree, cons_tree,
                                                cost_tree, ce_tree)
    sub_len = sdf_tree.subinterval_len
    i = 1
    for period in sdf_tree.periods[1:]:
        node_period = sdf_tree.decision_interval(period)
        period_probs = utility.tree.get_probs_in_period(node_period)
        expected_damage = np.dot(new_cons_tree[period], period_probs)
        expected_damages[i] = expected_damage

        if sdf_tree.is_information_period(period - sdf_tree.subinterval_len):
            total_probs = period_probs[::2] + period_probs[1::2]
            mu_temp = np.zeros(2 * len(mu_1[period - sub_len]))
            mu_temp[::2] = mu_1[period - sub_len]
            mu_temp[1::2] = mu_2[period - sub_len]
            sdf = (np.repeat(total_probs, 2) / period_probs) * (
                mu_temp / np.repeat(mu_0[period - sub_len], 2))
            period_sdf = np.repeat(sdf_tree.tree[period - sub_len], 2) * sdf
        else:
            sdf = mu_1[period - sub_len] / mu_0[period - sub_len]
            period_sdf = sdf_tree[period - sub_len] * sdf

        expected_sdf[i] = np.dot(period_sdf, period_probs)
        cross_sdf_damages[i] = np.dot(period_sdf,
                                      new_cons_tree[period] * period_probs)
        cov_term[i] = cross_sdf_damages[i] - expected_sdf[i] * expected_damage

        discount_prices[i] = expected_sdf[i]
        sdf_tree.set_value(period, period_sdf)

        if i < len(cost_array):
            net_discount_damages[i] = -(expected_damage + cost_array[
                i, 1]) * expected_sdf[i] / new_cons_tree.tree[0]
            cost_sum += -cost_array[
                i, 1] * expected_sdf[i] / new_cons_tree.tree[0]
        else:
            net_discount_damages[
                i] = -expected_damage * expected_sdf[i] / new_cons_tree.tree[0]

        risk_premiums[i] = -cov_term[i] / new_cons_tree.tree[0]
        discounted_expected_damages[
            i] = -expected_damage * expected_sdf[i] / new_cons_tree.tree[0]
        i += 1

    damage_scale = utility.cost.price(
        0, m[0], 0) / (net_discount_damages.sum() + risk_premiums.sum())
    scaled_discounted_ed = net_discount_damages * damage_scale
    scaled_risk_premiums = risk_premiums * damage_scale

    write_columns_csv([
        discount_prices, net_discount_damages, expected_damages, risk_premiums,
        expected_sdf, cross_sdf_damages, discounted_expected_damages, cov_term,
        scaled_discounted_ed, scaled_risk_premiums
    ], start_filename + "sensitivity_output", [
        "Year", "Discount Prices", "Net Expected Damages", "Expected Damages",
        "Risk Premium", "Expected SDF", "Cross SDF & Damages",
        "Discounted Expected Damages", "Cov Term",
        "Scaled Net Expected Damages", "Scaled Risk Premiums"
    ], [sdf_tree.periods.astype(int) + 2015])

    store_trees(prefix=start_filename,
                SDF=sdf_tree,
                DeltaConsumption=new_cons_tree,
                MU_0=mu_0,
                MU_1=mu_1,
                MU_2=mu_2)
Пример #10
0
    def adjusted_utility(self,
                         m,
                         period_cons_eps=None,
                         node_cons_eps=None,
                         final_cons_eps=0.0,
                         first_period_consadj=0.0,
                         return_trees=False):
        """Calculating adjusted utility for sensitivity analysis. Used e.g. to find zero-coupon bond price.

		Args:
			m (ndarray): 1D-array of mitigations.
			period_cons_eps (optionla, ndarray): Array of increases in consumption per period. #77
			node_cons_eps (optional, ndarray): Array of increases in consumption per node. #(big_storage)
			final_cons_eps (optional, float): Number to increase the final utility.
			first_period_consadj (optional, float): Adjustment of consumption at time 0.
			return_trees (bool): True if method should return trees calculculated in producing the utility.

		Returns:
			tuple of ndarrays if return_trees else float of period 0's utility.

		"""
        # can we make this smarter and not create these every time we call the utility?
        utility_tree = BigStorageTree(subinterval_len=self.period_len,
                                      decision_times=self.decision_times)
        cons_tree = BigStorageTree(subinterval_len=self.period_len,
                                   decision_times=self.decision_times)
        ce_tree = BigStorageTree(subinterval_len=self.period_len,
                                 decision_times=self.decision_times)
        cost_tree = SmallStorageTree(decision_times=self.decision_times)

        self._end_period_utility(m, utility_tree, cons_tree, cost_tree)
        periods = utility_tree.periods[::-1]

        if period_cons_eps is None:
            period_cons_eps = np.zeros(len(periods))
        if node_cons_eps is None:
            node_cons_eps = BigStorageTree(subinterval_len=self.period_len,
                                           decision_times=self.decision_times)

        it = self._utility_generator(m, utility_tree, cons_tree, cost_tree,
                                     ce_tree, first_period_consadj)
        i = len(utility_tree) - 2
        for u, period in it:
            if period == periods[1]:
                mu_0 = (1.0 - self.b) * (u / cons_tree[period])**(1.0 - self.r)
                next_term = self.b * (1.0 - self.b) / (
                    1.0 - self.b * self.growth_term**self.r)
                mu_1 = (u**(1.0 - self.r)) * next_term * (cons_tree.last
                                                          **(self.r - 1.0))
                u += (final_cons_eps + period_cons_eps[-1]) * mu_1
                u += (period_cons_eps[i] + node_cons_eps.tree[period]) * mu_0
                utility_tree.set_value(period, u)
            else:
                mu_0, m_1, m_2 = self._period_marginal_utility(
                    mu_0, mu_1, m, period, utility_tree, cons_tree, ce_tree)
                u += (period_cons_eps[i] + node_cons_eps.tree[period]) * mu_0
                utility_tree.set_value(period, u)
            i -= 1

        if return_trees:
            return utility_tree, cons_tree, cost_tree, ce_tree
        return utility_tree.tree[0]