Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
80 changes: 75 additions & 5 deletions HARK/ConsumptionSaving/ConsPortfolioModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def update_solution_terminal(self):
None
"""
# Consume all market resources: c_T = m_T
cFuncAdj_terminal = IdentityFunction()
cFuncAdj_terminal = LinearInterp([0.0, 1.0], [0.0, 1.0])
cFuncFxd_terminal = IdentityFunction(i_dim=0, n_dims=2)

# Risky share is irrelevant-- no end-of-period assets; set to zero
Expand Down Expand Up @@ -244,6 +244,8 @@ def update_solution_terminal(self):
dvdsFuncFxd=dvdsFuncFxd_terminal,
)

self.solution_terminal.EndOfPrdShareFunc = ShareFuncAdj_terminal

def update_ShareGrid(self):
"""
Creates the attribute ShareGrid as an evenly spaced grid on [0.,1.], using
Expand Down Expand Up @@ -822,6 +824,74 @@ def make_ShareFuncAdj(self):
Construct the risky share function when the agent can adjust
"""

# Share function on aGrid

if self.zero_bound:
aNrm_temp = np.append(0.0, self.aNrmGrid)
share_temp = np.append(self.ShareLimit, self.Share_now)
else:
aNrm_temp = self.aNrmGrid
share_temp = self.Share_now

self.EndOfPrdShareFunc = LinearInterp(
aNrm_temp, share_temp, intercept_limit=self.ShareLimit, slope_limit=0.0
)

# alternative share functions from linear approximation

# get next period's consumption and share function
cFunc_next = self.solution_next.cFuncAdj
sFunc_next = self.solution_next.EndOfPrdShareFunc

def premium(shock):
"""
Used to evaluate mean and variance of equity premium.
"""
r_diff = shock - self.Rfree

return r_diff, r_diff ** 2

prem_mean, prem_var = calc_expectation(self.RiskyDstn, premium)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alanlujan91 not sure if this is a bug given your notation, but I think that what your are calling prem_var is not the variance of the premium, but rather E[premium^2].

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be interesting to see what happens when you make the maximum amount of assets something much larger, like 2000 or 10000 or something. Out that far, the consumption function is essentially linear, so the error coming from the approximation's assumption that $c^{''}$ is zero should be inconsequential. If the orange does converge to the blue, that would suggest that maybe using the 2nd order Taylor approximation would make the results considerably closer for small values of wealth. If orange does not converge to blue, I'd guess that there's a bug somewhere.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Mv77 you're right, I have called this prem_sqrd instead.


def c_nrm_and_deriv(shocks, a_nrm):
"""
Used to calculate expected consumption and MPC given today's savings,
assuming that today's risky share is the same as it would be tomorrow
with that same level of savings.
"""
p_shk = shocks[0] * self.PermGroFac
share = sFunc_next(a_nrm)
r_diff = shocks[2] - self.Rfree
r_port = self.Rfree + r_diff * share
m_nrm_next = a_nrm * r_port / p_shk + shocks[1]

c_next, cP_next = cFunc_next.eval_with_derivative(m_nrm_next)

return c_next, cP_next

c_vals = calc_expectation(self.ShockDstn, c_nrm_and_deriv, self.aNrmGrid)

c_vals = c_vals[:, :, 0]
c_next = c_vals[0]
cP_next = c_vals[1]

MPC = cP_next * self.aNrmGrid / c_next

approx_share = prem_mean / (self.CRRA * MPC * prem_var)

# clip at 0 and 1, although we know the Share limit we
# want to see what the approximation would give us
approx_share = np.clip(approx_share, 0, 1)

self.ApproxShareFunc = LinearInterp(
self.aNrmGrid,
approx_share,
intercept_limit=self.ShareLimit,
slope_limit=0.0,
)

# Share function for mGrid

if self.zero_bound:
Share_lower_bound = self.ShareLimit
else:
Expand Down Expand Up @@ -978,6 +1048,9 @@ def make_porfolio_solution(self):
AdjPrb=self.AdjustPrb,
)

self.solution.EndOfPrdShareFunc = self.EndOfPrdShareFunc
self.solution.ApproxShareFunc = self.ApproxShareFunc

def solve(self):
"""
Solve the one period problem for a portfolio-choice consumer.
Expand Down Expand Up @@ -1319,10 +1392,7 @@ def add_SequentialShareFuncAdj(self, solution):
Share_now = self.Share_now

self.SequentialShareFuncAdj_now = LinearInterp(
aNrm_temp,
Share_now,
intercept_limit=self.ShareLimit,
slope_limit=0.0,
aNrm_temp, Share_now, intercept_limit=self.ShareLimit, slope_limit=0.0,
)

solution.SequentialShareFuncAdj = self.SequentialShareFuncAdj_now
Expand Down
Loading