Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WealthPortfolioConsumerType uses constructors #1498

Merged
merged 1 commit into from
Sep 20, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 147 additions & 10 deletions HARK/ConsumptionSaving/ConsWealthPortfolioModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import numpy as np
from HARK.ConsumptionSaving.ConsPortfolioModel import (
PortfolioConsumerType,
init_portfolio,
PortfolioSolution,
make_portfolio_solution_terminal,
)
from HARK.distribution import expected
from HARK.interpolation import (
Expand All @@ -14,11 +14,22 @@
MargValueFuncCRRA,
ValueFuncCRRA,
)
from HARK.Calibration.Assets.AssetProcesses import (
make_lognormal_RiskyDstn,
combine_IncShkDstn_and_RiskyDstn,
calc_ShareLimit_for_CRRA,
)
from HARK.Calibration.Income.IncomeProcesses import (
construct_lognormal_income_process_unemployment,
get_PermShkDstn_from_IncShkDstn,
get_TranShkDstn_from_IncShkDstn,
)
from HARK.ConsumptionSaving.ConsRiskyAssetModel import (
make_simple_ShareGrid,
)
from HARK.rewards import UtilityFuncCRRA
from HARK.utilities import NullFunc
from HARK.utilities import NullFunc, make_assets_grid


import numpy as np
from HARK.interpolation import LinearInterp


Expand Down Expand Up @@ -100,6 +111,129 @@ def __call__(self, omega):
return np.nan_to_num(chi)


# Trivial constructor function
def make_ChiFromOmega_function(CRRA, WealthShare, ChiFromOmega_N, ChiFromOmega_bound):
return ChiFromOmegaFunction(
CRRA, WealthShare, N=ChiFromOmega_N, z_bound=ChiFromOmega_bound
)


###############################################################################

# Make a dictionary of constructors for the wealth-in-utility portfolio choice consumer type
WealthPortfolioConsumerType_constructors_default = {
"IncShkDstn": construct_lognormal_income_process_unemployment,
"PermShkDstn": get_PermShkDstn_from_IncShkDstn,
"TranShkDstn": get_TranShkDstn_from_IncShkDstn,
"aXtraGrid": make_assets_grid,
"RiskyDstn": make_lognormal_RiskyDstn,
"ShockDstn": combine_IncShkDstn_and_RiskyDstn,
"ShareLimit": calc_ShareLimit_for_CRRA,
"ShareGrid": make_simple_ShareGrid,
"ChiFunc": make_ChiFromOmega_function,
"solution_terminal": make_portfolio_solution_terminal,
}

# Default parameters to make IncShkDstn using construct_lognormal_income_process_unemployment
WealthPortfolioConsumerType_IncShkDstn_default = {
"PermShkStd": [0.1], # Standard deviation of log permanent income shocks
"PermShkCount": 7, # Number of points in discrete approximation to permanent income shocks
"TranShkStd": [0.1], # Standard deviation of log transitory income shocks
"TranShkCount": 7, # Number of points in discrete approximation to transitory income shocks
"UnempPrb": 0.05, # Probability of unemployment while working
"IncUnemp": 0.3, # Unemployment benefits replacement rate while working
"T_retire": 0, # Period of retirement (0 --> no retirement)
"UnempPrbRet": 0.005, # Probability of "unemployment" while retired
"IncUnempRet": 0.0, # "Unemployment" benefits when retired
}

# Default parameters to make aXtraGrid using make_assets_grid
WealthPortfolioConsumerType_aXtraGrid_default = {
"aXtraMin": 0.001, # Minimum end-of-period "assets above minimum" value
"aXtraMax": 100, # Maximum end-of-period "assets above minimum" value
"aXtraNestFac": 1, # Exponential nesting factor for aXtraGrid
"aXtraCount": 200, # Number of points in the grid of "assets above minimum"
"aXtraExtra": None, # Additional other values to add in grid (optional)
}

# Default parameters to make RiskyDstn with make_lognormal_RiskyDstn (and uniform ShareGrid)
WealthPortfolioConsumerType_RiskyDstn_default = {
"RiskyAvg": 1.08, # Mean return factor of risky asset
"RiskyStd": 0.18362634887, # Stdev of log returns on risky asset
"RiskyCount": 5, # Number of integration nodes to use in approximation of risky returns
}

WealthPortfolioConsumerType_ShareGrid_default = {
"ShareCount": 25 # Number of discrete points in the risky share approximation
}

# Default parameters to make ChiFunc with make_ChiFromOmega_function
WealthPortfolioConsumerType_ChiFunc_default = {
"ChiFromOmega_N": 501, # Number of gridpoints in chi-from-omega function
"ChiFromOmega_bound": 15, # Highest gridpoint to use for it
}

