Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ makedocs(
"Work with a more complex model - Smets and Wouters (2003)" => "tutorials/sw03.md",
"Calibration / method of moments (for higher order perturbation solutions) - Gali (2015)" => "tutorials/calibration.md",
"Estimate a model using gradient based samplers - Schorfheide (2000)" => "tutorials/estimation.md",
"Ramsey Optimal Policy" => "tutorials/ramsey.md",
],
"Plotting" => [
"Overview" => "plotting.md",
Expand Down
154 changes: 154 additions & 0 deletions docs/src/tutorials/ramsey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Ramsey Optimal Policy

This guide explains how to derive and analyze Ramsey optimal policy using MacroModelling.jl. Ramsey optimal policy is a framework where a benevolent social planner maximizes welfare subject to the constraints imposed by private agents' behavior (the model equations).

## Overview

In the Ramsey problem, a planner chooses policy instruments (like the interest rate or tax rates) to maximize discounted welfare:

```math
\max_{instruments} E_0 \sum_{t=0}^{\infty} \beta^t U(y_t)
```

subject to the model's equilibrium conditions:

```math
f_i(y_{t+1}, y_t, y_{t-1}, \varepsilon_t) = 0, \quad \forall i
```

MacroModelling.jl can automatically derive the first-order conditions (FOCs) for this problem using the `@ramsey` macro.

## Basic Usage

### Step 1: Define Your Model

First, define a standard DSGE model:

```julia
using MacroModelling

@model RBC begin
1/c[0] = β * (1/c[1]) * (α * exp(z[1]) * k[0]^(α-1) + (1-δ))
c[0] + k[0] = (1-δ) * k[-1] + q[0]
q[0] = exp(z[0]) * k[-1]^α
z[0] = ρ * z[-1] + std_z * eps_z[x]
end

@parameters RBC begin
std_z = 0.01
ρ = 0.2
δ = 0.02
α = 0.5
β = 0.95
end
```

### Step 2: Create the Ramsey Model

Use the `@ramsey` macro to derive the optimal policy FOCs:

```julia
result = @ramsey RBC begin
objective = log(c[0]) # Utility function
instruments = [q] # Policy instrument(s)
discount = β # Discount factor
end
```

This returns a NamedTuple with:
- `equations`: All equations in the Ramsey system (constraints + FOCs)
- `focs`: Just the first-order conditions
- `multipliers`: The Lagrange multiplier symbols
- `variables`: All variables including multipliers
- `objective`, `instruments`, `discount`: The configuration

### Step 3: View the Results

```julia
println("Original equations: ", length(RBC.original_equations))
println("Total Ramsey equations: ", length(result.equations))
println("Lagrange multipliers: ", result.multipliers)

println("\nFirst-Order Conditions:")
for (i, foc) in enumerate(result.focs)
println(" FOC $i: ", foc)
end
```

## Example Output

For the RBC model above, the `@ramsey` macro generates:

```
Creating Ramsey model: RBC_ramsey
Original equations: 4
Ramsey equations (total): 8
Lagrange multipliers: [:Lagr_mult_1, :Lagr_mult_2, :Lagr_mult_3, :Lagr_mult_4]
Instruments: [:q]
```

## Multiple Instruments

You can specify multiple policy instruments:

```julia
result = @ramsey NK begin
objective = log(C[0]) - N[0]^(1+φ)/(1+φ)
instruments = [R, τ] # Interest rate and tax rate
discount = β
end
```

## Understanding the Output

### Original Equations (Constraints)
These are the model's equilibrium conditions that constrain the planner's choices.

### Lagrange Multipliers
Each constraint gets a multiplier (`Lagr_mult_1`, `Lagr_mult_2`, ...). These represent the shadow value of relaxing each constraint.

### First-Order Conditions
The FOCs determine optimal policy. For each variable `y`:

```math
\frac{\partial U}{\partial y_{j,t}} - \sum_i \left[ \lambda_{i,t} \frac{\partial f_i}{\partial y_{j,t}} + \beta \lambda_{i,t+1} \frac{\partial f_i}{\partial y_{j,t+1}} + \frac{\lambda_{i,t-1}}{\beta} \frac{\partial f_i}{\partial y_{j,t-1}} \right] = 0
```

## Building the Full Ramsey Model

To create a solvable model, you need to include the generated equations in a new `@model` block. The returned `result.equations` contains both the original model equations and the new FOCs.

```julia
# Get the Ramsey equations
result = @ramsey RBC begin
objective = log(c[0])
instruments = [q]
discount = β
end

# The equations are available for building a new model
println("All equations: ", result.equations)
println("New variables (including multipliers): ", result.variables)
```

## Mathematical Details

The Ramsey Lagrangian is:

```math
\mathcal{L} = E_0 \sum_{t=0}^{\infty} \beta^t \left[ U(y_t) - \sum_i \lambda_{i,t} f_i(y_{t+1}, y_t, y_{t-1}, \varepsilon_t) \right]
```

Taking FOCs with respect to each variable `y_j`:

```math
\frac{\partial \mathcal{L}}{\partial y_{j,t}} = \beta^t \left[ \frac{\partial U}{\partial y_{j,t}} - \sum_i \lambda_{i,t} \frac{\partial f_i}{\partial y_{j,t}} - \beta \lambda_{i,t+1} \frac{\partial f_i}{\partial y_{j,t+1}} - \frac{\lambda_{i,t-1}}{\beta} \frac{\partial f_i}{\partial y_{j,t-1}} \right] = 0
```

## API Reference

```@docs
@ramsey
parse_ramsey_block
transform_equations_for_ramsey
```
5 changes: 5 additions & 0 deletions src/MacroModelling.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ include("./filter/find_shocks.jl")
include("./filter/inversion.jl")
include("./filter/kalman.jl")

include("ramsey.jl")


# end # DispatchDoctor

Expand Down Expand Up @@ -207,6 +209,9 @@ export translate_mod_file, translate_dynare_file, import_model, import_dynare
export write_mod_file, write_dynare_file, write_to_dynare_file, write_to_dynare, export_dynare, export_to_dynare, export_mod_file, export_model

export get_equations, get_steady_state_equations, get_dynamic_equations, get_calibration_equations, get_parameters, get_calibrated_parameters, get_parameters_in_equations, get_parameters_defined_by_parameters, get_parameters_defining_parameters, get_calibration_equation_parameters, get_variables, get_nonnegativity_auxiliary_variables, get_dynamic_auxiliary_variables, get_shocks, get_state_variables, get_jump_variables, get_missing_parameters, has_missing_parameters

export @ramsey, parse_ramsey_block, transform_equations_for_ramsey, generate_ramsey_model_code, print_ramsey_model_code

# Internal
export irf, girf

Expand Down
Loading