Esempio n. 1
0
    def updateEvolution(self):
        '''
        Updates the "population punk proportion" evolution array.  Fasion victims
        believe that the proportion of punks in the subsequent period is a linear
        function of the proportion of punks this period, subject to a uniform
        shock.  Given attributes of self pNextIntercept, pNextSlope, pNextCount,
        pNextWidth, and pGrid, this method generates a new array for the attri-
        bute pEvolution, representing a discrete approximation of next period
        states for each current period state in pGrid.

        Parameters
        ----------
        None

        Returns
        -------
        None
        '''
        self.pEvolution = np.zeros((self.pCount, self.pNextCount))
        for j in range(self.pCount):
            pNow = self.pGrid[j]
            pNextMean = self.pNextIntercept + self.pNextSlope * pNow
            dist = Uniform(bot=pNextMean - self.pNextWidth,
                           top=pNextMean + self.pNextWidth)
            self.pEvolution[j, :] = dist.approx(self.pNextCount).X
Esempio n. 2
0
    def test_distribute_params(self):
        dist = Uniform(bot=0.9, top=0.94)

        self.agents = distribute_params(self.agent, 'DiscFac', 3, dist)

        self.assertTrue(all(['DiscFac' in agent.parameters for agent in self.agents]))
        self.assertTrue(all([self.agents[i].parameters['DiscFac'] == dist.approx(3).X[i] for i in range(3)]))