# Make a dictionary to specify a risky asset consumer type
WealthPortfolioConsumerType_solving_default = {
# BASIC HARK PARAMETERS REQUIRED TO SOLVE THE MODEL
"cycles": 1, # Finite, non-cyclic model
"T_cycle": 1, # Number of periods in the cycle for this agent type
"constructors": WealthPortfolioConsumerType_constructors_default, # See dictionary above
# PRIMITIVE RAW PARAMETERS REQUIRED TO SOLVE THE MODEL
"CRRA": 5.0, # Coefficient of relative risk aversion
"Rfree": 1.03, # Return factor on risk free asset
"DiscFac": 0.90, # Intertemporal discount factor
"LivPrb": [0.98], # Survival probability after each period
"PermGroFac": [1.01], # Permanent income growth factor
"BoroCnstArt": 0.0, # Artificial borrowing constraint
"WealthShare": 0.5, # Share of wealth in Cobb-Douglas aggregator in utility function
"WealthShift": 0.1, # Shifter for wealth in utility function
"DiscreteShareBool": False, # Whether risky asset share is restricted to discrete values
"vFuncBool": False, # Whether to calculate the value function during solution
"CubicBool": False, # Whether to use cubic spline interpolation when True
# (Uses linear spline interpolation for cFunc when False)
"AdjustPrb": 1.0, # Probability that the agent can update their risky portfolio share each period
"sim_common_Rrisky": True, # Whether risky returns have a shared/common value across agents
}
WealthPortfolioConsumerType_simulation_default = {
# PARAMETERS REQUIRED TO SIMULATE THE MODEL
"AgentCount": 10000, # Number of agents of this type
"T_age": None, # Age after which simulated agents are automatically killed
"aNrmInitMean": 0.0, # Mean of log initial assets
"aNrmInitStd": 1.0, # Standard deviation of log initial assets
"pLvlInitMean": 0.0, # Mean of log initial permanent income
"pLvlInitStd": 0.0, # Standard deviation of log initial permanent income
"PermGroFacAgg": 1.0, # Aggregate permanent income growth factor
# (The portion of PermGroFac attributable to aggregate productivity growth)
"NewbornTransShk": False, # Whether Newborns have transitory shock
# ADDITIONAL OPTIONAL PARAMETERS
"PerfMITShk": False, # Do Perfect Foresight MIT Shock
# (Forces Newborns to follow solution path of the agent they replaced if True)
"neutral_measure": False, # Whether to use permanent income neutral measure (see Harmenberg 2021)
}

# Assemble the default dictionary
WealthPortfolioConsumerType_default = {}
WealthPortfolioConsumerType_default.update(WealthPortfolioConsumerType_solving_default)
WealthPortfolioConsumerType_default.update(
WealthPortfolioConsumerType_simulation_default
)
WealthPortfolioConsumerType_default.update(
WealthPortfolioConsumerType_aXtraGrid_default
)
WealthPortfolioConsumerType_default.update(
WealthPortfolioConsumerType_ShareGrid_default
)
WealthPortfolioConsumerType_default.update(
WealthPortfolioConsumerType_IncShkDstn_default
)
WealthPortfolioConsumerType_default.update(
WealthPortfolioConsumerType_RiskyDstn_default
)
WealthPortfolioConsumerType_default.update(WealthPortfolioConsumerType_ChiFunc_default)
init_wealth_portfolio = WealthPortfolioConsumerType_default


class WealthPortfolioConsumerType(PortfolioConsumerType):
time_inv_ = deepcopy(PortfolioConsumerType.time_inv_)
time_inv_ = time_inv_ + ["WealthShare", "WealthShift", "ChiFunc"]
Expand All @@ -114,10 +248,18 @@ def __init__(self, **kwds):

self.solve_one_period = solve_one_period_WealthPortfolio

def update(self):
super().update()
self.update_ChiFunc()

def update_ChiFunc(self):
if self.WealthShare == 0.0:
self.ChiFunc = None
else:
self.ChiFunc = ChiFromOmegaFunction(self.CRRA, self.WealthShare)
self.construct("ChiFunc")


###############################################################################


def utility(c, a, CRRA, share=0.0, intercept=0.0):
Expand Down Expand Up @@ -502,8 +644,3 @@ def solve_one_period_WealthPortfolio(
vFuncAdj=vFuncNow,
)
return solution_now


init_wealth_portfolio = init_portfolio.copy()
init_wealth_portfolio["WealthShare"] = 0.5
init_wealth_portfolio["WealthShift"] = 0.1
Loading