def update(self): ''' Use primitive parameters to set basic objects. This is an extremely stripped-down version of update for CobbDouglasEconomy. Parameters ---------- none Returns ------- none ''' self.kSS = 1.0 self.MSS = 1.0 self.KtoLnow_init = self.kSS self.Rfunc = ConstantFunction(self.Rfree) self.wFunc = ConstantFunction(self.wRte) self.RfreeNow_init = self.Rfunc(self.kSS) self.wRteNow_init = self.wFunc(self.kSS) self.MaggNow_init = self.kSS self.AaggNow_init = self.kSS self.PermShkAggNow_init = 1.0 self.TranShkAggNow_init = 1.0 self.TranShkAggDstn = approxMeanOneLognormal(sigma=self.TranShkAggStd, N=self.TranShkAggCount) self.PermShkAggDstn = approxMeanOneLognormal(sigma=self.PermShkAggStd, N=self.PermShkAggCount) self.AggShkDstn = combineIndepDstns(self.PermShkAggDstn, self.TranShkAggDstn) self.AFunc = ConstantFunction(1.0)
def evalSocialOptimum(self): ''' Execute a simulation run that calculates "socially optimal" objects. ''' self.update() self.solve() self.CalcSocialOptimum = True self.initializeSim() self.simulate() self.iLvlSocOpt_histX = deepcopy(self.iLvlSocOpt_hist) self.CopaySocOpt_histX = deepcopy(self.CopaySocOpt_hist) self.LifePriceSocOpt_histX = deepcopy(self.LifePriceSocOpt_hist) self.CumLivPrb_histX = deepcopy(self.CumLivPrb_hist) self.CalcSocialOptimum = False try: Health = self.hLvlNow_hist.flatten() Weights = self.CumLivPrb_hist.flatten() Copays = self.CopaySocOpt_hist.flatten() Age = np.tile( np.reshape(np.arange(self.T_cycle), (self.T_cycle, 1)), (1, self.AgentCount)).flatten() AgeSq = Age**2. HealthSq = Health**2 Ones = np.ones_like(Health) AgeHealth = Age * Health AgeHealthSq = Age * HealthSq AgeSqHealth = AgeSq * Health AgeSqHealthSq = AgeSq * HealthSq these = np.logical_not(np.isnan(Copays)) regressors = np.transpose( np.vstack((Ones, Health, HealthSq, Age, AgeHealth, AgeHealthSq, AgeSq, AgeSqHealth, AgeSqHealthSq))) copay_model = WLS(Copays[these], regressors[these, :], weights=Weights[these]) coeffs = (copay_model.fit()).params UpperCopayFunc = ConstantFunction(1.0) LowerCopayFunc = ConstantFunction(0.01) OptimalCopayInvstFunc = [] for t in range(self.T_cycle): c0 = coeffs[0] + t * coeffs[3] + t**2 * coeffs[6] c1 = coeffs[1] + t * coeffs[4] + t**2 * coeffs[7] c2 = coeffs[2] + t * coeffs[5] + t**2 * coeffs[8] TempFunc = QuadraticFunction(c0, c1, c2) OptimalCopayInvstFunc_t = UpperEnvelope( LowerEnvelope(TempFunc, UpperCopayFunc), LowerCopayFunc) OptimalCopayInvstFunc.append(OptimalCopayInvstFunc_t) except: for t in range(self.T_cycle): OptimalCopayInvstFunc.append(ConstantFunction(1.0)) self.OptimalCopayInvstFunc = OptimalCopayInvstFunc self.delSolution()
def updateInsuranceFuncs(self): ''' Altered version of this method that makes the counterfactuals able to handle a subsidy policy that specifies a flat coinsurance rate for investment. ''' EstimationAgentType.updateInsuranceFuncs(self) if hasattr(self, 'FlatCopayInvst'): self.CopayInvstFunc = self.T_cycle * [ ConstantFunction(self.FlatCopayInvst) ] self.SameCopayForMedAndInvst = False
def updateSolutionTerminal(self): ''' Updates the terminal period solution for an aggregate shock consumer. Only fills in the consumption function and marginal value function. Parameters ---------- None Returns ------- None ''' cFunc_terminal = BilinearInterp(np.array([[0.0, 0.0], [1.0, 1.0]]), np.array([0.0, 1.0]), np.array([0.0, 1.0])) vPfunc_terminal = MargValueFunc2D(cFunc_terminal, self.CRRA) mNrmMin_terminal = ConstantFunction(0) self.solution_terminal = ConsumerSolution(cFunc=cFunc_terminal, vPfunc=vPfunc_terminal, mNrmMin=mNrmMin_terminal)
def solveConsAggShock(solution_next, IncomeDstn, LivPrb, DiscFac, CRRA, PermGroFac, aXtraGrid, BoroCnstArt, Mgrid, AFunc, Rfunc, wFunc, DeprFac): ''' Solve one period of a consumption-saving problem with idiosyncratic and aggregate shocks (transitory and permanent). This is a basic solver that can't handle borrowing (assumes liquidity constraint) or cubic splines, nor can it calculate a value function. Parameters ---------- solution_next : ConsumerSolution The solution to the succeeding one period problem. IncomeDstn : [np.array] A list containing five arrays of floats, representing a discrete approximation to the income process between the period being solved and the one immediately following (in solution_next). Order: event probabilities, idisyncratic permanent shocks, idiosyncratic transitory shocks, aggregate permanent shocks, aggregate transitory shocks. LivPrb : float Survival probability; likelihood of being alive at the beginning of the succeeding period. DiscFac : float Intertemporal discount factor for future utility. CRRA : float Coefficient of relative risk aversion. PermGroGac : float Expected permanent income growth factor at the end of this period. aXtraGrid : np.array Array of "extra" end-of-period asset values-- assets above the absolute minimum acceptable level. BoroCnstArt : float Artificial borrowing constraint; minimum allowable end-of-period asset-to- permanent-income ratio. Unlike other models, this *can't* be None. Mgrid : np.array A grid of aggregate market resourses to permanent income in the economy. AFunc : function Aggregate savings as a function of aggregate market resources. Rfunc : function The net interest factor on assets as a function of capital ratio k. wFunc : function The wage rate for labor as a function of capital-to-labor ratio k. DeprFac : float Capital Depreciation Rate Returns ------- solution_now : ConsumerSolution The solution to the single period consumption-saving problem. Includes a consumption function cFunc (linear interpolation over linear interpola- tions) and marginal value function vPfunc. ''' # Unpack next period's solution vPfuncNext = solution_next.vPfunc mNrmMinNext = solution_next.mNrmMin # Unpack the income shocks ShkPrbsNext = IncomeDstn[0] PermShkValsNext = IncomeDstn[1] TranShkValsNext = IncomeDstn[2] PermShkAggValsNext = IncomeDstn[3] TranShkAggValsNext = IncomeDstn[4] ShkCount = ShkPrbsNext.size # Make the grid of end-of-period asset values, and a tiled version aNrmNow = np.insert(aXtraGrid, 0, 0.0) aNrmNow_tiled = np.tile(aNrmNow, (ShkCount, 1)) aCount = aNrmNow.size # Make tiled versions of the income shocks ShkPrbsNext_tiled = (np.tile(ShkPrbsNext, (aCount, 1))).transpose() PermShkValsNext_tiled = (np.tile(PermShkValsNext, (aCount, 1))).transpose() TranShkValsNext_tiled = (np.tile(TranShkValsNext, (aCount, 1))).transpose() PermShkAggValsNext_tiled = (np.tile(PermShkAggValsNext, (aCount, 1))).transpose() TranShkAggValsNext_tiled = (np.tile(TranShkAggValsNext, (aCount, 1))).transpose() # Loop through the values in Mgrid and calculate a linear consumption function for each cFuncBaseByM_list = [] BoroCnstNat_array = np.zeros(Mgrid.size) mNrmMinNext_array = mNrmMinNext(AFunc(Mgrid) * (1 - DeprFac)) for j in range(Mgrid.size): MNow = Mgrid[j] AaggNow = AFunc(MNow) # Calculate returns to capital and labor in the next period kNext_array = AaggNow * (1 - DeprFac) / ( PermGroFac * PermShkAggValsNext_tiled * TranShkAggValsNext_tiled) kNextEff_array = kNext_array / TranShkAggValsNext_tiled R_array = Rfunc(kNextEff_array) # Interest factor on aggregate assets Reff_array = R_array / LivPrb # Effective interest factor on individual assets *for survivors* wEff_array = wFunc( kNextEff_array ) * TranShkAggValsNext_tiled # Effective wage rate (accounts for labor supply) PermShkTotal_array = PermGroFac * PermShkValsNext_tiled * PermShkAggValsNext_tiled # total / combined permanent shock Mnext_array = kNext_array * (R_array + DeprFac) + wEff_array # Find the natural borrowing constraint for this capital-to-labor ratio aNrmMin_candidates = PermGroFac * PermShkValsNext * PermShkAggValsNext / Reff_array[:, 0] * ( mNrmMinNext_array[j] - wEff_array[:, 0] * TranShkValsNext) aNrmMin = np.max(aNrmMin_candidates) BoroCnstNat = aNrmMin BoroCnstNat_array[j] = BoroCnstNat # Calculate market resources next period (and a constant array of capital-to-labor ratio) mNrmNext_array = Reff_array * ( aNrmNow_tiled + aNrmMin) / PermShkTotal_array + TranShkValsNext_tiled * wEff_array # Find marginal value next period at every income shock realization and every aggregate market resource gridpoint vPnext_array = Reff_array * PermShkTotal_array**(-CRRA) * vPfuncNext( mNrmNext_array, Mnext_array) # Calculate expectated marginal value at the end of the period at every asset gridpoint EndOfPrdvP = DiscFac * LivPrb * PermGroFac**(-CRRA) * np.sum( vPnext_array * ShkPrbsNext_tiled, axis=0) # Calculate optimal consumption from each asset gridpoint, and construct a linear interpolation cNrmNow = EndOfPrdvP**(-1.0 / CRRA) mNrmNow = (aNrmNow + aNrmMin) + cNrmNow c_for_interpolation = np.insert( cNrmNow, 0, 0.0) # Add liquidity constrained portion m_for_interpolation = np.insert(mNrmNow - BoroCnstNat, 0, 0.0) cFuncBase_j = LinearInterp(m_for_interpolation, c_for_interpolation) # Add the M-specific consumption function to the list cFuncBaseByM_list.append(cFuncBase_j) # Construct the overall unconstrained consumption function by combining the M-specific functions BoroCnstNat = LinearInterp(np.insert(Mgrid, 0, 0.0), np.insert(BoroCnstNat_array, 0, 0.0)) cFuncBase = LinearInterpOnInterp1D(cFuncBaseByM_list, Mgrid) cFuncUnc = VariableLowerBoundFunc2D(cFuncBase, BoroCnstNat) # Make the constrained consumption function and combine it with the unconstrained component cFuncCnst = BilinearInterp(np.array([[0.0, 0.0], [1.0, 1.0]]), np.array([BoroCnstArt, BoroCnstArt + 1.0]), np.array([0.0, 1.0])) cFuncNow = LowerEnvelope2D(cFuncUnc, cFuncCnst) # Make the minimum m function as the greater of the natural and artificial constraints mNrmMinNow = UpperEnvelope(BoroCnstNat, ConstantFunction(BoroCnstArt)) # Construct the marginal value function using the envelope condition vPfuncNow = MargValueFunc2D(cFuncNow, CRRA) # Pack up and return the solution solution_now = ConsumerSolution(cFunc=cFuncNow, vPfunc=vPfuncNow, mNrmMin=mNrmMinNow) return solution_now