コード例 #1
0
def calcLorenzDistance(SomeTypes):
    '''
    Calculates the Euclidean distance between the simulated and actual (from SCF data) Lorenz curves at the
    20th, 40th, 60th, and 80th percentiles.
    
    Parameters
    ----------
    SomeTypes : [AgentType]
        List of AgentTypes that have been solved and simulated.  Current levels of individual assets should
        be stored in the attribute aLvl.
        
    Returns
    -------
    lorenz_distance : float
        Euclidean distance (square root of sum of squared differences) between simulated and actual Lorenz curves.
    '''
    # Define empirical Lorenz curve points
    lorenz_SCF = np.array([-0.00183091,  0.0104425 ,  0.0552605 ,  0.1751907 ])
    
    # Extract asset holdings from all consumer types
    aLvl_sim = np.concatenate([ThisType.aLvl for ThisType in MyTypes])
    
    # Calculate simulated Lorenz curve points
    lorenz_sim = get_lorenz_shares(aLvl_sim,percentiles=[0.2,0.4,0.6,0.8])
    
    # Calculate the Euclidean distance between the simulated and actual Lorenz curves
    lorenz_distance = np.sqrt(np.sum((lorenz_SCF - lorenz_sim)**2))
    
    # Return the Lorenz distance
    return lorenz_distance
コード例 #2
0
# %% [markdown]
# ## Plotting the Lorenz Curve

# %%
# Plot Lorenz curves for model with uniform distribution of time preference
from HARK.datasets import load_SCF_wealth_weights
from HARK.utilities import get_lorenz_shares, get_percentiles

SCF_wealth, SCF_weights = load_SCF_wealth_weights()

pctiles = np.linspace(0.001, 0.999, 200)
sim_wealth = np.concatenate(
    [ThisType.state_now["aLvl"] for ThisType in MyTypes])
SCF_Lorenz_points = get_lorenz_shares(SCF_wealth,
                                      weights=SCF_weights,
                                      percentiles=pctiles)
sim_Lorenz_points = get_lorenz_shares(sim_wealth, percentiles=pctiles)
plt.plot(pctiles, SCF_Lorenz_points, '--k')
plt.plot(pctiles, sim_Lorenz_points, '-b')
plt.xlabel('Percentile of net worth')
plt.ylabel('Cumulative share of wealth')
plt.show(block=False)

# %% [markdown]
# ## Calculating the Lorenz Distance at Targets
#
# Now we want to construct a function that calculates the Euclidean distance between simulated and actual Lorenz curves at the four percentiles of interest: 20, 40, 60, and 80.