Esempio n. 3
0
    def getMarkovStates(self):
        """
        Draw new Markov states for each agent in the simulated population, using
        the attribute MrkvArray to determine transition probabilities.
        
        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        # Draw random numbers that will be used to determine the next Markov state
        if self.global_markov:
            base_draws = np.ones(self.AgentCount) * Uniform(
                seed=self.RNG.randint(0, 2 ** 31 - 1)
            ).draw(1)
        else:
            base_draws = Uniform(seed=self.RNG.randint(0, 2 ** 31 - 1)).draw(
                self.AgentCount
            )
        dont_change = (
            self.t_age == 0
        )  # Don't change Markov state for those who were just born (unless global_markov)
        if self.t_sim == 0:  # Respect initial distribution of Markov states
            dont_change[:] = True

        # Determine which agents are in which states right now
        J = self.MrkvArray[0].shape[0]
        MrkvPrev = self.shocks["MrkvNow"]
        MrkvNow = np.zeros(self.AgentCount, dtype=int)
        MrkvBoolArray = np.zeros((J, self.AgentCount))

        for j in range(J):
            MrkvBoolArray[j, :] = MrkvPrev == j

        # Draw new Markov states for each agent
        for t in range(self.T_cycle):
            Cutoffs = np.cumsum(self.MrkvArray[t], axis=1)
            right_age = self.t_cycle == t
            for j in range(J):
                these = np.logical_and(right_age, MrkvBoolArray[j, :])
                MrkvNow[these] = np.searchsorted(
                    Cutoffs[j, :], base_draws[these]
                ).astype(int)
        if not self.global_markov:
            MrkvNow[dont_change] = MrkvPrev[dont_change]

        self.shocks["MrkvNow"] = MrkvNow.astype(int)
Esempio n. 4
0
    def test_small_open(self):
        agent = AggShockConsumerType()
        agent.AgentCount = 100  # Very low number of agents for the sake of speed
        agent.cycles = 0

        # Make agents heterogeneous in their discount factor
        agents = distribute_params(
            agent, "DiscFac", 3, Uniform(bot=0.90, top=0.94)  # Impatient agents
        )

        # Make an economy with those agents living in it
        small_economy = SmallOpenEconomy(
            agents=agents,
            Rfree=1.03,
            wRte=1.0,
            KtoLnow=1.0,
            **copy.copy(init_cobb_douglas)
        )

        small_economy.act_T = 400  # Short simulation history
        small_economy.max_loops = 3  # Give up quickly for the sake of time
        small_economy.make_AggShkHist()  # Simulate a history of aggregate shocks
        small_economy.verbose = False  # Turn off printed messages

        # Give data about the economy to all the agents in it
        for this_type in small_economy.agents:
            this_type.get_economy_data(small_economy)

        small_economy.solve()
Esempio n. 5
0
    def getShocks(self):
        '''
        Draws a new Markov state and income shocks for the representative agent.

        Parameters
        ----------
        None

        Returns
        -------
        None
        '''
        cutoffs = np.cumsum(self.MrkvArray[self.MrkvNow,:])
        MrkvDraw = Uniform().draw(N=1,seed=self.RNG.randint(0,2**31-1))
        self.MrkvNow = np.searchsorted(cutoffs,MrkvDraw)

        t = self.t_cycle[0]
        i = self.MrkvNow[0]
        IncomeDstnNow    = self.IncomeDstn[t-1][i] # set current income distribution
        PermGroFacNow    = self.PermGroFac[t-1][i] # and permanent growth factor
        # Get random draws of income shocks from the discrete distribution
        EventDraw        =         IncomeDstnNow.draw_events(1,
                                                             seed=self.RNG.randint(0,2**31-1))
        PermShkNow = IncomeDstnNow.X[0][EventDraw]*PermGroFacNow # permanent "shock" includes expected growth
        TranShkNow = IncomeDstnNow.X[1][EventDraw]
        self.PermShkNow = np.array(PermShkNow)
        self.TranShkNow = np.array(TranShkNow)
Esempio n. 6
0
    def sim_birth(self, which_agents):
        """
        Makes new Markov consumer by drawing initial normalized assets, permanent income levels, and
        discrete states. Calls IndShockConsumerType.sim_birth, then draws from initial Markov distribution.

        Parameters
        ----------
        which_agents : np.array(Bool)
            Boolean array of size self.AgentCount indicating which agents should be "born".

        Returns
        -------
        None
        """
        IndShockConsumerType.sim_birth(
            self, which_agents
        )  # Get initial assets and permanent income
        if (
            not self.global_markov
        ):  # Markov state is not changed if it is set at the global level
            N = np.sum(which_agents)
            base_draws = Uniform(seed=self.RNG.randint(0, 2 ** 31 - 1)).draw(N)
            Cutoffs = np.cumsum(np.array(self.MrkvPrbsInit))
            self.shocks["Mrkv"][which_agents] = np.searchsorted(
                Cutoffs, base_draws
            ).astype(int)
Esempio n. 7
0
 def hitWithPandemicShock(self):
     '''
     Alter the Markov state of each simulated agent, jumping some people into
     an otherwise inaccessible "deep unemployment" state, and others into
     normal unemployment.
     '''
     # Calculate (cumulative) probabilities of each agent being shocked into each state
     age = (self.t_age/4) + 24
     DeepX = self.DeepParam0 + self.DeepParam1*np.log(self.pLvlNow) + self.DeepParam2*age + self.DeepParam3*age**2
     UnempX = self.UnempParam0 + self.UnempParam1*np.log(self.pLvlNow) + self.UnempParam2*age + self.UnempParam3*age**2
     expDeepX = np.exp(DeepX)
     expUnempX = np.exp(UnempX)
     denom = 1. + expDeepX + expUnempX
     EmpPrb = 1./denom
     UnempPrb = expUnempX/denom
     DeepPrb = expDeepX/denom
     PrbArray = np.vstack([EmpPrb,UnempPrb,DeepPrb])
     CumPrbArray = np.cumsum(PrbArray, axis=0)
     
     # Draw new Markov states for each agent
     draws = Uniform().draw(self.AgentCount, seed=self.RNG.randint(0,2**31-1))
     draws = self.RNG.permutation(draws)
     MrkvNew = np.zeros(self.AgentCount, dtype=int)
     MrkvNew[draws > CumPrbArray[0]] = 1
     MrkvNew[draws > CumPrbArray[1]] = 2
     if (self.PanShock and not self.L_shared): # If the pandemic actually occurs,
         MrkvNew += 3 # then put everyone into the low marginal utility world/
         # This is (momentarily) skipped over if the lockdown state is shared
         # rather than idiosyncratic.  See a few lines below.
     
     # Move agents to those Markov states 
     self.MrkvNow = MrkvNew
     
     # Take the appropriate shock history for each agent, depending on their state
     J = self.MrkvArray[0].shape[0]
     for j in range(J):
         these = self.MrkvNow == j
         self.history['who_dies'][:,these] = self.DeathHistAll[j,:,:][:,these]
         self.history['MrkvNow'][:,these] = self.MrkvHistAll[j,:,:][:,these]
         self.history['PermShkNow'][:,these] = self.PermShkHistAll[j,:,:][:,these]
         self.history['TranShkNow'][:,these] = self.TranShkHistAll[j,:,:][:,these]
     
     # If the lockdown is a common/shared event, rather than idiosyncratic, bump
     # everyone into the lockdown state for *exactly* T_lockdown periods
     if (self.PanShock and self.L_shared):
         T = self.T_lockdown
         self.history['MrkvNow'][0:T,:] += 3
         
     # Edit the first period of the shock history to give all unemployed
     # people a bonus payment in just that quarter
     one_off_benefits = True   # If agents get continued unemployment benefits, the first period benefits are counted later
     if hasattr(self,'ContUnempBenefits'):
         if self.ContUnempBenefits==True:
             one_off_benefits = False
     if one_off_benefits:
         young = self.age_base < self.T_retire
         unemp = np.logical_and(np.mod(self.MrkvNow,3) == 1, young)
         deep  = np.logical_and(np.mod(self.MrkvNow,3) == 2, young)
         self.history['TranShkNow'][0,unemp] += self.BonusUnemp/(self.pLvlNow[unemp]*self.history['PermShkNow'][0,unemp])
         self.history['TranShkNow'][0,deep]  += self.BonusDeep/(self.pLvlNow[deep]*self.history['PermShkNow'][0,deep])
Esempio n. 8
0
    def sim_death(self):
        """
        Determines which agents die this period and must be replaced.  Uses the sequence in LivPrb
        to determine survival probabilities for each agent.

        Parameters
        ----------
        None

        Returns
        -------
        which_agents : np.array(bool)
            Boolean array of size AgentCount indicating which agents die.
        """
        # Determine who dies
        LivPrb = np.array(self.LivPrb)[
            self.t_cycle - 1, self.shocks["Mrkv"]
        ]  # Time has already advanced, so look back one
        DiePrb = 1.0 - LivPrb
        DeathShks = Uniform(seed=self.RNG.randint(0, 2 ** 31 - 1)).draw(
            N=self.AgentCount
        )
        which_agents = DeathShks < DiePrb
        if self.T_age is not None:  # Kill agents that have lived for too many periods
            too_old = self.t_age >= self.T_age
            which_agents = np.logical_or(which_agents, too_old)
        return which_agents
Esempio n. 9
0
 def initializeSim(self):
     IndShockConsumerType.initializeSim(self)
     if self.global_markov:  #Need to initialize markov state to be the same for all agents
         base_draw = Uniform(seed=self.RNG.randint(0, 2**31 - 1)).draw(1)
         Cutoffs = np.cumsum(np.array(self.MrkvPrbsInit))
         self.MrkvNow = np.ones(self.AgentCount) * np.searchsorted(
             Cutoffs, base_draw).astype(int)
     self.MrkvNow = self.MrkvNow.astype(int)
 def initialize_sim(self):
     self.shocks["Mrkv"] = np.zeros(self.AgentCount, dtype=int)
     IndShockConsumerType.initialize_sim(self)
     if (self.global_markov
         ):  # Need to initialize markov state to be the same for all agents
         base_draw = Uniform(seed=self.RNG.randint(0, 2**31 - 1)).draw(1)
         Cutoffs = np.cumsum(np.array(self.MrkvPrbsInit))
         self.shocks["Mrkv"] = np.ones(self.AgentCount) * np.searchsorted(
             Cutoffs, base_draw).astype(int)
     self.shocks["Mrkv"] = self.shocks["Mrkv"].astype(int)
    def setUp(self):
        agent = AggShockConsumerType()
        agent.AgentCount = 900  # Very low number of agents for the sake of speed
        agent.cycles = 0

        # Make agents heterogeneous in their discount factor
        self.agents = distribute_params(
            agent, "DiscFac", 3, Uniform(bot=0.90, top=0.94)  # Impatient agents
        )

        # Make an economy with those agents living in it
        self.economy = CobbDouglasEconomy(agents=self.agents)
Esempio n. 12
0
    def distribute_params(self, param_name, param_count, center, spread,
                          dist_type):
        '''
        Distributes heterogeneous values of one parameter to the AgentTypes in self.agents.

        Parameters
        ----------
        param_name : string
            Name of the parameter to be assigned.
        param_count : int
            Number of different values the parameter will take on.
        center : float
            A measure of centrality for the distribution of the parameter.
        spread : float
            A measure of spread or diffusion for the distribution of the parameter.
        dist_type : string
            The type of distribution to be used.  Can be "lognormal" or "uniform" (can expand).

        Returns
        -------
        None
        '''
        # Get a list of discrete values for the parameter
        if dist_type == 'uniform':
            # If uniform, center is middle of distribution, spread is distance to either edge
            param_dist = Uniform(bot=center - spread,
                                 top=center + spread).approx(N=param_count)
        elif dist_type == 'lognormal':
            # If lognormal, center is the mean and spread is the standard deviation (in log)
            tail_N = 3
            param_dist = Lognormal(mu=np.log(center) - 0.5 * spread**2,
                                   sigma=spread,
                                   tail_N=tail_N,
                                   tail_bound=[0.0, 0.9],
                                   tail_order=np.e).approx(N=param_count -
                                                           tail_N)

        # Distribute the parameters to the various types, assigning consecutive types the same
        # value if there are more types than values
        replication_factor = len(self.agents) // param_count
        # Note: the double division is intenger division in Python 3 and 2.7, this makes it explicit
        j = 0
        b = 0
        while j < len(self.agents):
            for n in range(replication_factor):
                self.agents[j].assign_parameters(
                    AgentCount=int(self.Population * param_dist.pmf[b] *
                                   self.TypeWeight[n]))
                exec('self.agents[j].assign_parameters(' + param_name +
                     '= param_dist.X[b])')
                j += 1
            b += 1
Esempio n. 13
0
# %% [markdown]
# Now let's make several instances of our class of agents and give them different values of $\beta$, following cstwMPC's estimated distribution.  In our specification of interest, we will use $\grave{\beta}=0.9855583$ and $\nabla = 0.0085$.
#
# NB: Reported parameter estimates in cstwMPC use a model with aggregate shocks and wage and interest rates determined dynamically (a heterogeneous agents DSGE model); this is the $\texttt{AggShockConsumerType}$ in HARK.  The estimated parameters are slightly different in this exercise, as we are ignoring general equilibrium aspects and only using the $\texttt{IndShockConsumerType}$

# %%
# This cell constructs seven instances of IndShockConsumerType with different discount factors
from HARK.distribution import Uniform

BaselineType = IndShockConsumerType(**cstwMPC_calibrated_parameters)

# Specify the distribution of the discount factor
num_types = 7  # number of types we want
DiscFac_mean = 0.9855583  # center of beta distribution
DiscFac_spread = 0.0085  # spread of beta distribution
DiscFac_dstn = Uniform(DiscFac_mean - DiscFac_spread, DiscFac_mean +
                       DiscFac_spread).approx(num_types).X.flatten()

MyTypes = []  # initialize an empty list to hold our consumer types
for nn in range(num_types):
    # Now create the types, and append them to the list MyTypes
    NewType = deepcopy(BaselineType)
    NewType.DiscFac = DiscFac_dstn[nn]
    NewType.seed = nn  # give each consumer type a different RNG seed
    MyTypes.append(NewType)

# %% [markdown]
# ## Solving and Simulating the Baseline Agents
#
# Now let's solve and simulate each of our types of agents.  If you look in the parameter dictionary (or at any of the agent objects themselves), you will see that each one has an $\texttt{AgentCount}$ attribute of 10000. That is, these seven ex ante heterogeneous types each represent ten thousand individual agents that will experience ex post heterogeneity when they draw different income (and mortality) shocks over time.
#
# In the code block below, fill in the contents of the loop to solve and simulate each agent type for many periods.  To do this, you should invoke the methods $\texttt{solve}$, $\texttt{initialize_sim}$, and $\texttt{simulate}$ in that order.  Simulating for 1200 quarters (300 years) will approximate the long run distribution of wealth in the population.
    # Now create the types, and append them to the list ConsumerTypes
    NewType = deepcopy(BaselineType)
    NewType.seed = nn  # give each consumer type a different RNG seed
    ConsumerTypes.append(NewType)

# %% [markdown]
# Now we can give each of the consumer types their own discount factor. (This approximates the distribution of parameters estimated in ["The Distribution of Wealth and the Marginal Propensity to Consume"](http://econ.jhu.edu/people/ccarroll/papers/cstwMPC)).

# %% {"code_folding": []}
# Seven types is enough to approximate the uniform distribution (5 is not quite enough)
from HARK.distribution import Uniform

# Calibrations from cstwMPC
bottomDiscFac = 0.9800
topDiscFac = 0.9934
DiscFac_list = Uniform(bot=bottomDiscFac,
                       top=topDiscFac).approx(N=num_consumer_types).X

# Now, assign the discount factors
for j in range(num_consumer_types):
    ConsumerTypes[j].DiscFac = DiscFac_list[j]
    ConsumerTypes[j].quiet = True  # Turn off some output

# %% [markdown]
# Our agents now exist and have a concept of the problem they face, but we still need them to solve that problem.
#
# Once we have solved each type of consumer's individual problem, we need to know the distribution of wealth (and permanent income) that the population would achieve in the long run.
#
# The cell below does both of those tasks, looping through the consumer types. For each one, it solves that type's infinite horizon model, then simulates 1000 periods to generate an approximation to the long run distribution of wealth.

# %% {"code_folding": []}
# tqdm presents a pretty bar that interactively shows how far the calculations have gotten
Esempio n. 15
0
###############################################################################

# Size of simulations
AgentCountTotal = 50000  # Total simulated population
T_sim = 13  # Number of quarters to simulate in counterfactuals

# Basic lifecycle length parameters (don't touch these)
init_age = 24
working_T = 41 * 4  # Number of working periods
retired_T = 55 * 4  # Number of retired periods
T_cycle = working_T + retired_T

# Define the distribution of the discount factor for each eduation level
DiscFacCount = 7
DiscFacDstnD = Uniform(DiscFacMeanD - DiscFacSpread,
                       DiscFacMeanD + DiscFacSpread).approx(DiscFacCount)
DiscFacDstnH = Uniform(DiscFacMeanH - DiscFacSpread,
                       DiscFacMeanH + DiscFacSpread).approx(DiscFacCount)
DiscFacDstnC = Uniform(DiscFacMeanC - DiscFacSpread,
                       DiscFacMeanC + DiscFacSpread).approx(DiscFacCount)
DiscFacDstns = [DiscFacDstnD, DiscFacDstnH, DiscFacDstnC]

# Define permanent income growth rates for each education level (from Cagetti 2003)
PermGroRte_d_ann = [
    5.2522391e-002, 5.0039782e-002, 4.7586132e-002, 4.5162424e-002,
    4.2769638e-002, 4.0408757e-002, 3.8080763e-002, 3.5786635e-002,
    3.3527358e-002, 3.1303911e-002, 2.9117277e-002, 2.6968437e-002,
    2.4858374e-002, 2.2788068e-002, 2.0758501e-002, 1.8770655e-002,
    1.6825511e-002, 1.4924052e-002, 1.3067258e-002, 1.1256112e-002,
    9.4915947e-003, 7.7746883e-003, 6.1063742e-003, 4.4876340e-003,
    2.9194495e-003, 1.4028022e-003, -6.1326258e-005, -1.4719542e-003,
Esempio n. 16
0
def FagerengObjFunc(center, spread, verbose=False):
    '''
    Objective function for the quick and dirty structural estimation to fit
    Fagereng, Holm, and Natvik's Table 9 results with a basic infinite horizon
    consumption-saving model (with permanent and transitory income shocks).

    Parameters
    ----------
    center : float
        Center of the uniform distribution of discount factors.
    spread : float
        Width of the uniform distribution of discount factors.
    verbose : bool
        When True, print to screen MPC table for these parameters.  When False,
        print (center, spread, distance).

    Returns
    -------
    distance : float
        Euclidean distance between simulated MPCs and (adjusted) Table 9 MPCs.
    '''
    # Give our consumer types the requested discount factor distribution
    beta_set = Uniform(bot=center - spread,
                       top=center + spread).approx(N=TypeCount).X
    for j in range(TypeCount):
        EstTypeList[j](DiscFac=beta_set[j])

    # Solve and simulate all consumer types, then gather their wealth levels
    multiThreadCommands(
        EstTypeList,
        ['solve()', 'initializeSim()', 'simulate()', 'unpackcFunc()'])
    WealthNow = np.concatenate([ThisType.aLvlNow for ThisType in EstTypeList])

    # Get wealth quartile cutoffs and distribute them to each consumer type
    quartile_cuts = getPercentiles(WealthNow, percentiles=[0.25, 0.50, 0.75])
    for ThisType in EstTypeList:
        WealthQ = np.zeros(ThisType.AgentCount, dtype=int)
        for n in range(3):
            WealthQ[ThisType.aLvlNow > quartile_cuts[n]] += 1
        ThisType(WealthQ=WealthQ)

    # Keep track of MPC sets in lists of lists of arrays
    MPC_set_list = [[[], [], [], []], [[], [], [], []], [[], [], [], []],
                    [[], [], [], []]]

    # Calculate the MPC for each of the four lottery sizes for all agents
    for ThisType in EstTypeList:
        ThisType.simulate(1)
        c_base = ThisType.cNrmNow
        MPC_this_type = np.zeros((ThisType.AgentCount, 4))
        for k in range(4):  # Get MPC for all agents of this type
            Llvl = lottery_size[k]
            Lnrm = Llvl / ThisType.pLvlNow
            if do_secant:
                SplurgeNrm = Splurge / ThisType.pLvlNow
                mAdj = ThisType.mNrmNow + Lnrm - SplurgeNrm
                cAdj = ThisType.cFunc[0](mAdj) + SplurgeNrm
                MPC_this_type[:, k] = (cAdj - c_base) / Lnrm
            else:
                mAdj = ThisType.mNrmNow + Lnrm
                MPC_this_type[:, k] = cAdj = ThisType.cFunc[0].derivative(mAdj)

        # Sort the MPCs into the proper MPC sets
        for q in range(4):
            these = ThisType.WealthQ == q
            for k in range(4):
                MPC_set_list[k][q].append(MPC_this_type[these, k])

    # Calculate average within each MPC set
    simulated_MPC_means = np.zeros((4, 4))
    for k in range(4):
        for q in range(4):
            MPC_array = np.concatenate(MPC_set_list[k][q])
            simulated_MPC_means[k, q] = np.mean(MPC_array)

    # Calculate Euclidean distance between simulated MPC averages and Table 9 targets
    diff = simulated_MPC_means - MPC_target
    if drop_corner:
        diff[0, 0] = 0.0
    distance = np.sqrt(np.sum((diff)**2))
    if verbose:
        print(simulated_MPC_means)
    else:
        print(center, spread, distance)
    return distance
Esempio n. 17
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.updatepLvlNextFunc() # 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.updatepLvlNextFunc()
    
        # Simulate the agents for many periods
        ThisType.T_sim = 100
        #ThisType.track_vars = ['cLvlNow','aLvlNow','pLvlNow','MPCnow']
        ThisType.initializeSim()
        ThisType.simulate()
        type_list.append(ThisType)
    
    # Get the most recent simulated values of X = cLvlNow, MPCnow, aLvlNow, pLvlNow for all types   
    cLvl_all = np.concatenate([ThisType.controls["cLvlNow"] for ThisType in type_list])
    aLvl_all = np.concatenate([ThisType.state_now["aLvlNow"] for ThisType in type_list])
    MPC_all = np.concatenate([ThisType.MPCnow for ThisType in type_list])
    pLvl_all = np.concatenate([ThisType.state_now["pLvlNow"] 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 = getLorenzShares(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 = calcSubpopAvg(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
Esempio n. 18
0
#center = .977 for Rfree 1.04**.25 and target 0.34505832912738216
center = .9681
#center =.7

while go:

    discFacDispersion = 0.0049
    bottomDiscFac = center - discFacDispersion
    topDiscFac = center + discFacDispersion

    #tail_N = 3
    #param_dist = Lognormal(mu=np.log(center)-0.5*spread**2,sigma=spread,tail_N=tail_N,tail_bound=[0.0,0.9], tail_order=np.e).approx(N=param_count-tail_N)

    #DiscFac_dist =Lognormal(mu=np.log(center)-0.5*discFacDispersion**2,sigma=discFacDispersion).approx(N=num_consumer_types-3,tail_N=3, tail_bound=[0,0.9])
    DiscFac_dist = Uniform(bot=bottomDiscFac, top=topDiscFac,
                           seed=606).approx(N=num_consumer_types)
    DiscFac_list = DiscFac_dist.X

    consumers_ss = []

    # now create types with different disc factors
    for i in range(num_consumer_types):
        consumers_ss.append(deepcopy(ss_agent))

    for i in range(num_consumer_types):
        consumers_ss[i].DiscFac = DiscFac_list[i]
        consumers_ss[i].AgentCount = int(NumAgents * DiscFac_dist.pmf[i])

    list_pLvl = []
    list_aNrm = []
    list_aLvl = []
Esempio n. 19
0
    def test_Uniform(self):
        uni = Uniform()

        self.assertEqual(Uniform().draw(1)[0], 0.5488135039273248)

        self.assertEqual(calc_expectation(uni.approx(10)), 0.5)
    def update_pLvlGrid(self):
        """
        Update the grid of persistent income levels.  Currently only works for
        infinite horizon models (cycles=0) and lifecycle models (cycles=1).  Not
        clear what to do about cycles>1 because the distribution of persistent
        income will be different within a period depending on how many cycles
        have elapsed.  This method uses a simulation approach to generate the
        pLvlGrid at each period of the cycle, drawing on the initial distribution
        of persistent income, the pLvlNextFuncs, and the attribute pLvlPctiles.

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        LivPrbAll = np.array(self.LivPrb)

        # Simulate the distribution of persistent income levels by t_cycle in a lifecycle model
        if self.cycles == 1:
            pLvlNow = Lognormal(self.pLvlInitMean,
                                sigma=self.pLvlInitStd,
                                seed=31382).draw(self.AgentCount)
            pLvlGrid = []  # empty list of time-varying persistent income grids
            # Calculate distribution of persistent income in each period of lifecycle
            for t in range(len(self.PermShkStd)):
                if t > 0:
                    PermShkNow = self.PermShkDstn[t -
                                                  1].draw(N=self.AgentCount)
                    pLvlNow = self.pLvlNextFunc[t - 1](pLvlNow) * PermShkNow
                pLvlGrid.append(
                    get_percentiles(pLvlNow, percentiles=self.pLvlPctiles))

        # Calculate "stationary" distribution in infinite horizon (might vary across periods of cycle)
        elif self.cycles == 0:
            T_long = 1000  # Number of periods to simulate to get to "stationary" distribution
            pLvlNow = Lognormal(mu=self.pLvlInitMean,
                                sigma=self.pLvlInitStd,
                                seed=31382).draw(self.AgentCount)
            t_cycle = np.zeros(self.AgentCount, dtype=int)
            for t in range(T_long):
                LivPrb = LivPrbAll[
                    t_cycle]  # Determine who dies and replace them with newborns
                draws = Uniform(seed=t).draw(self.AgentCount)
                who_dies = draws > LivPrb
                pLvlNow[who_dies] = Lognormal(self.pLvlInitMean,
                                              self.pLvlInitStd,
                                              seed=t + 92615).draw(
                                                  np.sum(who_dies))
                t_cycle[who_dies] = 0

                for j in range(self.T_cycle):  # Update persistent income
                    these = t_cycle == j
                    PermShkTemp = self.PermShkDstn[j].draw(N=np.sum(these))
                    pLvlNow[these] = self.pLvlNextFunc[j](
                        pLvlNow[these]) * PermShkTemp
                t_cycle = t_cycle + 1
                t_cycle[t_cycle == self.T_cycle] = 0

            # We now have a "long run stationary distribution", extract percentiles
            pLvlGrid = []  # empty list of time-varying persistent income grids
            for t in range(self.T_cycle):
                these = t_cycle == t
                pLvlGrid.append(
                    get_percentiles(pLvlNow[these],
                                    percentiles=self.pLvlPctiles))

        # Throw an error if cycles>1
        else:
            assert False, "Can only handle cycles=0 or cycles=1!"

        # Store the result and add attribute to time_vary
        self.pLvlGrid = pLvlGrid
        self.add_to_time_vary("pLvlGrid")
