def updateSolutionTerminal(self): """ Solves the terminal period of the portfolio choice problem. The solution is trivial, as usual: consume all market resources, and put nothing in the risky asset (because you have nothing anyway). Parameters ---------- None Returns ------- None """ # Consume all market resources: c_T = m_T cFuncAdj_terminal = IdentityFunction() cFuncFxd_terminal = IdentityFunction(i_dim=0, n_dims=2) # Risky share is irrelevant-- no end-of-period assets; set to zero ShareFuncAdj_terminal = ConstantFunction(0.0) ShareFuncFxd_terminal = IdentityFunction(i_dim=1, n_dims=2) # Value function is simply utility from consuming market resources vFuncAdj_terminal = ValueFunc(cFuncAdj_terminal, self.CRRA) vFuncFxd_terminal = ValueFunc2D(cFuncFxd_terminal, self.CRRA) # Marginal value of market resources is marg utility at the consumption function vPfuncAdj_terminal = MargValueFunc(cFuncAdj_terminal, self.CRRA) dvdmFuncFxd_terminal = MargValueFunc2D(cFuncFxd_terminal, self.CRRA) dvdsFuncFxd_terminal = ConstantFunction( 0.0 ) # No future, no marg value of Share # Construct the terminal period solution self.solution_terminal = PortfolioSolution( cFuncAdj=cFuncAdj_terminal, ShareFuncAdj=ShareFuncAdj_terminal, vFuncAdj=vFuncAdj_terminal, vPfuncAdj=vPfuncAdj_terminal, cFuncFxd=cFuncFxd_terminal, ShareFuncFxd=ShareFuncFxd_terminal, vFuncFxd=vFuncFxd_terminal, dvdmFuncFxd=dvdmFuncFxd_terminal, dvdsFuncFxd=dvdsFuncFxd_terminal, )
def solve(self, Pfunc_0=None, logDGrid=None, tol=1e-5, maxIter=500, disp=False): # Initialize the norm norm = tol + 1 # Initialize Pfunc if initial guess is not provided if Pfunc_0 is None: Pfunc_0 = ConstantFunction(0.0) # Create a grid for log-dividends if one is not provided if logDGrid is None: logDGrid = self.DivProcess.getLogdGrid() # Initialize function and compute prices on the grid Pf_0 = copy(Pfunc_0) P_0 = Pf_0(logDGrid) it = 0 while norm > tol and it < maxIter: # Apply the pricing equation Pf_next = self.priceOnePeriod(Pf_0, logDGrid) # Find new prices on the grid P_next = Pf_next(logDGrid) # Measure the change between price vectors norm = np.linalg.norm(P_0 - P_next) # Update price function and vector Pf_0 = Pf_next P_0 = P_next it = it + 1 # Print iteration information if disp: print('Iter:' + str(it) + ' Norm = ' + str(norm)) if disp: if norm <= tol: print('Price function converged!') else: print('Maximum iterations exceeded!') self.EqlogPfun = Pf_0 self.EqPfun = lambda d: self.EqlogPfun(np.log(d))
def update_solution_terminal(self): """ Updates the terminal period solution and solves for optimal consumption and labor when there is no future. Parameters ---------- None Returns ------- None """ t = -1 TranShkGrid = self.TranShkGrid[t] LbrCost = self.LbrCost[t] WageRte = self.WageRte[t] bNrmGrid = np.insert( self.aXtraGrid, 0, 0.0 ) # Add a point at b_t = 0 to make sure that bNrmGrid goes down to 0 bNrmCount = bNrmGrid.size # 201 TranShkCount = TranShkGrid.size # = (7,) bNrmGridTerm = np.tile( np.reshape(bNrmGrid, (bNrmCount, 1)), (1, TranShkCount )) # Replicated bNrmGrid for each transitory shock theta_t TranShkGridTerm = np.tile( TranShkGrid, (bNrmCount, 1) ) # Tile the grid of transitory shocks for the terminal solution. (201,7) # Array of labor (leisure) values for terminal solution LsrTerm = np.minimum( (LbrCost / (1.0 + LbrCost)) * (bNrmGridTerm / (WageRte * TranShkGridTerm) + 1.0), 1.0, ) LsrTerm[0, 0] = 1.0 LbrTerm = 1.0 - LsrTerm # Calculate market resources in terminal period, which is consumption mNrmTerm = bNrmGridTerm + LbrTerm * WageRte * TranShkGridTerm cNrmTerm = mNrmTerm # Consume everything we have # Make a bilinear interpolation to represent the labor and consumption functions LbrFunc_terminal = BilinearInterp(LbrTerm, bNrmGrid, TranShkGrid) cFunc_terminal = BilinearInterp(cNrmTerm, bNrmGrid, TranShkGrid) # Compute the effective consumption value using consumption value and labor value at the terminal solution xEffTerm = LsrTerm**LbrCost * cNrmTerm vNvrsFunc_terminal = BilinearInterp(xEffTerm, bNrmGrid, TranShkGrid) vFunc_terminal = ValueFuncCRRA(vNvrsFunc_terminal, self.CRRA) # Using the envelope condition at the terminal solution to estimate the marginal value function vPterm = LsrTerm**LbrCost * CRRAutilityP(xEffTerm, gam=self.CRRA) vPnvrsTerm = CRRAutilityP_inv( vPterm, gam=self.CRRA ) # Evaluate the inverse of the CRRA marginal utility function at a given marginal value, vP vPnvrsFunc_terminal = BilinearInterp(vPnvrsTerm, bNrmGrid, TranShkGrid) vPfunc_terminal = MargValueFuncCRRA( vPnvrsFunc_terminal, self.CRRA) # Get the Marginal Value function bNrmMin_terminal = ConstantFunction( 0.0 ) # Trivial function that return the same real output for any input self.solution_terminal = ConsumerLaborSolution( cFunc=cFunc_terminal, LbrFunc=LbrFunc_terminal, vFunc=vFunc_terminal, vPfunc=vPfunc_terminal, bNrmMin=bNrmMin_terminal, )