class PortfolioConsumerFrameType(FrameAgentType, PortfolioConsumerType): """ A consumer type with a portfolio choice, using Frame architecture. A subclass of PortfolioConsumerType for now. This is mainly to keep the _solver_ logic intact. """ def __init__(self, **kwds): params = init_portfolio.copy() params.update(kwds) kwds = params # Initialize a basic consumer type PortfolioConsumerType.__init__(self, **kwds) # Initialize a basic consumer type FrameAgentType.__init__(self, self.model, **kwds) self.shocks = {} self.controls = {} self.state_now = {} def solve(self): # Some contortions are needed here to make decision rule shaped objects # out of the HARK solution objects super().solve(self) ## TODO: make this a property of FrameAgentTypes or FrameModels? self.decision_rules = {} def decision_rule_Share_from_solution(solution_t): def decision_rule_Share(Adjust, mNrm, Share): Share = np.zeros(len(Adjust)) + np.nan Share[Adjust] = solution_t.ShareFuncAdj(mNrm[Adjust]) Share[~Adjust] = solution_t.ShareFuncFxd( mNrm[~Adjust], Share[~Adjust]) return Share return decision_rule_Share def decision_rule_cNrm_from_solution(solution_t): def decision_rule_cNrm(Adjust, mNrm, Share): cNrm = np.zeros(len(Adjust)) + np.nan cNrm[Adjust] = solution_t.cFuncAdj(mNrm[Adjust]) cNrm[~Adjust] = solution_t.cFuncFxd(mNrm[~Adjust], Share[~Adjust]) return cNrm return decision_rule_cNrm self.decision_rules[('Share', )] = [ decision_rule_Share_from_solution(sol) for sol in self.solution ] self.decision_rules[('cNrm', )] = [ decision_rule_cNrm_from_solution(sol) for sol in self.solution ] # TODO: streamline this so it can draw the parameters from context def birth_aNrmNow(self, N): """ Birth value for aNrmNow """ return Lognormal( mu=self.aNrmInitMean, sigma=self.aNrmInitStd, seed=self.RNG.randint(0, 2**31 - 1), ).draw(N) # TODO: streamline this so it can draw the parameters from context def birth_pLvlNow(self, N): """ Birth value for pLvlNow """ pLvlInitMeanNow = self.pLvlInitMean + np.log( self.state_now["PlvlAgg"] ) # Account for newer cohorts having higher permanent income return Lognormal(pLvlInitMeanNow, self.pLvlInitStd, seed=self.RNG.randint(0, 2**31 - 1)).draw(N) # maybe replace reference to init_portfolio to self.parameters? model = FrameModel( [ # todo : make an aggegrate value Frame(('PermShkAgg', ), ('PermGroFacAgg', ), transition=lambda PermGroFacAgg: (PermGroFacAgg, ), aggregate=True), Frame( ('PermShk'), None, default={ 'PermShk': 1.0 }, # maybe this is unnecessary because the shock gets sampled at t = 0 # this is discretized before it's sampled transition=IndexDistribution( Lognormal.from_mean_std, { 'mean': init_portfolio['PermGroFac'], 'std': init_portfolio['PermShkStd'] }).approx(init_portfolio['PermShkCount'], tail_N=0), ), Frame( ('TranShk'), None, default={ 'TranShk': 1.0 }, # maybe this is unnecessary because the shock gets sampled at t = 0 transition=add_discrete_outcome_constant_mean( IndexDistribution(MeanOneLogNormal, { 'sigma': init_portfolio['TranShkStd'] }).approx(init_portfolio['TranShkCount'], tail_N=0), p=init_portfolio['UnempPrb'], x=init_portfolio['IncUnemp'])), Frame( ## TODO: Handle Risky as an Aggregate value ('Risky'), None, transition=IndexDistribution( Lognormal.from_mean_std, { 'mean': init_portfolio['RiskyAvg'], 'std': init_portfolio['RiskyStd'] } # seed=self.RNG.randint(0, 2 ** 31 - 1) : TODO: Seed logic ).approx(init_portfolio['RiskyCount']), aggregate=True), Frame( ('Adjust'), None, default={'Adjust': False}, transition=IndexDistribution( Bernoulli, {'p': init_portfolio['AdjustPrb']}, # seed=self.RNG.randint(0, 2 ** 31 - 1) : TODO: Seed logic ) # self.t_cycle input implied ), Frame(('Rport'), ('Share', 'Risky', 'Rfree'), transition=lambda Share, Risky, Rfree: (Share * Risky + (1.0 - Share) * Rfree, )), Frame(('PlvlAgg'), ('PlvlAgg', 'PermShkAgg'), default={'PlvlAgg': 1.0}, transition=lambda PlvlAgg, PermShkAgg: PlvlAgg * PermShkAgg, aggregate=True), Frame(('pLvl', ), ('pLvl', 'PermShk'), default={'pLvl': birth_pLvlNow}, transition=lambda pLvl, PermShk: (pLvl * PermShk, )), Frame(('bNrm', ), ('aNrm', 'Rport', 'PermShk'), transition=lambda aNrm, Rport, PermShk: (Rport / PermShk) * aNrm), Frame(('mNrm', ), ('bNrm', 'TranShk'), transition=lambda bNrm, TranShk: (bNrm + TranShk, )), Frame(('Share'), ('Adjust', 'mNrm', 'Share'), default={'Share': 0}, control=True), Frame(('cNrm'), ('Adjust', 'mNrm', 'Share'), control=True), Frame( ('U'), ('cNrm', 'CRRA'), ## Note CRRA here is a parameter not a state var transition=lambda cNrm, CRRA: (CRRAutility(cNrm, CRRA), ), reward=True), Frame(('aNrm'), ('mNrm', 'cNrm'), default={'aNrm': birth_aNrmNow}, transition=lambda mNrm, cNrm: (mNrm - cNrm, )), Frame(('aLvl'), ('aNrm', 'pLvl'), transition=lambda aNrm, pLvl: (aNrm * pLvl, )) ], init_portfolio)
aGrid = np.linspace(0,8,400) # Savings grid for EGM. # Model parameters # Parameters that need to be fixed # Relative risk aversion. This is fixed at 2 in order to mantain # the analytical solution that we use, from Carroll (2000) CRRA = 2 # Parameters that can be changed. w = 1 # Deterministic wage per period. willCstFac = 0.35 # Fraction of resources charged by lawyer for writing a will. DiscFac = 0.98 # Time-discount factor. # Define utility (and related) functions u = lambda x: CRRAutility(x,CRRA) uP = lambda x: CRRAutilityP(x, CRRA) uPinv = lambda x: CRRAutilityP_inv(x, CRRA) # Create a grid for market resources mGrid = (aGrid-aGrid[0])*1.5 mGridPlots = np.linspace(w,10*w,100) mGridPlotsC = np.insert(mGridPlots,0,0) # Transformations for value funtion interpolation vTransf = lambda x: np.exp(x) vUntransf = lambda x: np.log(x) # %% [markdown] # # The third (last) period of life #
init_parameters['PermShkCount'] = 5 init_parameters['TranShkStd'] = 3.0 init_parameters['TranShkCount'] = 5 init_parameters['RiskyAvg'] = 1.05 init_parameters['RiskyStd'] = 1.5 init_parameters['RiskyCount'] = 5 init_parameters['Rfree'] = 1.03 frames_A = [ Frame(('bNrm', ), ('aNrm', ), transition=lambda Rfree, aNrm: Rfree * aNrm), Frame(('mNrm', ), ('bNrm', 'TranShk'), transition=lambda bNrm: mNrm), Frame(('cNrm'), ('mNrm', ), control=True), Frame( ('U'), ('cNrm', 'CRRA'), ## Note CRRA here is a parameter not a state var transition=lambda cNrm, CRRA: (CRRAutility(cNrm, CRRA), ), reward=True, context={'CRRA': 2.0}), Frame(('aNrm'), ('mNrm', 'cNrm'), transition=lambda mNrm, cNrm: (mNrm - cNrm, )), ] class test_FrameModel(unittest.TestCase): def setUp(self): self.model = FrameModel(frames_A, init_parameters) def test_init(self): self.model.frames.var('aNrm')