Go back to the Main.ipynb notebook.

Including structs and related constructors¶

Input¶

We introduce the structure Parameters, which is an immutable struct containing the parameters of the model and of the resolution.

Structure¶

In [1]:
mutable struct Params{T<:Real,T1<:Function,T2<:Function,T3<:Function,T4<:Function,I<:Int64}
    β::T      # discount factor
    α::T      # capital share in the Cobb-Douglas production function
    δ::T      # capital depreciation
    γ::T     # inverse of consumption IES (needed for Dynare only)
    θ::T      # Curvature of the public good utility function
    τ::T      # progressitivity
    Tt::T     # transfers
    #=
        *** utility functions ***
    =#
    u::T1        # utility function for consumption
    u′::T2       # inverse of u
    inv_u′::T3   # derivative of u
    u′′::T4      # second-order derivative of u 
    
    #=
        *** grid for asset choices ***
    =#
    na    ::I         # number of grid points
    a_min ::T         # min asset holdings
    aGrid ::Vector{T} # grid for asset choices

    #=
        *** productivity process ***
    =#
    ny    ::I         # number of productivity states
    ys    ::Vector{T} # productivity states  
    Πy    ::Matrix{T} # transition matrix 
    Sy    ::Vector{T} # productivity distribution 
end;

Constructor¶

Besides the natural constructor, we introduce a special constructor that can be seen as a calibration device.

