The Dynare Project is looking for independent Julia programmers - work remote

The Dynare Project is looking for independent Julia programmers doing remote work.
Dynare (https://www.dynare.org) is a Matlab/Octave toolbox for
solving, simulating and estimating dynamic macroeconomic models.
We are now rewriting the application in Julia (https://github.com/DynareJulia)

The project is ambitious and involves many areas of Julia
computing. Among them

  • general architecture of the application, packages and modules
  • parsing an existing modeling language
  • optimizing precompilation
  • functional approximation with perturbation and projections methods
  • stochastic simulation
  • Kalman filter
  • numerical optimization
  • Bayesian estimation of linearized models
  • Nonlinear estimation and particle filters
  • Results vizualization
  • Because economic models may be large and complex, computation time
    matters and very efficient code must be written for several critical
    parts.

The aim of the Dynare project is to provide economists who aren’t
numerical analysts or computing scientists with the best tools and
algorithms currently available. The project is entirely Open Source.

There exist a vibrant community of Dynare end users
(https://forum.dynare.org/). We organize an annual conference
(Dynare Conference 2022 | Dynare) and a yearly
Summer School.

The Dynare project is based in Paris and working Western Europe
business hours, but we are flexible about coordinating with
developers in other time zones.

Different working arrangements can be considered but will always be
formalized by a contract.

Please send resume and previous code examples @MichelJuillard. Don’t
hesitate to ask for further details about this job.

49 Likes

I have some questions:
Is the work paid?
What are the professional requirements for the work?

1 Like

This is exciting stuff for a former macro guy like myself! Not to hijack your job posting, but could you elaborate on what you mean by “rewriting” Dynare in Julia? How do you see the relationship of “traditional” Matlab-Dynare to this new effort going forward?

Of course the work is paid at a daily rate to be commonly agreed upon. We are looking for developers with previous experience in Julia programing and knowledge of some of the areas described in the job posting

6 Likes

Rewriting Dynare in Julia is the occasion to rething the architecture of an application written over more than 20 year. Julia should provide a solution more efficient than Matlab. The process should go back to the various algorithms and implement them in Julia, not translating existing Matlab code in Julia.
DynareJulia should be able to run the same *.mod files as Dynare Matlab. For the time being we are leveraging the same C++ preprocessor as in Dynare Matlab (see Readme · DynarePreprocessor_jll.jl)

23 Likes

This took me 15+ years back in time, when I did econometric research at the Swedish central Bank. Dynare was new back then. Makes me happy that it will be rewritten in Julia. It should be an excellent fit, it makes total sense. Good luck!

10 Likes

@MichelJuillard this is exciting news! I have some questions.

  1. inter-temporal optimization problems appear in 1 of 4 quadrants
    image
    Old versions of Dynare only tried to solve problems in the left two quadrants (& only problems w/ well defined steady states).
    Enormous progress has been made in solving continuous time models. There are even packages in Julia.
    Note these continuous time methods are: very fast, robust, and work for problems w/o steady-states.
    Note: we can further decompose each quadrant into Finite/Infinite horizon…
    Which problems will the new Dynare work on? (Your post above is very general.)
  2. Jesus FV has argued that there are broadly 3 classes of methods for solving intertemporal problems:
    Fixed Point Iteration (FPI)/Perturbation/Projection.
    FPI can solve a very wide variety of problems w/o SS.
    Is Dynare open to FPI methods?
Method Toolkits
Fixed Point Iteration (VFI, PFI, EE iter) VFIToolkit, CLMM, Dolo.jl, EconPDEs.jl
Perturbation Old Dynare, SolveDSGE.jl, Dolo.jl, DSGE.jl
Projection SolveDSGE.jl, TaylorProjection.m

IMHO if you start w/ @RJDennis SolveDSGE.jl
-Add Oren Levintal’s 5th order perturbation & Taylor projection
-Add Dolo.jl’s time iteration
-Add generic FPI methods like in VFIToolkit.m
-integrate continuous time methods from EconPDEs.jl
-@ChrisRackauckas explained in detail here the properties that makes a package composable
-ideally this means getting rid of the awkward .mod files (see my example)

3 Likes

@Albert_Zevelev, thank you for the message, the pointers and the advice.

  1. Our first priority is to replicate in Julia the main functionalities of DynareMatlab, so we remain for now in the two left quadrants. Continuous time models have become more popular and we may provide support for them further down the line. For now, we are dealing with infinite horizon models. Finite horizon models are important in variety of contexts and we need to see what we can do, in particular for limited rationality models
  2. Dynare has always put an emphasis on medium and large size models used in policy. So for now we use perturbation techniques for stochastic models. It would be nice to have some projection methods.
  3. We are using a much more modular approach than in DynareMatlab, making separate packages for different algorithms so we are going into the direction of composable pacakges.
  4. I don’t share your stern view of the *.mod file. First of all there exist now thousands of them out there and we need to keep providing support for them. It is a domain specific language. Users like it and it make it possible to write a DSGE model almost like in a paper. It is important to provide a way to express a model with as little formal constraints as possible.
  5. It would be good to provide the possibility to write the optimization problem instead of its first order conditions, as in your example, but I see it only when there is a single optimization problem in a model, if the households, the firm, labor hiring, banking, all solve their own optimization problem, I don’t see the interface to express each optimization problem and collect their respective constraints in a coherent model.
4 Likes

@MichelJuillard thanks for the reply!
My understanding is Dynare.jl intends to Solve/Simulate/Estimate economic models.

  1. The current focus is on models that are:
    Discrete time (deterministic or stochastic)
    Infinite horizon
    Have a unique steady state? (I couldn’t tell from your answer. This doesn’t allow for consumption savings models, or models w/ a BGP such as the Lucas-Uzawa model.)

  2. I think you’re saying the emphasis is on perturbation techniques bc they’re very fast. However, FPI methods, can also be very fast for certain types of high-dimensional problems.
    Has it been decided not to include FPI methods? Or is this still to be determined?

  3. If I solve a model using my own method, so I have the policy functions, but then want to simulate/compute-IRFs/estimate it, can I still use Dynare? (I hope this is what you mean by modular.)
    In the future if Dynare.jl adds the ability to handle e.g. Finite horizon models, developers will not need to change other parts of the code (much) so these new models will work w/ the simulation etc…

  4. Please don’t interpret my views to be “stern”. I’m merely asking questions.
    Many prefer writing their models in the same language as the rest of their code.
    What difference would it make if we can write the same exact Euler equations & transition functions in Julia vs mod file (like Dynare) or YAML (like Dolo)?

Update: I took out my strongly opinionated views (on DSLs for economics) from this comment.
I’ll write them up elsewhere.

  1. It is not required that the model has a unique steady state, but local approximation is built around one of the steady state. Models characterized by a balanced growth path can be stationarized before being brought to Dynare. We provide some tools to compute the stationarized version
  2. What papers/Julia pacakge are you thinking at when you are thinking at very fast FPI for certain types of high-dimensional problems? There is no decision not to include FPI eventually.
    3.-4. You are right, we need to give access to the numerical algorithms as a library and not only via the *.mod file. I hope that writing algorithms in different packages will facilitate it. Using the package as a library will then let you side-step the *.mod file
1 Like

There have been a lot of discussions on Domain Specific Languages in the Julia community.
I briefly noted down some of my opinions here.

  1. Models that Dynare can solve:
    I look forward to seeing examples of how models can be “stationarized”
    Perhaps you meant similar to this example Villemot 2013
    I also hope Dynare.jl will (some day) be able to handle models w/ some discrete decisions (kinks in the value function) (e.g. models where Governments/Households/Firms can default on debt). I’ve only seen these types of models solved with fixed point methods…

  2. Solvers that Dynare may one day include:
    In continuous time, the finite difference upwind scheme solves for a value function that is a fixed point of the HJB. These methods can be used to solve for the equilibrium distribution of Heterogeneous agent Bewley/Huggett/Aiyagari models in a fraction of a second.
    In discrete time, Coleman, Lyon, Maliar, Maliar (2020) solve the stochastic Neoclassical growth model with 7 different fixed point algorithms. They provide replication code, but not a generic package (like VFIToolkit.m which only has the slowest method VFI).
    The literature has all kinds of other examples (which often get forgotten partly bc they are not included into large well maintained open source packages).
    One of my favorites is FiPIt (2020) (fast global EE iteration w/ occasionally binding constraints)

  3. Writing models in Julia vs a separate .mod or .yaml file:
    The gold standard approach in the Julia ecosystem is to formulate the problem & solver in the same Julia language or even in the same program.
    See the Problem/Solve approach in SciML.
    See the Model/optimize!() approach in JuMP.jl & InfiniteOpt.jl
    SolveDSGE.jl:
    -models are written in a .txt file
    -models are parsed in julia model= retrieve_processed_model(path)
    -models are solved/simulated/etc w/ various solvers in Julia
    Dolo.jl:
    -models are written in a .yaml file
    -models are parsed in julia model = yaml_import(filename)
    -models are solved/simulated/etc w/ various solvers in Julia
    BankOfCanada.jl:
    -models are written/solved/analyzed in Julia
    RiskAdjustedLinearizations.jl
    -models are written/solved/analyzed in Julia
    EconPDEs.jl
    -models are written/solved/analyzed in Julia
    VFIToolkit.m
    -models are written/solved/analyzed in Matlab
    Oren Levintal’s TaylorProjection.m
    -models are written/solved/analyzed in Matlab beautifully (using projection and/or perturbation)
    Generically, any “solve” should take a model object as an input (and solver parameters), then return a policy function (as a function of parameters) as the output.

Why is it more natural to write down model equations in a separate .mod or .yaml file, than to write the all the equations in the same Julia program?

  1. Your work on Dynare (so far) has provided the world w/ an amazing public good.
    Dynare.jl has the potential to go a lot further!

Example following the JuMP/SciML approaches:
Define model: states/controls/shocks, optimality, transition etc

α=.33; δ=1.0; β=.98;
f(k; δ=δ,α=α) = (1.0 -δ)*k +   (k^α)
df(k;δ=δ,α=α) = (1.0 -δ)   + α*(k^(α-1.0))
sdf(cp,c;β=β) = β*((cp/c)^(-1.0))
EE(cp,c,kp,k) = sdf(cp,c)*df(kp) - 1.0 ## optimality condition
T(c, k) = f(k) -c ## transition function kp= T(c,k)

ncgm = DynareModel()
@variable(ncgm , K, state) ## state variables
@variable(ncgm , C, control) ## control variables
@equation(ncgm , EE(cp,c,kp,k)) ## optimality equations
@transition(ncgm , T(c, k)) ## transition function

# now all relevant variables/equations stored in "ncgm"

# Pick your favorite solvers (from the entire Julia ecosystem etc)
tol = 1e-8; maxiters = 100; 
PPP = PerturbationScheme(ss,1.0,"third") # SolveDSGE.jl
soln_to = solve(ncgm, PPP)

CCC = ChebyshevSchemeDet(ss,chebyshev_nodes,[31,31,31],5,[0.07 3.2 0.8; -0.07 2.9 0.6],tol,1e-6,maxiters,:newton)
soln_cheb = solve(ncgm, CCC)

# if there was an Euler Equation Iteration type fixed point solver 
soln_ee = solve(ncgm, EE)

# Similarly for VFI/EC/PFI/etc 
# Note: to use some Fixed Point solvers the user would need to add
# the appropriate Envelope conditions etc as explained in my other post
solve(ncgm, VFI(),      guess; maxiter=1000, verbose=false)
solve(ncgm, VFI_EGM(),  guess; maxiter=1000, verbose=false)
solve(ncgm, VFI_ECM(),  guess; maxiter=1000, verbose=false)
solve(ncgm, dVFI_ECM(), guess; maxiter=1000, verbose=false)
solve(ncgm, PFI(),      guess; maxiter=1000, verbose=false)
solve(ncgm, PFI_ECM(),  guess; maxiter=1000, verbose=false)
solve(ncgm, EE(),       guess; maxiter=1000, verbose=false)

# once a model is solve, using appropriate method(s) the user has a solution object w/ a policy function
# the model can be automatically simulated using the transition & policy functions 
3 Likes

The webpage for the Bank of Canada project says that the model is contained in a Module which is stored in its own separate file.

Whether it be a Module, .txt, .mod, .yaml file, the advantage of having the model in its own separate file is that it lets the user focus on just writing down the equations, setting parameter values, etc. All of the processing, the heavy lifting to produce the model struct is done by the parser, which reasons about the whole model as a system and can identify problems before it gets to the solvers. Having the model defined in the same .jl file where the solution and analysis take place requires the user do the work required to create the model struct. This can work fine for small, simple, models with few states, controls, and equations, but would likely lead to the typical user making errors for the larger models that economists often want to solve. Then those of us that write these packages would be spending of our time resolving “issues” and debugging people’s code.

As it is, the processed model file created by SolveDSGE.jl can be copy-pasted into a .jl file if you want, then it is straightforward to create the model struct and go from there all in the one file.

Applying the approach you describe to something like Smets and Wouters (2007), Gertler and Karadi (2011), the NY Fed. model or the Bank of Canada model would be a challange; not impossible, but a challange.

2 Likes

Thanks. I slightly edited my note.
Here is a link to the Bank of Canada model: simple_RBC.jl

There are (at least) two issues:
1: should the model definition/solution/analysis-estimation be in the same language
Such as: Bank Of Canada, VFIToolkit, TaylorProjection …
2: should the user have the option to define the model equations/parameters etc in the same program as where the model is solved?
JuMP.jl/DifferentialEquations.jl allows users to define quite complicated systems in the same program…

Currently a deterministic growth model in a .txt in your package

# Deterministic growth model with habit formation, expressed so solution will be in terms of logs

states:
z, k
end

jumps:
c, ce
end

shocks:
end

parameters:
β = 0.99
σ = 1.1
γ = 0.8
δ = 0.025
α = 0.30
ρ = 0.8
end

solvers: Any

equations:
exp(k(+1)) = (1.0 - δ)*exp(k) + exp(z)*exp(k)^α - exp(c)
(exp(c) - γ*exp(c(-1)))^(-σ) = β*ce(+1)
ce = (exp(c) - γ*exp(c(-1)))^(-σ)*(1.0 - δ + α*exp(z)*exp(k)^(α - 1.0))
z(+1) = ρ*z
end

Why can’t this be just as easy to do as in the same program as in SciML/JuMP?
A model is declared. ncgm = model()
The user defines the states/controls/shocks in the model
The user adds the optimality, transition, Envelope Condition etc equations to the model
Then the user just picks their desired solver…

Btw, wouldn’t it be easier to pass the parameters through a parameter vector as in DifferentialEquations.jl?
My guess this would make it easier/faster to resolve the model for a different set of parameters? and to estimate the model?

Albert,

there is more than one way of doing things. The point I was trying to make is that there are some good reasons for putting the model in its own file, even if one is not ensuring compatability with all the pre-existing .mod files out there (one of Michel’s points). All of these approaches are in some way turning model information into Julia code; your hypothetical example from earlier does it using macros.

Incidentally, the assign_parameters() function in SolveDSGE.jl does exactly what you wrote: it passes values for parameters into the model.

I think that this is the last that I will write here because this is a thread about Dynare.jl and I don’t want to hijack it with discussions about SolveDSGE.jl.

Thanks. I think there’s a benefit to having a public discussion about best practices for designing DSLs for econ.

I prefer the idea of defining a model w/ macros (like state of the art packages SciML/JuMP)

Users can decide if they prefer to put the model definition in a separate file or in the same file.

There is no reason Dynare.jl cannot be backward compatible.
It can read .mod files
like SolveDSGE: model= retrieve_processed_model(path)
like Dolo.jl: model = yaml_import(filename)
But it can also define a model like state-of-the-art packages (in a separate file, or in the same file)

This can give users access to
MacroModelDataBase
Pfeifer’s Github repo
Other large collections of models may need to be rewritten to Julia:
VFIToolkit replication

It would be a lot easier for me to explain w/ an example from SciML

using DifferentialEquations, Plots;

#####################################################
# Define the problem equations given a parameter θ  #
# This can be done in a separate Julia file.        #
#####################################################
function ngm!(dX, X, θ, t)
    C, K          = X  # variables: Consumption, Capital
    ρ, γ, z, α, δ = θ  # parameters
    dC = ((α*z*(K^(α-1.0)) -δ -ρ)/γ)*C # Euler Eqn
    dK = z*K^(α) - δ*K - C             # Law of Motion
    dX .= (dC, dK)    # Time derivatives
end

#####################################################
# Set parameters & initial conditions               #
#####################################################
α=0.20; γ=6.0; δ=0.25; z=1.0; ρ = δ*(α*γ-1.0)
K0 = 1.0; C0 = (1-(1/γ))*z*(K0)^α;
KSS= ((α)/(ρ+δ))^(1/(1-α))
CSS = (KSS)^α - δ*KSS

#####################################################
# Define the Problem                                #
#####################################################
X0 = [C0, K0]                         # initial conditions
tspan = (0.0, 30.0)                   # time span
θ = [ρ, γ, z, α, δ]                   # parameters
prob = ODEProblem(ngm!, X0, tspan, θ) # problem

#####################################################
# Solve the Problem w/ your favorite solvers        #
# https://diffeq.sciml.ai/dev/solvers/ode_solve/    #
# 100s of ODE solvers                               # 
#####################################################
sol = solve(prob)
sol = solve(prob,reltol=1e-6)
sol = solve(prob,alg_hints=[:stiff],reltol=1e-8,abstol=1e-8)
sol = solve(prob,Tsit5())
sol = solve(prob,Tsit5(),reltol=1e-8,abstol=1e-8)

#####################################################
# See if the solution converges to steady state     #
#####################################################
plot(sol, label=["C(t)" "K(t)"])
plot!([CSS KSS 0.0],  seriestype = :hline, lab=["CSS" "KSS" ""], color="grey", l=:dash)

Thanks Robert, I agree entirely with you. Don’t hesitate to stay/jump in this discussion. I hope we will be able to have cross-fertilizing exchanges between SolveDSGE and DynareJulia

1 Like

The key is to provide a stable, documented interface to the solvers/estimators provided in DynareJulia like for solve() in your above example. Once we are there, you will be able to use it the way you like.

Note that your example is about a continuous time model. With discrete time and difference equations, we need some conventional way of indicating leads, lags and most likely an expectation operator. Same for occasionally binding constraints and then some parsing of the elements communicated by the user will need parsing. We are at the onset of a minimal DSL that goes beyond Julia’s usual syntax

2 Likes