In [ ]:
"""
Consumption-saving problem with two assets and non-convex adjustment costs
## Fields
#### Parameters
- `γ::Float64` : parameter on CRRA utility
- `ρ::Float64` : discount factor
- `ξ::Float64` : automatic deposit
- `σ::Float64` : frisch elasticity of labor supply
- `ψ::Float64` : disutility of labor
#### Prices
- `rᴬ::Float64` : interest rate on illiquid asset
- `rᴮ::Float64` : interest rate for savings in liquid asset
- `wedge::Float64` : interest rate for borrowing in liquid asset
- `w::Float64` : wage rate
#### Tax
- `τ::Float64` : tax on income
- `T::Float64` : Lump-sum transfer
#### Cost Function
- `χ₀::Float64` :
- `χ₁::Float64` :
"""
type TwoAssetsProb
γ::Float64 # CRRA utility with parameter γ
ρ::Float64 # discount rate
σ::Float64
ψ::Float64
ξ::Float64 # automatic deposit on illiquid asset
rᴬ ::Float64 # ret on illiquid asset
rᴮ::Float64 # ret on liq asset
wedge::Float64
w ::Float64 # wage rate
τ::Float64
T::Float64
χ₀::Float64 # parameters on adjustment cost
χ₁::Float64
end
In [ ]:
type SolutionExp
## Solution
V::Vector{Vector{Float64}} # Value function
g::Vector{Vector{Float64}} # Density over state space
c::Array{Float64,3} # Optimal consumption
sc::Array{Float64,3} # Savings without deposit
d::Array{Float64,3} # Optimal deposit flow
## Matrices to be filled
A ::Vector{Base.SparseMatrix.SparseMatrixCSC{Float64, Int}} # used on HJB to compute vⁿ⁺¹
Au::Vector{Base.SparseMatrix.SparseMatrixCSC{Float64, Int}} # used for KFE to compute transition dynamics
end
"""
Specification for the Implicit-Explicit Finite Difference method
"""
type FDExp
## GRID INFO
b ::Vector{Float64}
Δbgrid ::Vector{Float64}
ΔTbgrid::Vector{Float64}
rbdrift::Vector{Float64}
netbinc::Matrix{Float64}
a ::Vector{Float64}
Δagrid ::Vector{Float64}
ΔTagrid::Vector{Float64}
radrift::Vector{Float64}
netainc::Matrix{Float64}
ΔTab::Vector{Float64}
## LaborSupply decisions
ℓsupply::Vector{Float64}
ℓutilgrid::Vector{Float64}
## Δ in finite difference scheme
invΔ::Float64
invΔᴷ::Float64
## Stochastic Information
z::Vector{Float64}
λ::Matrix{Float64}
λdiag::Vector{Float64}
λoff::Matrix{Float64}
## Solution
sol::SolutionExp
## Storage
btilde ::Vector{Vector{Float64}} # RHS of hjb
B ::Vector{Base.SparseMatrix.SparseMatrixCSC{Float64, Int}} # storage matrix
end
This is useful for bigger projects
In [ ]:
function Base.show(io::IO, fd::FDExp)
fd.Δbgrid[2]-fd.Δbgrid[1] == 0 ? (binfo = "uniform ") : (binfo = "non-uniform ")
fd.Δagrid[2]-fd.Δagrid[1] == 0 ? (ainfo = "uniform ") : (ainfo = "non-uniform ")
@printf io "\n"
@printf io " Explicit-Implicit Finite Difference Method\n"
@printf io "\n"
@printf io " Grids \n"
@printf io " ------- \n"
@printf io " %12sb: %3d points in [% .0f, %.0f]\n" binfo length(fd.b) fd.b[1] fd.b[end]
@printf io " %12sa: %3d poitns in [% .0f, %.0f]\n" ainfo length(fd.a) fd.a[1] fd.a[end]
end
In [70]:
#== INCLUDE files ==#
include("aggregate.jl")
include("twoassets.jl")
include("solveHJB.jl")
include("solveKFE.jl")
Out[70]:
Let's create an TwoAssetProblem instance
In [71]:
#== Instance of prices ==#
pr = Prices(0.0, 0.04, 0.03, 0.09, 8.0)
#== Instance of TwoAssetProblem ==#
twoap = TwoAssetsProb2(pr; γ = 2.0, ρ = 0.06, ξ = 0.10, χ₀ = 0.08, χ₁= 3.0, τ = 0.0, T = 0.0)
Out[71]:
With that I will create the Finite Difference specification
In [79]:
#== Create and FiniteDifference Structure ==#
fde = FDExp(twoap; z = [.8, 1.3], λ = [-1/3 1/3; 1/3 -1/3],
fixedΔa = true, fixedΔb = false, bn = 100, bmin = -2.0, bmax = 40.0, an =70, amax = 70.0, invΔᴷ = 0.05)
Out[79]:
The solve_hjb function will use information from
twoap::TwoAssetProblem
fde::FDExpl
and save solution on
fde.sol::SolutionExp
Why is useful to separate these? Further in the code, when we are doing transitional dynamics, I will maintain grid structure while solution will change for each period. Moreover I will need to save all SolutionExp before computing the dynamics.
In [80]:
#== Solve the HJB equation ==#
solve_hjb!(twoap, fde, fde.sol)
In [81]:
#== Solve the KF equation ==#
solve_fp!(fde, fde.sol, maxit = 4000, tolFK = 1e-9)
Out[81]:
In [1]:
using PlotlyJS
In [82]:
sol = fde.sol
c = sol.c; d = sol.d; sc = sol.sc
b = fde.b; a = fde.a; z = fde.z;
an = length(a)
bn = length(b)
zn = length(z)
netainc = fde.netainc
# agrid, bgrid = meshgrid(a,b)
#== Consumption 2D ==#
tcons = Any[]
for ai in 1:10:an
push!(tcons,scatter(;x=fde.b, y=c[:,ai,1], name = "Illiquid level $(round(a[ai],1))") )
end
#== Deposits 2D ==#
tdep = Any[]
for ai in 1:10:an
push!(tdep,scatter(;x=fde.b, y=d[:,ai,2], name = "Illiquid level $(round(a[ai],1))") )
end
lcon = Layout(;title="Consumption Low state",
xaxis_range=-2.0, xaxis_title="Liquid asset",
yaxis_title="Consumption",
xaxis_showgrid=true, yaxis_showgrid=true,
legend_y=0.0, legend_x=1.01)
Out[82]:
In [83]:
lcons = Layout(;title="Consumption Low state",
xaxis_range=-2.0, xaxis_title="Liquid asset",
yaxis_title="Consumption",
xaxis_showgrid=true, yaxis_showgrid=true,
legend_y=0.0, legend_x=1.01)
plot([tcons...], lcons)
Out[83]:
In [84]:
ldep = Layout(;title="Deposit High state",
xaxis_range=-2.0, xaxis_title="Liquid asset",
yaxis_title="Deposit flow",
xaxis_showgrid=true, yaxis_showgrid=true,
legend_y=0.0, legend_x=1.01)
plot([tdep...], l)
Out[84]:
In [87]:
include("main_fig.jl");
#== Policies ==#
# fig_pol(fde)
#== Distributions ==#
fig_dens(fde)