Skip to content

cycles #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 40 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
1fc4fd0
no precompile
thorek1 Nov 19, 2023
4d3547c
Merge branch 'main' into cycles
thorek1 Nov 20, 2023
e23b0ad
first test script
thorek1 Nov 22, 2023
58752f4
trying to match SS
thorek1 Nov 23, 2023
2132603
Merge branch 'main' into cycles
thorek1 Nov 23, 2023
1afe849
add test script
thorek1 Nov 29, 2023
749effe
update todos
thorek1 Nov 29, 2023
9e04d84
add cycles notebook
thorek1 Dec 3, 2023
747c591
Merge branch 'main' into cycles
thorek1 Jan 8, 2024
95b82f1
fix precompile
thorek1 Jan 8, 2024
290c208
write get_eigenvalues
thorek1 Jan 8, 2024
3b75c5c
fix wrappers
thorek1 Jan 9, 2024
f0106cc
Update get_functions.jl
thorek1 Jan 9, 2024
642eb51
fix wrappers
thorek1 Jan 9, 2024
8e0c025
Update get_functions.jl
thorek1 Jan 9, 2024
0238a9d
Update plotting.jl
thorek1 Jan 9, 2024
5d2a74e
Update get_functions.jl
thorek1 Jan 9, 2024
443e740
Merge branch 'main' into cycles
thorek1 Jan 9, 2024
5158ca0
Update get_functions.jl
thorek1 Jan 9, 2024
741baa8
Update MacroModelling.jl
thorek1 Jan 9, 2024
d1da62a
Update get_functions.jl
thorek1 Jan 9, 2024
038bc08
consolidate wrapper code
thorek1 Jan 9, 2024
344edfa
bundle initial state handling in a function
thorek1 Jan 9, 2024
cd4cfe1
fix docstring, types, defaults
thorek1 Jan 9, 2024
7d80db3
fix steady states
thorek1 Jan 10, 2024
a38eca0
allows small caps
thorek1 Jan 10, 2024
723c1e6
fix init state func
thorek1 Jan 10, 2024
8d3de87
fix remaining old init state
thorek1 Jan 10, 2024
1f6fd4c
fix init state again
thorek1 Jan 10, 2024
e36aa1f
wanr not fail if no SSS
thorek1 Jan 10, 2024
986f616
Merge branch 'main' into cycles
thorek1 Jan 10, 2024
569e11d
no nsss throws error
thorek1 Jan 11, 2024
8cbd9e6
try and fix plot_solutions
thorek1 Jan 12, 2024
8953acc
adjust init state func
thorek1 Jan 12, 2024
335d88a
amend plot solution
thorek1 Jan 12, 2024
ca091a3
more tested models
thorek1 Jan 12, 2024
0c47385
Create cycles_pluto.jl
thorek1 Jan 12, 2024
6d9471d
fix typo
thorek1 Jan 12, 2024
45db098
fix plot solutions
thorek1 Jan 13, 2024
b887c9a
Merge branch 'main' into cycles
thorek1 Apr 2, 2024
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
2,755 changes: 2,755 additions & 0 deletions cycles.jl

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/src/unfinished_docs/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@
## Not high priority