In [2]:
function Params(
    KsY::T,   # Capital-to-output ratio. Used to calibrate β and χ 
              # by assuming βR=1 at the steady state and assuming an 
              # aggregate labor supply normalized to 1/3
    α::T,     # capital share in the Cobb Douglas prod. function. 
    δ::T,     # capital depreciation
    γ::T,     # inverse of consumption IES
    θ::T,     # curvature of the public good utility function
    τ::T,     # labor taxprogressitivy
    na::I,    # number of grid points
    a_min::T, # min asset holdings
    a_max::T, # max asset holdings    
    curv_a::T,# curvature of the exponential grid  
    ny::I,    # nb of productivity levels
    ρy::T,    # annual persistence of the productivity process, 
              # assuming it is an AR(1). It is then discretized at 
              # a quarterly frequency using the Rouwenhorst (1995)
              # procedure (run in when callling the constructor).
    σy::T     # annual standard deviation of the productivity process,
              # also used in the Rouwenhorst procedure. 
    ) where {T<:Real,I<:Int}
    
    #=
        *** Constructing production parameters ***
    =#
    β = (one(T) + α/KsY - δ)^(-one(T))
    R = one(T)/β #  before-tax gross interest rate
    w = (one(T)-α) * ((R - (one(T)-δ))/α)^(α/(α-one(T)))
    L = 1.0
    K0 = ((R-1 + δ)/(α*L^(1-α)))^(1 /(α-1)) #capital
    Y0 = K0^α*L^(1-α) #output
    Tt =  - τ*Y0
    
    #=
        *** Constructing utility functions ***
    =#
    u = c::T -> (γ ≈ one(T)) ? log.(c) : (c.^(one(T)-γ)-one(T))./(one(T)-γ)::T
    u′ = c::T -> c.^(-γ)::T
    inv_u′ = up::T -> up.^(-one(T)/γ)::T    
    u′′ = c::T -> -γ*c.^(-γ-one(T))::T
    
    #=
        *** Constructing the asset grid ***
    =#    
    aGrid = a_min .+ (a_max-a_min)*(range(0.0, 1.0, length=na)).^curv_a
    
    #=
        *** Constructing the productivity process ***
    =#
    mc    =  rouwenhorst(ny,ρy,σy)
    Trans = collect(mc.p')
    Trans[findall(x->x<=5*10^-5,Trans)] .= zero(Trans[1,1])
    for i = 1:ny
        Trans[i,i] += one(Trans[1,1]) - sum(Trans,dims=1)[i]
    end
    Sy  = (Trans^100000)[:,1]
    
    endow = exp.(mc.state_values)
    ys = endow./dot(Sy,endow) # ensuring L=1
    
    # return the Params using the natural constructor 
    return Params{T,typeof(u),typeof(u′),typeof(inv_u′),
                    typeof(u′′),I}(
        β,α,δ,γ,θ,τ,Tt,
        u,u′,inv_u′,u′′,
        na,a_min,aGrid,
        ny,ys,Trans',Sy)
end;

The following constructor is the same as before but with keyword arguments.

In [3]:
function Params(;
    KsY::T,
    α::T,
    δ::T,
    γ::T,
    θ::T,
    τ::T,
    na::I, 
    a_min::T, 
    a_max::T,     
    curv_a::T,
    ny::I,
    ρy::T, 
    σy::T
    ) where {T<:Real,I<:Int}
    Params(KsY,α,δ,γ,θ,τ,na,a_min,a_max,curv_a,ny,ρy,σy)
end;

Output of the Aiyagari model¶

We introduce the structure AiyagariSolution, which is a mutable struct containing the model solution.

Structure¶

In [4]:
mutable struct AiyagariSolution{T<:Real,I<:Integer}    
    ga::Matrix{T} # policy function for savings on the asset grid
    gc::Matrix{T} # policy function for consumption on the asset grid
    R::T          # post-tax gross interest rate
    w::T          # post-tax wage rate
    A::T          # aggregate savings
    C::T          # aggregate consumption
    K::T          # aggregate capital
    L::T          # aggregate labor supply (in efficient units)
    G::T          # public spending
    Y::T          # GDP
    B::T          # public debt
    transitMat::SparseMatrixCSC{T,I}
                  # transition matrix from one pair 
                  # (asset x productivity) to another
    stationaryDist::Matrix{T}
                  # stationary distribution over the product grid
                  # (asset x productivity)
    residEuler::Matrix{T}
                  # Euler equation residuals
end;

Constructor¶

We introduce a construtor that enables to initialize the solution structure for a given Params input.

In [5]:
function AiyagariSolution(p::Params{T,T1,T2,T3,T4,I}) where {T<:Real,
            T1<:Function,T2<:Function,T3<:Function,
            T4<:Function,I<:Int64}
    @unpack β,α,δ,u′,θ,na,aGrid,ny,ys = p
    R = one(T)/β #  before-tax gross interest rate
    w = (one(T)-α) * ((R - (one(T)-δ))/α)^(α/(α-one(T)))
    
    
    cs = repeat(ys', outer=(na,1))

    as = repeat(aGrid, outer=(1,ny))
    L  = one(T)
    A  = sum(as)
    return AiyagariSolution{T,I}(as,cs,R,w,A,A,A,L,
                                 zero(T),A*L,zero(T),
                                 spzeros(T, I, na*ny,na*ny), 
                                 fill(one(T)/(na*ny), na,ny), 
                                 zeros(T,na,ny))
end;

Truncation¶

Structures¶

We consider three structures for the Truncation:

  • Allocation_trunc containing the allocations at the truncated history level (as well as sizes and transition matrix);
  • ξs containing the various ξs (residual heterogeneity parameters);
  • Lagrange_mult containing Lagrange mutipliers of the Ramsey program;
  • Truncation containing the three previous structures.
In [6]:
struct Allocation_trunc{I<:Integer,T<:Real}
    S_h::Vector{T}       # size of truncated histories
    Π_h::SparseMatrixCSC{T,I}# transition matrix for histories
    y0_h::Vector{T}      # current productivity levels
    a_beg_h::Vector{T}   # beginning-of-period wealth per history and per capita
    a_end_h::Vector{T}   # end-of-period wealth per history and per capita
    c_h::Vector{T}       # consumption per history and per capita
    u_h::Vector{T}       # utility of consumption per history and per capita
    u′_h::Vector{T}      # marginal utility of consumption per history and per capita
    u′′_h::Vector{T}     # second-order derivative of utility of consumption per history and per capita
    resid_E_h::Vector{T} # Euler Lagrange multiplier at the history level
    nb_cc_h::I           # nb of credit constrained histories
    ind_cc_h::Vector{I}  # indices of credit constrained histories
end

struct ξs_struct{T<:Real}# (residual heterogeneity parameters)
    ξu0::Vector{T}       # corresponds to u
    ξu1::Vector{T}       # corresponds to u′
    ξu2::Vector{T}       # corresponds to u′′
end  

struct Lagrange_mult{T<:Real}
    λ::Array{T,1}        # Lagrange multiplier on Euler equation
    λt::Array{T,1}       # past Lagrange multiplier on Euler equation
    ψh::Array{T,1}       # social valuation of liquidity
    Φ::Array{T,1}        #  
end

struct Truncation{I<:Integer,T<:Real}
    N::I             # truncation length
    Ntot::I          # nb of postive-size truncated histories
    ind_h::Vector{I} # vector of indices of postive-size truncated histories
    allocation_trunc::Allocation_trunc{I,T}
                     # truncated allocation (see above)
    ξs::ξs_struct{T} # residual heterogeneity parameters (see above)
    lagrange_mult::Lagrange_mult{T}
    θ::T             # Curvature of the public good utility function
                     # (may be endogenous)
end;

Constructors¶

These constructors are only meant to provide constructor with keywords.

In [7]:
function Allocation_trunc(;S_h::Vector{T},Π_h::SparseMatrixCSC{T,I},y0_h::Vector{T},
        a_beg_h::Vector{T},a_end_h::Vector{T},c_h::Vector{T},u_h::Vector{T},u′_h::Vector{T},u′′_h::Vector{T},
        resid_E_h::Vector{T},
        nb_cc_h::I,ind_cc_h::Vector{I}) where{I<:Integer,T<:Real}
    Allocation_trunc{I,T}(S_h,Π_h,y0_h,a_beg_h,a_end_h,c_h,u_h,u′_h,u′′_h,
            resid_E_h, nb_cc_h,ind_cc_h)    
end

function ξs_struct(;ξu0::Vector{T},ξu1::Vector{T},ξu2::Vector{T}) where{T<:Real}
    ξs_struct{T}(ξu0,ξu1,ξu2)
end  

function Lagrange_mult(;λ::Vector{T},λt::Vector{T}, ψh::Vector{T},Φ::Vector{T}) where {T<:Real}
    Lagrange_mult{T}(λ,λt,ψh,Φ)
end

function Truncation(;N::I,Ntot::I,ind_h::Vector{I},
        allocation_trunc::Allocation_trunc{I,T},ξs::ξs_struct{T},
        lagrange_mult::Lagrange_mult{T},θ::T) where {I<:Integer,T<:Real}
    Truncation{I,T}(N,Ntot,ind_h,allocation_trunc,ξs,lagrange_mult,θ)
end;

Dynare specific structure¶

Unfortunately, we cannot transfer greek letter to Matlab on which relies Dynare. For this reason, we define a specific object without greek letters, which will consist in a translation of the structure Truncation.

In [8]:
struct Truncation_d{T <: Real,I <: Integer} #be careful the following structure store information by bin (and not per capita). Divide by the size of the bin to have per capita terms    
    N::I #lenght of the truncation
    ns::I #number of states
    Nbin::I #number of bins
    R::T
    w::T
    TT::T
    A::T
    B::T
    states::Array{T,1}
    Transv::Array{T,1}
    Sp::Array{T,1} #size of each bin
    abp::Array{T,1}
    aep::Array{T,1}
    lb::Array{T,1}
    cp::Array{T,1}
    Ucv::Array{T,1} #vector of marginal utilities (before multiplication by xsip) by bin
    Matab::Matrix{T} #transition matrix
    Ucp::Array{T,1}
    Ul::Array{T,1}
    Res::Array{T,1} #check that res is small and Res =  Upvb - β*R*Matab*Upvb
    Ntoi::Array{I,1}
    CC::Array{T,1}
    indnc::Array{I,1} #index of non-credit constrained histories
    indcc::Array{I,1} #index of credit constrained histories
    ytype::Array{T,1}
    xsyn::Array{Float64,1}
    xsyn1::Array{Float64,1}
    xsyn2::Array{Float64,1}
end

struct Lagrange_mult_d{T <: Real}
    lambda::Array{T,1}
    lambdat::Array{T,1}
    psih::Array{T,1}
    Phi::Array{T,1}
end;

The function Write_Dynare

In [9]:
function Write_Dynare(trunc::Truncation,solution::AiyagariSolution,
        params::Params)
    
    @unpack β,α,δ,γ,Tt,u,u′,na,a_min,aGrid,ny,ys = params
    @unpack R,w,A,K,C,L,B = solution
    @unpack N,Ntot,ind_h,allocation_trunc,ξs,lagrange_mult,θ=trunc
    @unpack c_h,u′_h,Π_h,S_h,y0_h,a_beg_h,a_end_h,resid_E_h,ind_cc_h = allocation_trunc
    @unpack ξu0,ξu1,ξu2= ξs

    resid = u′_h - (β*R)*Π_h*u′_h
    tauopt = -Tt/(K^α*L^(1-α))
    Ctot = w*sum(S_h.*y0_h) - A + Tt + R*sum(solution.stationaryDist.*repeat(params.aGrid,1,ny))
    Welfare = sum(ξu0 .* S_h .* u.(c_h)) .+ (-Tt)^(θ)

    lagrange_m_d = Lagrange_mult_d(lagrange_mult.λ,
                                   lagrange_mult.λt,
                                   lagrange_mult.ψh,
                                   lagrange_mult.Φ)
    
    eco = Truncation_d(
        N,
        ny,
        Ntot,
        R,
        w,
        -Tt,
        A,
        B,
        ys,
        collect(vec(params.Πy')),
        S_h,
        S_h.*a_beg_h,#by bin
        S_h.*a_end_h,#by bin
        ones(5),
        S_h.*c_h,#by bin
        u′_h, #vector of marginal utilities (before multiplication by xsi1)
        Matrix(Π_h'), # transpose transition matrix
        u′_h.*S_h,
        u.(c_h),
        resid,
        ind_h,
        resid_E_h,
        ind_cc_h*0,
        ind_cc_h,
        y0_h,
        ξu0,
        ξu1,
        ξu2)
    
    file = matopen("todynare_Truncation.mat", "w")
    write(file, "Pl", lagrange_m_d)
    write(file, "eco", eco)
    write(file, "alpha", α)
    write(file, "beta", β)
    write(file, "delta", δ)
    write(file, "gamma", γ)
    write(file, "theta", θ)
    write(file, "tau", tauopt)
    write(file, "abar", a_min)
    write(file, "states", ys)
    write(file, "G", -Tt)
    write(file, "Ctot", C)
    write(file, "Ws", Welfare)
    close(file)

end;