Skip to content

Commit

Permalink
Estimation (#84)
Browse files Browse the repository at this point in the history
non linear shock decomposition
fast linear Kalman and inversion filter
simplify keyword for parameters macro triggering symbolic equation solves
input custom plot attributes (overriding defaults)
improved plots
custom reverse mode AD inversion and kalman filter (1st order solutions)
eliminated a lot of allocations for estimation
---------

Co-authored-by: Thore Kockerols <thore.kockerols@ecb.europa.eu>
  • Loading branch information
thorek1 and Thore Kockerols authored Jul 13, 2024
1 parent 2e7b473 commit ad966aa
Show file tree
Hide file tree
Showing 29 changed files with 3,768 additions and 1,134 deletions.
38 changes: 21 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ jobs:
env:
GKS_ENCODING: "utf8"
GKSwstype: "nul"
name: ${{ matrix.test_set }} - ${{ matrix.version }} - ${{ matrix.os }}
name: ${{ matrix.test_set }} - ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.version == 'nightly' || matrix.version == '^1.11.0-0' }}
strategy:
fail-fast: false
matrix:
test_set: ["basic", "plots", "higher_order", "estimation"]
version: ['1.8', '1.9', '1.10']
os: [ubuntu-latest, macos-14, windows-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
arch: [x64, arm64]
exclude:
- version: '1.8'
Expand All @@ -31,50 +31,54 @@ jobs:
- arch: arm64
os: windows-latest
- arch: x64
os: macos-14
os: macos-latest
include:
- os: ubuntu-latest
prefix: xvfb-run
# - version: '1.10'
# os: macos-14
# os: macos-latest
# arch: x64
# test_set: "solver0"
# - version: '1.10'
# os: macos-14
# os: macos-latest
# arch: x64
# test_set: "solver1"
# - version: '1.10'
# os: macos-14
# os: macos-latest
# arch: x64
# test_set: "solver2"
# - version: '1.10'
# os: macos-14
# os: macos-latest
# arch: x64
# test_set: "solver3"
- version: '1.10'
os: macos-14
arch: x64
os: macos-latest
arch: arm64
test_set: "estimate_sw07"
- version: '1.10'
os: macos-latest
arch: arm64
test_set: "1st_order_inversion_estimation"
- version: '1.10'
os: macos-14
arch: x64
os: macos-latest
arch: arm64
test_set: "2nd_order_estimation"
- version: '1.10'
os: macos-14
arch: x64
os: macos-latest
arch: arm64
test_set: "3rd_order_estimation"
# - version: '1.10'
# os: macOS-latest
# arch: x64
# test_set: "basic"
- version: 'nightly'
os: macos-14
os: ubuntu-latest
arch: x64
test_set: "basic"
allow_failure: true
- version: '^1.11.0-0'
os: macos-14
arch: x64
os: macos-latest
arch: arm64
test_set: "basic"
allow_failure: true
steps:
Expand All @@ -90,7 +94,7 @@ jobs:
if: matrix.os != 'windows-latest'
run: echo "TEST_SET=${{ matrix.test_set }}" >> $GITHUB_ENV
- name: Set JULIA_NUM_THREADS for estimation tests
if: matrix.version == '1.10' && (matrix.test_set == 'estimation' || matrix.test_set == 'solver0' || matrix.test_set == 'solver1' || matrix.test_set == 'solver2' || matrix.test_set == 'solver3' || matrix.test_set == '1st_order_inversion_estimation' || matrix.test_set == '2nd_order_estimation' || matrix.test_set == '3rd_order_estimation')
if: (matrix.version == '1.10' && (matrix.test_set == 'estimation' || matrix.test_set == 'estimate_sw07' || matrix.test_set == '1st_order_inversion_estimation' || matrix.test_set == '2nd_order_estimation' || matrix.test_set == '3rd_order_estimation'))
run: echo "JULIA_NUM_THREADS=auto" >> $GITHUB_ENV
- uses: actions/cache@v4
env:
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ results
octave*
*.jls
samples*
*samples.csv
*samples.csv
skewness*.png
conditional_forecast*.png
98 changes: 51 additions & 47 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.1.36"

[deps]
AbstractDifferentiation = "c29ec348-61ec-40c8-8164-b8c60e9d9f3d"
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5"
BlockTriangularForm = "adeb47b7-70bf-415a-bb24-c358563e873a"
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
Expand All @@ -24,6 +25,7 @@ MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
MatrixEquations = "99c1a7ee-ab34-5fd5-8076-27c950a045f4"
NLopt = "76087f3c-5699-56af-9a33-bf431cd00edd"
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
Expand All @@ -47,55 +49,57 @@ StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
Turing = "fce5fe82-541a-59a6-adf8-730c64b5f9a0"

[compat]
AbstractDifferentiation = "^0.5, 0.6"
Aqua = "^0.8"
AxisKeys = "^0.2"
BlockTriangularForm = "^0.1"
CSV = "^0.10"
ChainRulesCore = "^1"
Combinatorics = "^1"
DataFrames = "^1"
DataStructures = "^0.18"
DocStringExtensions = "^0.8, 0.9"
DynamicPPL = "0.23, 0.24"
DynarePreprocessor_jll = "^6.2"
FiniteDifferences = "^0.12"
ForwardDiff = "^0.10"
ImplicitDifferentiation = "^0.5"
JET = "0.7, 0.8"
JSON = "^0.21"
Krylov = "^0.9"
LaTeXStrings = "^1"
LineSearches = "^7"
LinearAlgebra = "^1"
LinearOperators = "^2"
MCMCChains = "^6"
MacroTools = "^0.5"
MatrixEquations = "^2"
AbstractDifferentiation = "0.5, 0.6"
Accessors = "0.1"
Aqua = "0.8"
AxisKeys = "0.2"
BlockTriangularForm = "0.1"
CSV = "0.10"
ChainRulesCore = "1"
Combinatorics = "1"
DataFrames = "1"
DataStructures = "0.18"
DocStringExtensions = "0.8, 0.9"
DynamicPPL = "0.23, 0.24, 0.25, 0.26, 0.27, 0.28"
DynarePreprocessor_jll = "6"
FiniteDifferences = "0.12"
ForwardDiff = "0.10"
ImplicitDifferentiation = "0.5"
JET = "0.7, 0.8, 0.9"
JSON = "0.21"
Krylov = "0.9"
LaTeXStrings = "1"
LineSearches = "7"
LinearAlgebra = "1"
LinearOperators = "2"
MCMCChains = "6"
MacroTools = "0.5"
MatrixEquations = "2"
NLopt = "0.6, =1.0.1"
Optim = "^1"
Optim = "1"
Pigeons = "0.3, 0.4"
PrecompileTools = "^1"
PythonCall = "0.9.0 - 0.9.15"
REPL = "^1"
Random = "^1"
RecursiveFactorization = "^0.2"
Reexport = "^1"
Requires = "^1"
RuntimeGeneratedFunctions = "^0.5"
SparseArrays = "^1"
SpecialFunctions = "^2"
SpeedMapping = "^0.3"
StatsPlots = "^0.15"
Subscripts = "0.1.3"
Suppressor = "^0.2"
SymPyPythonCall = "^0.2"
Symbolics = "^5"
Test = "^1"
ThreadedSparseArrays = "^0.2.3"
Turing = "0.29, 0.30"
Unicode = "^1"
Zygote = "^0.6"
Polyester = "0.7"
PrecompileTools = "1"
PythonCall = "0.9"
REPL = "1"
Random = "1"
RecursiveFactorization = "0.2"
Reexport = "1"
Requires = "1"
RuntimeGeneratedFunctions = "0.5"
SparseArrays = "1"
SpecialFunctions = "2"
SpeedMapping = "0.3, 0.4"
StatsPlots = "0.15"
Subscripts = "0.1.3, 0.2"
Suppressor = "0.2"
SymPyPythonCall = "0.2, 0.3"
Symbolics = "5, 6"
Test = "1"
ThreadedSparseArrays = "0.2.3, 0.3"
Turing = "0.30, 0.31, 0.32, 0.33"
Unicode = "1"
Zygote = "0.6"
julia = "1.8"

[extras]
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

These kinds of models describe the behavior of a macroeconomy and are particularly suited for counterfactual analysis (economic policy evaluation) and exploring / quantifying specific mechanisms (academic research). Due to the complexity of these models, efficient numerical tools are required, as analytical solutions are often unavailable. `MacroModelling.jl` serves as a tool for handling the complexities involved, such as forward-looking expectations, nonlinearity, and high dimensionality.

The goal of this package is to reduce coding time and speed up model development by providing functions for working with discrete-time DSGE models. The user-friendly syntax, automatic variable declaration, and effective steady state solver facilitate fast prototyping of models. Furthermore, the package allows the user to work with nonlinear model solutions (up to third order (pruned) perturbation) and estimate the model using gradient based samplers (e.g. NUTS, or HMC). Currently, `DifferentiableStateSpaceModels.jl` is the only other package providing functionality to estimate using gradient based samplers but the use is limited to models with an analytical solution of the non stochastic steady state (NSSS). Larger models tend to not have an analytical solution of the NSSS and `MacroModelling.jl` can also use gradient based sampler in this case. The target audience for the package includes central bankers, regulators, graduate students, and others working in academia with an interest in DSGE modelling.
The goal of this package is to reduce coding time and speed up model development by providing functions for working with discrete-time DSGE models. The user-friendly syntax, automatic variable declaration, and effective steady state solver facilitate fast prototyping of models. Furthermore, the package allows the user to work with nonlinear model solutions (up to third order (pruned) perturbation) and estimate the model using gradient based samplers (e.g. NUTS, or HMC). Currently, `DifferentiableStateSpaceModels.jl` is the only other package providing functionality to estimate using gradient based samplers but they use the start-of-period timing convention instead of the end-of-period timing convention used in most other packages. The target audience for the package includes central bankers, regulators, graduate students, and others working in academia with an interest in DSGE modelling.

As of now the package can:

Expand Down Expand Up @@ -103,13 +103,13 @@ The package contains the following models in the `models` folder:
**Host language**|julia|MATLAB|julia|Python|julia|julia|julia|MATLAB|MATLAB|MATLAB|R|MATLAB|MATLAB|
**Non stochastic steady state solver**|*symbolic* or numerical solver of independent blocks; symbolic removal of variables redundant in steady state; inclusion of calibration equations in problem|numerical solver of independent blocks or user-supplied values/functions||numerical solver of independent blocks or user-supplied values/functions|numerical solver|numerical solver or user supplied values/equations|numerical solver of independent blocks or user-supplied values/functions|numerical solver of independent blocks or user-supplied values/functions|numerical solver of independent blocks or user-supplied values/functions|user-supplied steady state file or numerical solver|numerical solver; inclusion of calibration equations in problem|||
**Automatic declaration of variables and parameters**|yes|||||||||||||
**Derivatives (Automatic Differentiation) wrt parameters**|yes|||||yes - for all 1st, 2nd order perturbation solution related output *if user supplied steady state equations*|||||||
**Derivatives wrt parameters**|yes|||||yes|||||||
**Perturbation solution order**|1, 2, 3|k|1|1, 2, 3|1, 2, 3|1, 2|1|1|1 to 5|1|1||1 to 5|
**Pruning**|yes|yes||||yes|||yes|||||
**Automatic derivation of first order conditions**|||||||||||yes||
**Handles occasionally binding constraints**|yes|yes|yes|yes|yes||||yes|||yes||
**Occasionally binding constraints**|yes|yes|yes|yes|yes||||yes|||yes||
**Global solution**||||yes|yes|||||||yes||
**Estimation**|yes|yes|yes|||||yes|yes|yes|yes|||
**Estimation**|yes|yes|yes|||yes||yes|yes|yes|yes|||
**Balanced growth path**||yes|yes||||yes|yes|yes|yes|||||
**Model input**|macro (julia)|text file|text file|text file|text file|macro (julia)|module (julia)|text file|text file|text file|text file|text file|text file|
**Timing convention**|end-of-period|end-of-period||end-of-period|start-of-period|start-of-period|end-of-period|end-of-period|end-of-period|end-of-period|end-of-period|start-of-period|start-of-period|
Expand Down
13 changes: 13 additions & 0 deletions benchmark/optim_solver_params.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ include("../models/Ireland_2004.jl")
include("../models/Caldara_et_al_2012.jl")
include("../models/Gali_Monacelli_2005_CITR.jl")
include("../models/Gali_2015_chapter_3_nonlinear.jl")
# include("../models/Gali_2015_chapter_3_obc.jl")
include("../models/Aguiar_Gopinath_2007.jl")
include("../models/Ascari_Sbordone_2014.jl") # stands out
include("../models/FS2000.jl")
Expand Down Expand Up @@ -315,6 +316,18 @@ all_models = [
# all_models[1].NSSS_solver_cache
pars = [2.9912988764832833, 0.8725, 0.0027, 0.028948770826150612, 8.04, 4.076413176215408, 0.06375413238034794, 0.24284340766769424, 0.5634017580097571, 0.009549630552246828, 0.6342888355132347, 0.5275522227754195, 1.0, 0.06178989216048817, 0.5234277812131813, 0.422, 0.011209254402846185, 0.5047, 0.6020757011698457, 0.7688]



par_inputs = MacroModelling.solver_parameters(eps(), eps(), eps(), maxiters, pars..., transformation, 0.0, 2)

SS(Guerrieri_Iacoviello_2017)
get_solution(Guerrieri_Iacoviello_2017)
simulate(Guerrieri_Iacoviello_2017)
model = Guerrieri_Iacoviello_2017

model.SS_solve_func(model.parameter_values, model, false, true, [par_inputs])


evaluate_multi_pars_loglikelihood(pars, all_models)


Expand Down
8 changes: 4 additions & 4 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

These kinds of models describe the behavior of a macroeconomy and are particularly suited for counterfactual analysis (economic policy evaluation) and exploring / quantifying specific mechanisms (academic research). Due to the complexity of these models, efficient numerical tools are required, as analytical solutions are often unavailable. `MacroModelling.jl` serves as a tool for handling the complexities involved, such as forward-looking expectations, nonlinearity, and high dimensionality.

The goal of this package is to reduce coding time and speed up model development by providing functions for working with discrete-time DSGE models. The user-friendly syntax, automatic variable declaration, and effective steady state solver facilitate fast prototyping of models. Furthermore, the package allows the user to work with nonlinear model solutions (up to third order (pruned) perturbation) and estimate the model using gradient based samplers (e.g. NUTS, of HMC). Currently, `DifferentiableStateSpaceModels.jl` is the only other package providing functionality to estimate using gradient based samplers but the use is limited to models with an analytical solution of the non stochastic steady state (NSSS). Larger models tend to not have an analytical solution of the NSSS and `MacroModelling.jl` can also use gradient based sampler in this case. The target audience for the package includes central bankers, regulators, graduate students, and others working in academia with an interest in DSGE modelling.
The goal of this package is to reduce coding time and speed up model development by providing functions for working with discrete-time DSGE models. The user-friendly syntax, automatic variable declaration, and effective steady state solver facilitate fast prototyping of models. Furthermore, the package allows the user to work with nonlinear model solutions (up to third order (pruned) perturbation) and estimate the model using gradient based samplers (e.g. NUTS, or HMC). Currently, `DifferentiableStateSpaceModels.jl` is the only other package providing functionality to estimate using gradient based samplers but they use the start-of-period timing convention instead of the end-of-period timing convention used in most other packages. The target audience for the package includes central bankers, regulators, graduate students, and others working in academia with an interest in DSGE modelling.

As of now the package can:

Expand Down Expand Up @@ -56,13 +56,13 @@ The package contains the following models in the `models` folder:
**Host language**|julia|MATLAB|julia|Python|julia|julia|julia|MATLAB|MATLAB|MATLAB|R|MATLAB|MATLAB|
**Non stochastic steady state solver**|*symbolic* or numerical solver of independent blocks; symbolic removal of variables redundant in steady state; inclusion of calibration equations in problem|numerical solver of independent blocks or user-supplied values/functions||numerical solver of independent blocks or user-supplied values/functions|numerical solver|numerical solver or user supplied values/equations|numerical solver of independent blocks or user-supplied values/functions|numerical solver of independent blocks or user-supplied values/functions|numerical solver of independent blocks or user-supplied values/functions|user-supplied steady state file or numerical solver|numerical solver; inclusion of calibration equations in problem|||
**Automatic declaration of variables and parameters**|yes|||||||||||||
**Derivatives (Automatic Differentiation) wrt parameters**|yes|||||yes - for all 1st, 2nd order perturbation solution related output *if user supplied steady state equations*|||||||
**Derivatives wrt parameters**|yes|||||yes|||||||
**Perturbation solution order**|1, 2, 3|k|1|1, 2, 3|1, 2, 3|1, 2|1|1|1 to 5|1|1||1 to 5|
**Pruning**|yes|yes||||yes|||yes|||||
**Automatic derivation of first order conditions**|||||||||||yes||
**Handles occasionally binding constraints**|yes|yes|yes|yes|yes||||yes|||yes||
**Occasionally binding constraints**|yes|yes|yes|yes|yes||||yes|||yes||
**Global solution**||||yes|yes|||||||yes||
**Estimation**|yes|yes|yes|||||yes|yes|yes|yes|||
**Estimation**|yes|yes|yes|||yes||yes|yes|yes|yes|||
**Balanced growth path**||yes|yes||||yes|yes|yes|yes|||||
**Model input**|macro (julia)|text file|text file|text file|text file|macro (julia)|module (julia)|text file|text file|text file|text file|text file|text file|
**Timing convention**|end-of-period|end-of-period||end-of-period|start-of-period|start-of-period|end-of-period|end-of-period|end-of-period|end-of-period|end-of-period|start-of-period|start-of-period|
Expand Down
4 changes: 2 additions & 2 deletions docs/src/tutorials/calibration.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ using MacroModelling
end
```

First, we load the package and then use the [`@model`](@ref) macro to define our model. The first argument after [`@model`](@ref) is the model name and will be the name of the object in the global environment containing all information regarding the model. The second argument to the macro are the equations, which we write down between `begin` and `end`. Equations can contain an equality sign or the expression is assumed to equal 0. Equations cannot span multiple lines (unless you wrap the expression in brackets) and the timing of endogenous variables are expressed in the squared brackets following the variable name (e.g. `[-1]` for the past period). Exogenous variables (shocks) are followed by a keyword in squared brackets indicating them being exogenous (in this case `[x]`). Note that names can leverage julia's unicode capabilities (e.g. alpha can be written as α).
First, we load the package and then use the [`@model`](@ref) macro to define our model. The first argument after [`@model`](@ref) is the model name and will be the name of the object in the global environment containing all information regarding the model. The second argument to the macro are the equations, which we write down between `begin` and `end`. Equations can contain an equality sign or the expression is assumed to equal 0. Equations cannot span multiple lines (unless you wrap the expression in brackets) and the timing of endogenous variables are expressed in the square brackets following the variable name (e.g. `[-1]` for the past period). Exogenous variables (shocks) are followed by a keyword in square brackets indicating them being exogenous (in this case `[x]`). Note that names can leverage julia's unicode capabilities (e.g. alpha can be written as α).

## Define the parameters

Expand Down Expand Up @@ -319,7 +319,7 @@ get_statistics(Gali_2015, sol.minimizer, algorithm = :pruned_third_order, parame

The solution does not match the standard deviation of inflation very well.

Potentially the partial derivatives change a lot for small changes in parameters and even though the partial derivatives for standard deviation of inflation were large wrt `std_a` they might be small for value returned from the optimisation. We can check this with:
Potentially the partial derivatives change a lot for small changes in parameters and even though the partial derivatives for standard deviation of inflation were large wrt `std_a` they might be small for values returned from the optimisation. We can check this with:

```@repl tutorial_3
get_std(Gali_2015, parameter_derivatives = [:σ, :std_a, :α], variables = [:W_real,:Pi], algorithm = :pruned_third_order, parameters = [:α, :std_a] .=> sol.minimizer)
Expand Down
Loading

0 comments on commit ad966aa

Please sign in to comment.