- [ ] estimation codes with missing values (adopt kalman filter)
- [ ] add better error messages from dynare parser and dont have him change the folder even if he fails (catch the case and change the folder back)
- [ ] decide on whether levels = false means deviations from NSSS or relevant SS
- [ ] whats a good error measure for higher order solutions (taking whole dist of future shock into account)? use mean error for n number of future shocks
- [ ] improve redundant calculations of SS and other parts of solution
Expand Down
195 changes: 118 additions & 77 deletions src/MacroModelling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export plot_irfs, plot_irf, plot_IRF, plot_simulations, plot_solution, plot_simu
export plot_conditional_variance_decomposition, plot_forecast_error_variance_decomposition, plot_fevd, plot_model_estimates, plot_shock_decomposition
export get_irfs, get_irf, get_IRF, simulate, get_simulation, get_simulations
export get_conditional_forecast, plot_conditional_forecast
export get_solution, get_first_order_solution, get_perturbation_solution, get_second_order_solution, get_third_order_solution
export get_solution, get_first_order_solution, get_perturbation_solution, get_second_order_solution, get_third_order_solution, get_eigenvalues
export get_steady_state, get_SS, get_ss, get_non_stochastic_steady_state, get_stochastic_steady_state, get_SSS, steady_state, SS, SSS, ss, sss
export get_non_stochastic_steady_state_residuals, get_residuals, check_residuals
export get_moments, get_statistics, get_covariance, get_standard_deviation, get_variance, get_var, get_std, get_stdev, get_cov, var, std, stdev, cov, get_mean #, mean
Expand Down Expand Up @@ -1648,14 +1648,56 @@ function expand_indices(compressed_inputs::Vector{Symbol}, compressed_values::Ve
end


function get_and_check_initial_state(𝓂::ℳ, initial_state::Union{Vector{Vector{Float64}}, Vector{Float64}, Symbol}, reference_steady_state::Vector{Float64}, NSSS::Vector{Float64}, SSS_delta::Vector{Float64}, algorithm::Symbol)::Union{Vector{Vector{Float64}}, Vector{Float64}}
if initial_state isa Symbol
if initial_state ∈ [:relevant_SS, :relevant_ss, :relevant_steady_state]
init_state = zeros(𝓂.timings.nVars) - SSS_delta
elseif initial_state ∈ [:SSS, :sss, :stochastic_steady_state]
init_state = zeros(𝓂.timings.nVars) - SSS_delta

if algorithm ∈ [:second_order, :third_order, :pruned_second_order, :pruned_third_order]
@warn "Algorithm: $algorithm has no stochastic steady state. Continuing with the non stochastic steady state as the initial state."
init_state = zeros(𝓂.timings.nVars)
end
elseif initial_state ∈ [:NSSS, :nsss, :non_stochastic_steady_state]
init_state = zeros(𝓂.timings.nVars)
elseif initial_state == :mean
if algorithm == :first_order
init_state = zeros(𝓂.timings.nVars)
else
@assert algorithm ∈ [:first_order, :pruned_second_order, :pruned_third_order] "Mean only available for first order, pruned second order, or pruned third order solution."
end
else
@assert initial_state ∈ [:NSSS, :nsss, :non_stochastic_steady_state, :SSS, :sss, :stochastic_steady_state, :relevant_SS, :relevant_ss, :relevant_steady_state] "No valid input of type Symbol."
end
end

if initial_state isa Vector{Float64}
init_state = initial_state - NSSS
elseif initial_state isa Vector{Vector{Float64}}
if algorithm ∉ [:pruned_second_order, :pruned_third_order]
@assert initial_state isa Vector{Float64} "The solution algorithm has one state vector: initial_state must be a Vector{Float64}."
else
init_state = initial_state
end
end

if algorithm == :pruned_second_order
init_state = init_state isa Vector{Float64} ? [zeros(𝓂.timings.nVars), init_state] : init_state
elseif algorithm == :pruned_third_order
init_state = init_state isa Vector{Float64} ? [zeros(𝓂.timings.nVars), init_state, zeros(𝓂.timings.nVars)] : init_state
end

return init_state
end

function minmax!(x::Vector{Float64},lb::Vector{Float64},ub::Vector{Float64})
@inbounds for i in eachindex(x)
x[i] = max(lb[i], min(x[i], ub[i]))
end
end



# transformation of NSSS problem
function transform(x::Vector{T}, option::Int, shift::AbstractFloat) where T <: Real
if option == 4
Expand Down Expand Up @@ -4482,7 +4524,7 @@ function solve!(𝓂::ℳ;

stochastic_steady_state, converged, SS_and_pars, solution_error, ∇₁, ∇₂, 𝐒₁, 𝐒₂ = calculate_second_order_stochastic_steady_state(𝓂.parameter_values, 𝓂, verbose = verbose)

if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end
if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end

state_update₂ = function(state::Vector{T}, shock::Vector{S}) where {T,S}
aug_state = [state[𝓂.timings.past_not_future_and_mixed_idx]
Expand Down Expand Up @@ -4515,7 +4557,7 @@ function solve!(𝓂::ℳ;

stochastic_steady_state, converged, SS_and_pars, solution_error, ∇₁, ∇₂, 𝐒₁, 𝐒₂ = calculate_second_order_stochastic_steady_state(𝓂.parameter_values, 𝓂, verbose = verbose, pruning = true)

if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end
if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end

state_update₂ = function(pruned_states::Vector{Vector{T}}, shock::Vector{S}) where {T,S}
aug_state₁ = [pruned_states[1][𝓂.timings.past_not_future_and_mixed_idx]; 1; shock]
Expand Down Expand Up @@ -4546,7 +4588,7 @@ function solve!(𝓂::ℳ;
if ((:third_order == algorithm) && ((:third_order ∈ 𝓂.solution.outdated_algorithms) || (obc && obc_not_solved)))
stochastic_steady_state, converged, SS_and_pars, solution_error, ∇₁, ∇₂, ∇₃, 𝐒₁, 𝐒₂, 𝐒₃ = calculate_third_order_stochastic_steady_state(𝓂.parameter_values, 𝓂, verbose = verbose)

if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end
if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end

state_update₃ = function(state::Vector{T}, shock::Vector{S}) where {T,S}
aug_state = [state[𝓂.timings.past_not_future_and_mixed_idx]
Expand Down Expand Up @@ -4578,7 +4620,7 @@ function solve!(𝓂::ℳ;

stochastic_steady_state, converged, SS_and_pars, solution_error, ∇₁, ∇₂, ∇₃, 𝐒₁, 𝐒₂, 𝐒₃ = calculate_third_order_stochastic_steady_state(𝓂.parameter_values, 𝓂, verbose = verbose, pruning = true)

if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end
if !converged @warn "Solution does not have a stochastic steady state. Try reducing shock sizes by multiplying them with a number < 1." end

state_update₃ = function(pruned_states::Vector{Vector{T}}, shock::Vector{S}) where {T,S}
aug_state₁ = [pruned_states[1][𝓂.timings.past_not_future_and_mixed_idx]; 1; shock]
Expand Down Expand Up @@ -7964,80 +8006,79 @@ function filter_and_smooth(𝓂::ℳ,
end


if VERSION >= v"1.9"
@setup_workload begin
# Putting some things in `setup` can reduce the size of the
# precompile file and potentially make loading faster.
@model FS2000 precompile = true begin
dA[0] = exp(gam + z_e_a * e_a[x])
log(m[0]) = (1 - rho) * log(mst) + rho * log(m[-1]) + z_e_m * e_m[x]
- P[0] / (c[1] * P[1] * m[0]) + bet * P[1] * (alp * exp( - alp * (gam + log(e[1]))) * k[0] ^ (alp - 1) * n[1] ^ (1 - alp) + (1 - del) * exp( - (gam + log(e[1])))) / (c[2] * P[2] * m[1])=0
W[0] = l[0] / n[0]
- (psi / (1 - psi)) * (c[0] * P[0] / (1 - n[0])) + l[0] / n[0] = 0
R[0] = P[0] * (1 - alp) * exp( - alp * (gam + z_e_a * e_a[x])) * k[-1] ^ alp * n[0] ^ ( - alp) / W[0]
1 / (c[0] * P[0]) - bet * P[0] * (1 - alp) * exp( - alp * (gam + z_e_a * e_a[x])) * k[-1] ^ alp * n[0] ^ (1 - alp) / (m[0] * l[0] * c[1] * P[1]) = 0
c[0] + k[0] = exp( - alp * (gam + z_e_a * e_a[x])) * k[-1] ^ alp * n[0] ^ (1 - alp) + (1 - del) * exp( - (gam + z_e_a * e_a[x])) * k[-1]
P[0] * c[0] = m[0]
m[0] - 1 + d[0] = l[0]
e[0] = exp(z_e_a * e_a[x])
y[0] = k[-1] ^ alp * n[0] ^ (1 - alp) * exp( - alp * (gam + z_e_a * e_a[x]))
gy_obs[0] = dA[0] * y[0] / y[-1]
gp_obs[0] = (P[0] / P[-1]) * m[-1] / dA[0]
log_gy_obs[0] = log(gy_obs[0])
log_gp_obs[0] = log(gp_obs[0])
end

@parameters FS2000 silent = true precompile = true begin
alp = 0.356
bet = 0.993
gam = 0.0085
mst = 1.0002
rho = 0.129
psi = 0.65
del = 0.01
z_e_a = 0.035449
z_e_m = 0.008862
end

ENV["GKSwstype"] = "nul"

@compile_workload begin
# all calls in this block will be precompiled, regardless of whether
# they belong to your package or not (on Julia 1.8 and higher)
@model RBC precompile = true begin
1 / c[0] = (0.95 / c[1]) * (α * exp(z[1]) * k[0]^(α - 1) + (1 - δ))
c[0] + k[0] = (1 - δ) * k[-1] + exp(z[0]) * k[-1]^α
z[0] = 0.2 * z[-1] + 0.01 * eps_z[x]
end
# if VERSION >= v"1.9"
# @setup_workload begin
# # Putting some things in `setup` can reduce the size of the
# # precompile file and potentially make loading faster.
# @model FS2000 precompile = true begin
# dA[0] = exp(gam + z_e_a * e_a[x])
# log(m[0]) = (1 - rho) * log(mst) + rho * log(m[-1]) + z_e_m * e_m[x]
# - P[0] / (c[1] * P[1] * m[0]) + bet * P[1] * (alp * exp( - alp * (gam + log(e[1]))) * k[0] ^ (alp - 1) * n[1] ^ (1 - alp) + (1 - del) * exp( - (gam + log(e[1])))) / (c[2] * P[2] * m[1])=0
# W[0] = l[0] / n[0]
# - (psi / (1 - psi)) * (c[0] * P[0] / (1 - n[0])) + l[0] / n[0] = 0
# R[0] = P[0] * (1 - alp) * exp( - alp * (gam + z_e_a * e_a[x])) * k[-1] ^ alp * n[0] ^ ( - alp) / W[0]
# 1 / (c[0] * P[0]) - bet * P[0] * (1 - alp) * exp( - alp * (gam + z_e_a * e_a[x])) * k[-1] ^ alp * n[0] ^ (1 - alp) / (m[0] * l[0] * c[1] * P[1]) = 0
# c[0] + k[0] = exp( - alp * (gam + z_e_a * e_a[x])) * k[-1] ^ alp * n[0] ^ (1 - alp) + (1 - del) * exp( - (gam + z_e_a * e_a[x])) * k[-1]
# P[0] * c[0] = m[0]
# m[0] - 1 + d[0] = l[0]
# e[0] = exp(z_e_a * e_a[x])
# y[0] = k[-1] ^ alp * n[0] ^ (1 - alp) * exp( - alp * (gam + z_e_a * e_a[x]))
# gy_obs[0] = dA[0] * y[0] / y[-1]
# gp_obs[0] = (P[0] / P[-1]) * m[-1] / dA[0]
# log_gy_obs[0] = log(gy_obs[0])
# log_gp_obs[0] = log(gp_obs[0])
# end

@parameters RBC silent = true precompile = true begin
δ = 0.02
α = 0.5
end
# @parameters FS2000 silent = true precompile = true begin
# alp = 0.356
# bet = 0.993
# gam = 0.0085
# mst = 1.0002
# rho = 0.129
# psi = 0.65
# del = 0.01
# z_e_a = 0.035449
# z_e_m = 0.008862
# end

# ENV["GKSwstype"] = "nul"

get_SS(FS2000)
get_SS(FS2000, parameters = :alp => 0.36)
get_solution(FS2000)
get_solution(FS2000, parameters = :alp => 0.35)
get_standard_deviation(FS2000)
get_correlation(FS2000)
get_autocorrelation(FS2000)
get_variance_decomposition(FS2000)
get_conditional_variance_decomposition(FS2000)
get_irf(FS2000)
# @compile_workload begin
# # all calls in this block will be precompiled, regardless of whether
# # they belong to your package or not (on Julia 1.8 and higher)
# @model RBC precompile = true begin
# 1 / c[0] = (0.95 / c[1]) * (α * exp(z[1]) * k[0]^(α - 1) + (1 - δ))
# c[0] + k[0] = (1 - δ) * k[-1] + exp(z[0]) * k[-1]^α
# z[0] = 0.2 * z[-1] + 0.01 * eps_z[x]
# end

data = simulate(FS2000)([:c,:k],:,:simulate)
get_loglikelihood(FS2000, data, FS2000.parameter_values)
get_mean(FS2000, silent = true)
# get_SSS(FS2000, silent = true)
# get_SSS(FS2000, algorithm = :third_order, silent = true)
# @parameters RBC silent = true precompile = true begin
# δ = 0.02
# α = 0.5
# end

# import StatsPlots
# plot_irf(FS2000)
# plot_solution(FS2000,:k) # fix warning when there is no sensitivity and all values are the same. triggers: no strict ticks found...
# plot_conditional_variance_decomposition(FS2000)
end
end
end
# get_SS(FS2000)
# get_SS(FS2000, parameters = :alp => 0.36)
# get_solution(FS2000)
# get_solution(FS2000, parameters = :alp => 0.35)
# get_standard_deviation(FS2000)
# get_correlation(FS2000)
# get_autocorrelation(FS2000)
# get_variance_decomposition(FS2000)
# get_conditional_variance_decomposition(FS2000)
# get_irf(FS2000)

# data = simulate(FS2000)([:c,:k],:,:simulate)
# get_loglikelihood(FS2000, data, FS2000.parameter_values)
# get_mean(FS2000, silent = true)
# # get_SSS(FS2000, silent = true)
# # get_SSS(FS2000, algorithm = :third_order, silent = true)

# # import Plots, StatsPlots
# # plot_irf(FS2000)
# # plot_solution(FS2000,:k) # fix warning when there is no sensitivity and all values are the same. triggers: no strict ticks found...
# # plot_conditional_variance_decomposition(FS2000)
# end
# end

end
2 changes: 1 addition & 1 deletion src/common_docstrings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const DERIVATIVES = "`derivatives` [Default: `true`, Type: `Bool`]: calculate de
const PERIODS = "`periods` [Default: `40`, Type: `Int`]: number of periods for which to calculate the IRFs. In case a matrix of shocks was provided, periods defines how many periods after the series of shocks the simulation continues."
const NEGATIVE_SHOCK = "`negative_shock` [Default: `false`, Type: `Bool`]: calculate a negative shock. Relevant for generalised IRFs."
const GENERALISED_IRF = "`generalised_irf` [Default: `false`, Type: `Bool`]: calculate generalised IRFs. Relevant for nonlinear solutions. Reference steady state for deviations is the stochastic steady state."
const INITIAL_STATE = "`initial_state` [Default: `[0.0]`, Type: `Vector{Float64}`]: provide state (in levels, not deviations) from which to start IRFs. Relevant for normal IRFs. The state includes all variables as well as exogenous variables in leads or lags if present."
const ALGORITHM = "`algorithm` [Default: `:first_order`, Type: `Symbol`]: algorithm to solve for the dynamics of the model."
const FILTER = "`filter` [Default: `:kalman`, Type: `Symbol`]: filter used to compute the shocks given the data, model, and parameters. The Kalman filter only works for linear problems, whereas the inversion filter (`:inversion`) works for linear and nonlinear models. If a nonlinear solution algorithm is selected, the inversion filter is used."
const LEVELS = "`levels` [Default: `false`, Type: `Bool`]: return levels or absolute deviations from steady state corresponding to the solution algorithm (e.g. stochastic steady state for higher order solution algorithms)."
Expand All @@ -19,3 +18,4 @@ const PARAMETER_DERIVATIVES = "`parameter_derivatives` [Default: :all]: paramete
const DATA = "`data` [Type: `KeyedArray`]: data matrix with variables (`String` or `Symbol`) in rows and time in columns"
const SMOOTH = "`smooth` [Default: `true`, Type: `Bool`]: whether to return smoothed (`true`) or filtered (`false`) shocks. Only works for the Kalman filter. The inversion filter only returns filtered shocks."
const DATA_IN_LEVELS = "`data_in_levels` [Default: `true`, Type: `Bool`]: indicator whether the data is provided in levels. If `true` the input to the data argument will have the non stochastic steady state substracted."
const INITIAL_STATE = "`initial_state` [Default: `:relevant_steady_state`, Type: `Union{Vector{Vector{Float64}}, Vector{Float64}, Symbol}`]: The initial state defines the starting point for the model and is relevant for normal IRFs. The default is the relevant steady state (stochastic steady state in case of a nonlinear solution, otherwise the non stochastic steady state). You can use any of `:relevant_SS`, `:relevant_ss`, `:relevant_steady_state` to use the relevant steady state, any of `:SSS`, `:sss`, `:stochastic_steady_state` to use the stochastic steady state (falls back to the non stochastic steady state in case the model is solution deifned in `algorithm` is linear), or any of `:NSSS`, `:nsss`, `:non_stochastic_steady_state` to use the non stochastic steady state. In the case of pruned solution algorithms the initial state can be given as multiple state vectors (`Vector{Vector{Float64}}`). In this case the initial state must be given in devations from the non-stochastic steady state. In all other cases the initial state must be given in levels. If a pruned solution algorithm is selected and initial state is a `Vector{Float64}` then it impacts the first order initial state vector only. The state includes all variables as well as exogenous variables in leads or lags if present."
Loading
Loading