# %% [markdown]
# ## The Distribution Of the Marginal Propensity to Consume
コード例 #3
0
    def calc_stats(self, aLvlNow, pLvlNow, MPCnow, TranShkNow, EmpNow, t_age,
                   LorenzBool, ManyStatsBool):
        '''
        Calculate various statistics about the current population in the economy.

        Parameters
        ----------
        aLvlNow : [np.array]
            Arrays with end-of-period assets, listed by each ConsumerType in self.agents.
        pLvlNow : [np.array]
            Arrays with permanent income levels, listed by each ConsumerType in self.agents.
        MPCnow : [np.array]
            Arrays with marginal propensity to consume, listed by each ConsumerType in self.agents.
        TranShkNow : [np.array]
            Arrays with transitory income shocks, listed by each ConsumerType in self.agents.
        EmpNow : [np.array]
            Arrays with employment states: True if employed, False otherwise.
        t_age : [np.array]
            Arrays with periods elapsed since model entry, listed by each ConsumerType in self.agents.
        LorenzBool: bool
            Indicator for whether the Lorenz target points should be calculated.  Usually False,
            only True when DiscFac has been identified for a particular nabla.
        ManyStatsBool: bool
            Indicator for whether a lot of statistics for tables should be calculated. Usually False,
            only True when parameters have been estimated and we want values for tables.

        Returns
        -------
        None
        '''
        # Combine inputs into single arrays
        aLvl = np.hstack(aLvlNow)
        pLvl = np.hstack(pLvlNow)
        age = np.hstack(t_age)
        TranShk = np.hstack(TranShkNow)
        EmpNow = np.hstack(EmpNow)

        # Calculate the capital to income ratio in the economy
        CohortWeight = self.PopGroFac**(-age)
        CapAgg = np.sum(aLvl * CohortWeight)
        IncAgg = np.sum(pLvl * TranShk * CohortWeight)
        KtoYnow = CapAgg / IncAgg
        self.KtoYnow = KtoYnow

        # Store Lorenz data if requested
        self.LorenzLong = np.nan
        if LorenzBool:
            order = np.argsort(aLvl)
            aLvl = aLvl[order]
            CohortWeight = CohortWeight[order]
            wealth_shares = get_lorenz_shares(
                aLvl,
                weights=CohortWeight,
                percentiles=self.LorenzPercentiles,
                presorted=True)
            self.Lorenz = wealth_shares

            if ManyStatsBool:
                self.LorenzLong = get_lorenz_shares(aLvl,
                                                    weights=CohortWeight,
                                                    percentiles=np.arange(
                                                        0.01, 1.0, 0.01),
                                                    presorted=True)
        else:
            self.Lorenz = np.nan  # Store nothing if we don't want Lorenz data

        # Calculate a whole bunch of statistics if requested
        if ManyStatsBool:
            # Reshape other inputs
            MPC = np.hstack(MPCnow)

            # Sort other data items if aLvl and CohortWeight were sorted
            if LorenzBool:
                pLvl = pLvl[order]
                MPC = MPC[order]
                TranShk = TranShk[order]
                age = age[order]
                EmpNow = EmpNow[order]
            aNrm = aLvl / pLvl  # Normalized assets (wealth ratio)
            IncLvl = TranShk * pLvl  # Labor income this period

            # Calculate overall population MPC and by subpopulations
            MPCannual = 1.0 - (1.0 - MPC)**4
            self.MPCall = np.sum(
                MPCannual * CohortWeight) / np.sum(CohortWeight)
            employed = EmpNow
            unemployed = np.logical_not(employed)
            if self.T_retire > 0:  # Adjust for the lifecycle model, where agents might be retired instead
                unemployed = np.logical_and(unemployed, age < self.T_retire)
                employed = np.logical_and(employed, age < self.T_retire)
                retired = age >= self.T_retire
            else:
                retired = np.zeros_like(unemployed, dtype=bool)
            self.MPCunemployed = np.sum(
                MPCannual[unemployed] * CohortWeight[unemployed]) / np.sum(
                    CohortWeight[unemployed])
            self.MPCemployed = np.sum(
                MPCannual[employed] * CohortWeight[employed]) / np.sum(
                    CohortWeight[employed])
            self.MPCretired = np.sum(
                MPCannual[retired] * CohortWeight[retired]) / np.sum(
                    CohortWeight[retired])
            self.MPCbyWealthRatio = calc_subpop_avg(MPCannual, aNrm,
                                                    self.cutoffs, CohortWeight)
            self.MPCbyIncome = calc_subpop_avg(MPCannual, IncLvl, self.cutoffs,
                                               CohortWeight)

            # Calculate the wealth quintile distribution of "hand to mouth" consumers
            quintile_cuts = get_percentiles(aLvl,
                                            weights=CohortWeight,
                                            percentiles=[0.2, 0.4, 0.6, 0.8])
            wealth_quintiles = np.ones(aLvl.size, dtype=int)
            wealth_quintiles[aLvl > quintile_cuts[0]] = 2
            wealth_quintiles[aLvl > quintile_cuts[1]] = 3
            wealth_quintiles[aLvl > quintile_cuts[2]] = 4
            wealth_quintiles[aLvl > quintile_cuts[3]] = 5
            MPC_cutoff = get_percentiles(
                MPCannual, weights=CohortWeight, percentiles=[
                    2.0 / 3.0
                ])  # Looking at consumers with MPCs in the top 1/3
            these = MPCannual > MPC_cutoff
            in_top_third_MPC = wealth_quintiles[these]
            temp_weights = CohortWeight[these]
            hand_to_mouth_total = np.sum(temp_weights)
            hand_to_mouth_pct = []
            for q in range(1, 6):
                hand_to_mouth_pct.append(
                    np.sum(temp_weights[in_top_third_MPC == q]) /
                    hand_to_mouth_total)
            self.HandToMouthPct = np.array(hand_to_mouth_pct)

        else:  # If we don't want these stats, just put empty values in history
            self.MPCall = np.nan
            self.MPCunemployed = np.nan
            self.MPCemployed = np.nan
            self.MPCretired = np.nan
            self.MPCbyWealthRatio = np.nan
            self.MPCbyIncome = np.nan
            self.HandToMouthPct = np.nan
