Skip to content

Commit 6ff4727

Browse files
committed
feat: new article
1 parent 209a6ac commit 6ff4727

File tree

2 files changed

+342
-43
lines changed

2 files changed

+342
-43
lines changed
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
---
2+
author_profile: false
3+
categories:
4+
- Mathematical Economics
5+
classes: wide
6+
date: '2020-07-26'
7+
excerpt: A guide to solving DSGE models numerically, focusing on perturbation techniques
8+
and finite difference methods used in economic modeling.
9+
header:
10+
image: /assets/images/data_science_18.jpg
11+
og_image: /assets/images/data_science_18.jpg
12+
overlay_image: /assets/images/data_science_18.jpg
13+
show_overlay_excerpt: false
14+
teaser: /assets/images/data_science_18.jpg
15+
twitter_image: /assets/images/data_science_18.jpg
16+
keywords:
17+
- Dsge models
18+
- Numerical methods
19+
- Perturbation techniques
20+
- Finite difference methods
21+
- Economic modeling
22+
- Economics
23+
- Quantitative analysis
24+
- Computational methods
25+
- Python
26+
- Fortran
27+
- C
28+
seo_description: Explore numerical methods for solving DSGE models, including perturbation
29+
techniques and finite difference methods, essential tools in quantitative economics.
30+
seo_title: 'Solving DSGE Models: Perturbation and Finite Difference Methods'
31+
seo_type: article
32+
summary: This article covers numerical techniques for solving DSGE models, particularly
33+
perturbation and finite difference methods, essential in analyzing economic dynamics.
34+
tags:
35+
- Dsge models
36+
- Numerical methods
37+
- Perturbation techniques
38+
- Finite difference methods
39+
- Economics
40+
- Quantitative analysis
41+
- Computational methods
42+
- Python
43+
- Fortran
44+
- C
45+
title: 'Solving DSGE Models Numerically: Perturbation Techniques and Finite Difference
46+
Methods'
47+
---
48+
49+
Dynamic Stochastic General Equilibrium (DSGE) models are powerful tools for analyzing the effects of economic shocks and policy changes over time. Because DSGE models are inherently nonlinear and involve complex dynamic relationships, analytical solutions are often not feasible. Instead, numerical methods are used to approximate solutions to these models. Among the most popular techniques are **perturbation methods** and **finite difference methods**, each offering unique approaches to handling DSGE models' nonlinearity and time dependency.
50+
51+
This article explores these numerical methods in-depth, examining how perturbation and finite difference techniques work and how they apply to solving DSGE models.
52+
53+
## Perturbation Techniques for Solving DSGE Models
54+
55+
### Linearization and Higher-Order Approximations
56+
57+
**Perturbation methods** are among the most popular numerical techniques for solving DSGE models. These methods approximate the solution by expanding it around a known steady state, providing a series expansion that represents the model’s behavior. Perturbation methods start with a **first-order linearization** around the steady state and can be extended to **second-order or higher-order** terms to capture nonlinear effects.
58+
59+
1. **First-Order Approximation**: The model is linearized around its steady state, capturing the immediate effects of shocks but not the nonlinearities of the model.
60+
2. **Second-Order Approximation**: Adds a quadratic term to the expansion, allowing the model to capture some nonlinear effects such as risk premia and the effect of uncertainty on decision-making.
61+
3. **Higher-Order Approximations**: Higher-order terms can further refine the approximation, capturing more complex dynamic interactions and stochastic volatility.
62+
63+
The general approach for perturbation techniques is:
64+
65+
1. **Identify the Steady State**: Determine the values of variables where the system is in equilibrium.
66+
2. **Expand the System Around the Steady State**: Use Taylor expansions to approximate the equations of the model.
67+
3. **Solve the System of Approximated Equations**: The resulting equations provide an approximate solution near the steady state.
68+
69+
#### Example: First-Order Perturbation
70+
71+
Consider a simple DSGE model with a representative agent optimizing utility, where the Euler equation in the steady state is:
72+
73+
\[
74+
E_t \left[ u'(c_t) = \beta u'(c_{t+1}) \right]
75+
\]
76+
77+
A first-order perturbation would linearize this equation around the steady state values of \( c_t \) and \( c_{t+1} \), resulting in a system of linear equations that approximate the dynamics of the economy in response to small shocks.
78+
79+
### Advantages and Limitations of Perturbation Methods
80+
81+
Perturbation techniques have several advantages:
82+
83+
- **Computational Efficiency**: First-order approximations are computationally inexpensive, making them suitable for large models or policy simulations.
84+
- **Flexibility in Extensions**: Higher-order approximations allow for a more accurate representation of nonlinear effects, albeit with increased computational costs.
85+
86+
However, perturbation methods also have limitations:
87+
88+
- **Local Accuracy**: These methods are only accurate near the steady state and may perform poorly for large shocks or highly nonlinear models.
89+
- **Complexity in High-Order Terms**: Higher-order perturbations add complexity and can become difficult to interpret or implement.
90+
91+
## Comparing Perturbation and Finite Difference Approaches
92+
93+
Perturbation and finite difference methods each have unique advantages and are suitable for different types of DSGE models:
94+
95+
| Feature | Perturbation Methods | Finite Difference Methods |
96+
|-----------------------------|--------------------------------------------|-------------------------------------------|
97+
| **Model Suitability** | Best for models near steady state | Useful for models with strong nonlinearity|
98+
| **Computational Efficiency**| Generally faster, especially at first-order| Can be computationally intensive |
99+
| **Handling of Nonlinearity**| Captures local nonlinearity at higher order| Suitable for global nonlinear dynamics |
100+
| **Ease of Implementation** | Straightforward for low-order expansions | Requires careful grid setup and stability |
101+
102+
The choice between these methods depends on the model's characteristics, the desired level of approximation, and computational resources.
103+
104+
## Conclusion: Choosing the Right Method for DSGE Models
105+
106+
Both perturbation techniques and finite difference methods offer valuable approaches to solving DSGE models. Perturbation methods are ideal for scenarios where a model operates near its steady state, providing computational efficiency with moderate accuracy. In contrast, finite difference methods provide a more global perspective, capturing non-linear dynamics and making them suitable for highly complex or constrained models.
107+
108+
The selection of a numerical method depends on the model’s complexity, the type of economic analysis, and the computational resources available, allowing economists to adapt their approach to best understand dynamic economic relationships.
109+
110+
## Appendix: Python Code Examples for Solving DSGE Models Using Perturbation and Finite Difference Methods
111+
112+
```python
113+
import numpy as np
114+
from scipy.optimize import fsolve
115+
116+
# Example DSGE model parameters
117+
beta = 0.96
118+
alpha = 0.36
119+
delta = 0.08
120+
rho = 0.9
121+
sigma = 0.02
122+
123+
# Steady State Calculation for a Simple DSGE Model
124+
def steady_state():
125+
k_ss = ((1 / beta - (1 - delta)) / alpha) ** (1 / (alpha - 1))
126+
c_ss = k_ss ** alpha - delta * k_ss
127+
return k_ss, c_ss
128+
129+
k_ss, c_ss = steady_state()
130+
131+
# Perturbation Method: First-Order Linearization
132+
def first_order_perturbation(k, k_next):
133+
c = k ** alpha - delta * k
134+
c_next = k_next ** alpha - delta * k_next
135+
return beta * (c_next / c) * (alpha * k_next ** (alpha - 1) + 1 - delta) - 1
136+
137+
# Solve DSGE Model Using First-Order Perturbation
138+
def solve_dsge_perturbation(k0, num_periods=50):
139+
k_path = [k0]
140+
for t in range(num_periods):
141+
k_next = fsolve(first_order_perturbation, k_path[-1], args=(k_path[-1]))[0]
142+
k_path.append(k_next)
143+
return np.array(k_path)
144+
145+
# Initial capital and compute path
146+
k0 = k_ss * 0.9
147+
k_path = solve_dsge_perturbation(k0)
148+
print("Capital Path (Perturbation):", k_path)
149+
150+
# Finite Difference Method: Discrete Derivatives for a Simple DSGE Model
151+
def finite_difference_method(k_values, h=1e-4):
152+
derivs = []
153+
for k in k_values:
154+
fwd_diff = (k ** alpha - (k + h) ** alpha) / h
155+
derivs.append(fwd_diff)
156+
return np.array(derivs)
157+
158+
# Compute finite difference approximation
159+
k_values = np.linspace(k0, k_ss, 100)
160+
finite_diffs = finite_difference_method(k_values)
161+
print("Finite Differences:", finite_diffs)
162+
```
163+
164+
## Appendix: Fortran Code Examples for Solving DSGE Models Using Perturbation and Finite Difference Methods
165+
166+
```fortran
167+
program DSGE_Model
168+
implicit none
169+
integer, parameter :: num_periods = 50
170+
real(8) :: beta, alpha, delta, rho, sigma
171+
real(8) :: k_ss, c_ss, k0, h
172+
real(8), dimension(num_periods + 1) :: k_path
173+
integer :: i
174+
175+
! Model parameters
176+
beta = 0.96
177+
alpha = 0.36
178+
delta = 0.08
179+
rho = 0.9
180+
sigma = 0.02
181+
h = 1.0e-4
182+
183+
! Steady-state calculation
184+
call steady_state(k_ss, c_ss)
185+
print *, "Steady State Capital:", k_ss
186+
print *, "Steady State Consumption:", c_ss
187+
188+
! Perturbation method: Initial condition and solving for capital path
189+
k0 = 0.9 * k_ss
190+
k_path(1) = k0
191+
do i = 1, num_periods
192+
k_path(i + 1) = solve_dsge_perturbation(k_path(i))
193+
end do
194+
print *, "Capital Path (Perturbation):", k_path
195+
196+
! Finite difference approximation
197+
call finite_difference_method(k_path, h)
198+
199+
contains
200+
201+
subroutine steady_state(k_ss, c_ss)
202+
real(8), intent(out) :: k_ss, c_ss
203+
k_ss = ((1.0 / beta - (1.0 - delta)) / alpha) ** (1.0 / (alpha - 1.0))
204+
c_ss = k_ss ** alpha - delta * k_ss
205+
end subroutine steady_state
206+
207+
function solve_dsge_perturbation(k) result(k_next)
208+
real(8), intent(in) :: k
209+
real(8) :: k_next, f, f_prime
210+
integer :: iter
211+
real(8), parameter :: tol = 1.0e-6
212+
k_next = k
213+
iter = 0
214+
215+
do while (abs(f) > tol .and. iter < 100)
216+
f = first_order_perturbation(k, k_next)
217+
f_prime = derivative_first_order_perturbation(k, k_next)
218+
k_next = k_next - f / f_prime
219+
iter = iter + 1
220+
end do
221+
end function solve_dsge_perturbation
222+
223+
function first_order_perturbation(k, k_next) result(f)
224+
real(8), intent(in) :: k, k_next
225+
real(8) :: f, c, c_next
226+
c = k ** alpha - delta * k
227+
c_next = k_next ** alpha - delta * k_next
228+
f = beta * (c_next / c) * (alpha * k_next ** (alpha - 1) + 1 - delta) - 1.0
229+
end function first_order_perturbation
230+
231+
function derivative_first_order_perturbation(k, k_next) result(f_prime)
232+
real(8), intent(in) :: k, k_next
233+
real(8) :: f_prime, epsilon
234+
epsilon = 1.0e-6
235+
f_prime = (first_order_perturbation(k, k_next + epsilon) - &
236+
first_order_perturbation(k, k_next)) / epsilon
237+
end function derivative_first_order_perturbation
238+
239+
subroutine finite_difference_method(k_values, h)
240+
real(8), intent(in) :: k_values(:)
241+
real(8), intent(in) :: h
242+
real(8) :: fwd_diff
243+
integer :: i, n
244+
n = size(k_values)
245+
246+
print *, "Finite Differences:"
247+
do i = 1, n - 1
248+
fwd_diff = (k_values(i + 1) ** alpha - k_values(i) ** alpha) / h
249+
print *, fwd_diff
250+
end do
251+
end subroutine finite_difference_method
252+
253+
end program DSGE_Model
254+
```
255+
256+
## Appendix: C Code Examples for Solving DSGE Models Using Perturbation and Finite Difference Methods
257+
258+
```c
259+
#include <stdio.h>
260+
#include <math.h>
261+
262+
#define NUM_PERIODS 50
263+
#define TOL 1e-6
264+
#define H 1e-4
265+
266+
/* Parameters for the DSGE model */
267+
const double beta = 0.96;
268+
const double alpha = 0.36;
269+
const double delta = 0.08;
270+
271+
/* Steady-state calculation */
272+
void steady_state(double *k_ss, double *c_ss) {
273+
*k_ss = pow((1.0 / beta - (1.0 - delta)) / alpha, 1.0 / (alpha - 1.0));
274+
*c_ss = pow(*k_ss, alpha) - delta * (*k_ss);
275+
}
276+
277+
/* Perturbation Method: First-Order Linearization */
278+
double first_order_perturbation(double k, double k_next) {
279+
double c = pow(k, alpha) - delta * k;
280+
double c_next = pow(k_next, alpha) - delta * k_next;
281+
return beta * (c_next / c) * (alpha * pow(k_next, alpha - 1) + 1 - delta) - 1.0;
282+
}
283+
284+
/* Derivative for Newton-Raphson Method */
285+
double derivative_first_order_perturbation(double k, double k_next) {
286+
double epsilon = 1e-6;
287+
return (first_order_perturbation(k, k_next + epsilon) - first_order_perturbation(k, k_next)) / epsilon;
288+
}
289+
290+
/* Solve DSGE Model Using Perturbation */
291+
double solve_dsge_perturbation(double k) {
292+
double k_next = k, f, f_prime;
293+
int iter = 0;
294+
295+
do {
296+
f = first_order_perturbation(k, k_next);
297+
f_prime = derivative_first_order_perturbation(k, k_next);
298+
k_next -= f / f_prime;
299+
iter++;
300+
} while (fabs(f) > TOL && iter < 100);
301+
302+
return k_next;
303+
}
304+
305+
/* Finite Difference Method */
306+
void finite_difference_method(double k_values[], int n) {
307+
printf("Finite Differences:\n");
308+
for (int i = 0; i < n - 1; i++) {
309+
double fwd_diff = (pow(k_values[i + 1], alpha) - pow(k_values[i], alpha)) / H;
310+
printf("%f\n", fwd_diff);
311+
}
312+
}
313+
314+
int main() {
315+
double k_ss, c_ss, k0;
316+
double k_path[NUM_PERIODS + 1];
317+
318+
/* Calculate steady state */
319+
steady_state(&k_ss, &c_ss);
320+
printf("Steady State Capital: %f\n", k_ss);
321+
printf("Steady State Consumption: %f\n", c_ss);
322+
323+
/* Perturbation method: Initial condition and solving for capital path */
324+
k0 = 0.9 * k_ss;
325+
k_path[0] = k0;
326+
for (int i = 0; i < NUM_PERIODS; i++) {
327+
k_path[i + 1] = solve_dsge_perturbation(k_path[i]);
328+
}
329+
printf("Capital Path (Perturbation):\n");
330+
for (int i = 0; i <= NUM_PERIODS; i++) {
331+
printf("%f\n", k_path[i]);
332+
}
333+
334+
/* Finite difference approximation */
335+
finite_difference_method(k_path, NUM_PERIODS + 1);
336+
337+
return 0;
338+
}
339+
```

0 commit comments

Comments
 (0)