Esempio n. 21
0
# - The average duration of the highest and lowest $\beta$’s is 50 years. 
#
# The HARK toolkit is not natively set up to accommodate stochastic time preference factors (though an extension to accommodate this would be easy).  
#
# Here, instead, we assume that different agents have different values of $\beta$ that are uniformly distributed over some range. We approximate the uniform distribution by three points.  The agents are heterogeneous _ex ante_ (and permanently).

# %% code_folding=[]
# Construct the distribution of types
from HARK.distribution import Uniform


# Specify the distribution of the discount factor
num_types = 3              # number of types we want;
DiscFac_mean   = 0.9858    # center of beta distribution 
DiscFac_spread = 0.0085    # spread of beta distribution
DiscFac_dstn = Uniform(bot=DiscFac_mean-DiscFac_spread, top=DiscFac_mean+DiscFac_spread).approx(num_types).X

BaselineType = deepcopy(KSAgent)

MyTypes = [] # initialize an empty list to hold our consumer types
for nn in range(len(DiscFac_dstn)):
    # Now create the types, and append them to the list MyTypes
    NewType = deepcopy(BaselineType)
    NewType.DiscFac = DiscFac_dstn[nn]
    NewType.seed = nn # give each consumer type a different RNG seed
    MyTypes.append(NewType)

# %% code_folding=[]
# Put all agents into the economy
KSEconomy_sim = CobbDouglasMarkovEconomy(agents = MyTypes, **KSEconomyDictionary) 
KSEconomy_sim.AggShkDstn = KSAggShkDstn # Agg shocks are the same as defined earlier