コード例 #4
0
def runRoszypalSchlaffmanExperiment(CorrAct, CorrPcvd, DiscFac_center,
                                    DiscFac_spread):
    '''
    Solve and simulate a consumer type who misperceives the extent of serial correlation
    of persistent shocks to income.
    
    Parameters
    ----------
    CorrAct : float
        Serial correlation coefficient for *actual* persistent income.
    CorrPcvd : float
        List or array of *perceived* persistent income.
    DiscFac_center : float
        A measure of centrality for the distribution of the beta parameter, DiscFac.
    DiscFac_spread : float
        A measure of spread or diffusion for the distribution of the beta parameter.


    Returns
    -------
    AggWealthRatio: float
        Ratio of Aggregate wealth to income.
    Lorenz: numpy.array
        A list of two 1D array reprensenting the Lorenz curve for assets in the most recent simulated period.
    Gini: float
        Gini coefficient for assets in the most recent simulated period.
    Avg_MPC: numpy.array
        Average marginal propensity to consume by income quintile in the latest simulated period.
    
    '''

    # Make a dictionary to construct our consumer type
    ThisDict = copy(BaselineDict)
    ThisDict['PrstIncCorr'] = CorrAct

    # Make a 7 point approximation to a uniform distribution of DiscFac
    DiscFac_list = Uniform(bot=DiscFac_center - DiscFac_spread,
                           top=DiscFac_center + DiscFac_spread).approx(N=7).X

    type_list = []
    # Make a PersistentShockConsumerTypeX for each value of beta saved in DiscFac_list
    for i in range(len(DiscFac_list)):
        ThisDict['DiscFac'] = DiscFac_list[i]
        ThisType = PersistentShockConsumerTypeX(**ThisDict)

        # Make the consumer type *believe* he will face a different level of persistence
        ThisType.PrstIncCorr = CorrPcvd
        ThisType.update_pLvlNextFunc(
        )  # Now he *thinks* E[p_{t+1}] as a function of p_t is different than it is

        # Solve the consumer's problem with *perceived* persistence
        ThisType.solve()

        # Make the consumer type experience the true level of persistence during simulation
        ThisType.PrstIncCorr = CorrAct
        ThisType.update_pLvlNextFunc()

        # Simulate the agents for many periods
        ThisType.T_sim = 100
        #ThisType.track_vars = ['cLvl','aLvl','pLvl','MPCnow']
        ThisType.initialize_sim()
        ThisType.simulate()
        type_list.append(ThisType)

    # Get the most recent simulated values of X = cLvl, MPCnow, aLvl, pLvl for all types
    cLvl_all = np.concatenate(
        [ThisType.controls["cLvl"] for ThisType in type_list])
    aLvl_all = np.concatenate(
        [ThisType.state_now["aLvl"] for ThisType in type_list])
    MPC_all = np.concatenate([ThisType.MPCnow for ThisType in type_list])
    pLvl_all = np.concatenate(
        [ThisType.state_now["pLvl"] for ThisType in type_list])

    # The ratio of aggregate assets over the income
    AggWealthRatio = np.mean(aLvl_all) / np.mean(pLvl_all)

    # first 1D array: Create points in the range (0,1)
    wealth_percentile = np.linspace(0.001, 0.999, 201)

    # second 1D array: Compute Lorenz shares for the created points
    Lorenz_init = get_lorenz_shares(aLvl_all, percentiles=wealth_percentile)

    # Stick 0 and 1 at the boundaries of both arrays to make it inclusive on the range [0,1]
    Lorenz_init = np.concatenate([[0], Lorenz_init, [1]])
    wealth_percentile = np.concatenate([[0], wealth_percentile, [1]])

    # Create a list of wealth_percentile 1D array and Lorenz Shares 1D array
    Lorenz = np.stack((wealth_percentile, Lorenz_init))

    # Compute the Gini coefficient
    Gini = 1.0 - 2.0 * np.mean(Lorenz_init[1])

    # Compute the average MPC by income quintile in the latest simulated period
    Avg_MPC = calc_subpop_avg(MPC_all,
                              pLvl_all,
                              cutoffs=[(0.0, 0.2), (0.2, 0.4), (0.4, 0.6),
                                       (0.6, 0.8), (0.8, 1.0)])

    return AggWealthRatio, Lorenz, Gini, Avg_MPC
コード例 #5
0
    return AgeDstn


###############################################################################
### ACTUAL WORK BEGINS BELOW THIS LINE  #######################################
###############################################################################

if __name__ == '__main__':

    # Set targets for K/Y and the Lorenz curve based on the data
    if do_liquid:
        lorenz_target = np.array([0.0, 0.004, 0.025, 0.117])
        KY_target = 6.60
    else:  # This is hacky until I can find the liquid wealth data and import it
        lorenz_target = get_lorenz_shares(
            Params.SCF_wealth,
            weights=Params.SCF_weights,
            percentiles=Params.percentiles_to_match)
        lorenz_long_data = np.hstack(
            (np.array(0.0),
             get_lorenz_shares(Params.SCF_wealth,
                               weights=Params.SCF_weights,
                               percentiles=np.arange(0.01, 1.0,
                                                     0.01).tolist()),
             np.array(1.0)))
        #lorenz_target = np.array([-0.002, 0.01, 0.053,0.171])
        KY_target = 10.26

    # Set total number of simulated agents in the population
    if do_param_dist:
        if do_agg_shocks:
            Population = Params.pop_sim_agg_dist