内容为《动态随机一般均衡(DSGE)模型》的笔记,李向阳老师著,清华大学出版社出版。
我只将个人会用到的知识作了笔记,并对教材较难理解的部分做了进一步阐述。为了更易于理解,我还对教材上的一些部分(包括代码和正文)做了修改。
仅供学习参考,请勿转载,侵删!
第3章 · Dynare基本应用(1)
本章将会介绍一个简单的RBC模型以显示“如何在Dynare中编写一个完整的模型文件”。
3.1 介绍一个简单的模型
(1) 数学建模
假设一个代表性家庭(,以后用上标
表示)选择
和劳动
来最大化其终身贴现效用:
其中 和
为参数,并且有
为贴现因子。此效用函数表明消费和劳动不可分。最大化问题面临的资源约束为:
其中, 为产出的资本份额,
为投资,资本存量
遵循经典的积累方程:
其中, 为折旧率参数。另外,还定义外生冲击
服从简单的
过程:
其中, 为扰动参数,
为外生冲击持续性参数,越接近于1,持续性越强。
(2) 模型求解
对问题 及其面临的约束进行求解(对于离散的无穷贴现问题,统一采用
方法求解,统一记
为
),可以得到关于
和
的
为:
因此,模型的均衡由5个内生变量,以及下面5个均衡方程构成:
Euler方程
:
劳动供给方程
:
资源约束方程:
资本积累方程:
技术变量的
过程:
3.2 Dynare内生变量的分类和书写规范
3.2.1 Dynare内生变量的分类
在Dynare中,内生变量根据时间下标被分成4类,如下表(3.1)所示:
内生变量类型 | 定义 | 内生变量个数存储位置 |
---|---|---|
静态变量 | 仅仅出现时间下标 |
M._nstatic |
前向变量 | 仅仅出现时间下标 |
M._nfwrd |
后向变量 | 仅仅出现时间下标 |
M._npred |
混合变量 | 同时出现 |
M._nboth |
针对第3.1节的简单模型,可以观察均衡条件,并对模型变量进行归类:
和
都仅出现了
和
,属于前向变量
属于标准的后向变量
属于标准的静态变量
存量变量比较特殊:虽然存量变量出现了
和
,但存量变量是在
期末被决定,故属于后向变量。所以在Dynare编程中,
和
要写成
和
(在3.1.2节会解释!)
按照效用函数的不同设定,在通常情况下,如果:
效用函数为
和
的可加可分函数时,
为静态变量
效用函数为
和
的不可分函数时,
为非静态变量
效用函数引入消费习惯的设定,
变为混合变量
一般而言,内生变量只能属于上述4种变量的其中一类,所以上述的分类是内生变量
类型的一个完全划分。从而4种内生变量个数之和为整个模型所有内生变量
个数(M._endo_nbr),即:
一般而言,模型中内生状态变量
的个数(M._nspred)为后向变量和混合变量的个数之和:
此外,相对于静态变量而言,另外三者统称为动态变量
(M._ndynamic),有:
关于本节关于变量的逻辑,可以归类在图3.1中:
3.1.2 Dynare内生变量的书写规范
(1) 命名规范
Dynare运行在Matlab以上,内生变量规范要遵循Matlab的命名规范,一般:
尽量不要使用Matlab和Dynare内置函数的名字作为变量
不要在变量或参数中包含特殊字符
Dynare对变量是大小写敏感的
尽量不要使用小写字母
i
,以免与Matlab的复数单位混淆
(2) 时间下标约定
在Dynare中,变量的下标是根据该变量的决定时期来确定
的。一般来说, 期变量(流量变量)是由
期的变量(内生和外生变量)和
期初实现的外生冲击共同决定的。所以,从这个意义上说,
存量变量(Stock Variables)
在 期末被决定,或者说在流量变量决定后再决定。一个经典的例子就是资本存量,根据:
投资 在
期被决定,从而
形式上虽然是
期变量,本质上是
期
预先决定
的变量,它是在 期末就被决定的,因此也被写成:
从而,时期 可以虚拟地看成是由三部分构成:
初期:外生冲击实现
中期:当期变量决定
期末:存量变量决定
在Dynare编程中,对各种时间下标的语法见下表(3.2):
变量形式 | 书写形式 |
---|---|
x(+2),x(2) | |
x(+1),x(1) | |
x | |
x(-1) | |
x(-2) |
只有极少数的情况下会出现 或
期的情况。如果出现,Dynare会自动引入
辅助变量(Auxiliary Variables)
,无需编程者操心。
3.2.3 Dynare内生变量的排序
在Dynare中,有两种内生变量的排序,用于不同的场合:
- 声明顺序:根据模型文件书写时
var
命令的先后次序排序,例如:
var c k lab z I;
就表示内生变量按照 的顺序出存在
中
- 决策规则顺序:首先是静态变量,然后后向变量,然后混合变量,最后前向变量;同一种变量的排序按照声明顺序排列
3.3 Dynare文件基本结构
由于Dynare语法规则多,并且随着版本更新会删除和新增一些命令,教材只罗列了常用的语法规则。一般来说,一个模型文件(*.mod)由5个部分组成:
前导部分(Preamble)
模型声明部分(Model)
稳态值或初始值声明部分(Steady state or initial values)
外生冲击声明部分(Shocks)
模型计算部分(Computation)
下面会逐一讲解。
3.3.1 前导部分
这里主要完成模型声明的前期准备工作,包括3个部分:
内生变量声明(
var
命令)外生变量声明(
varexo
命令)参数声明(
parameters
命令)参数赋值(直接赋值)
针对第一节的模型,对应模型文件的前导部分可以写成源代码9
,为:
%----- 源代码9 -----%
var c k lab z I; % 内生变量声明
varexo e; % 外生变量声明
parameters beta theta delta alpha tau rho s; % 参数声明
% 参数赋值
beta = 0.987;
theta = 0.357;
delta = 0.012;
alpha = 0.4;
tau = 2;
rho = 0.95;
s = 0.01;
前导部分的三个声明命令 var
、varexo
、parameters
是可以在一个*.mod
文件中反复使用的,这样可以提高模型文件的可读性。Dyanre会自动处理,无需编者操心。
3.3.2 模型部分
在结束前面的前导部分声明后,即可声明模型部分,即模型的各个均衡条件
。模型部分以model;
开始,以end;
结束,在两个命令之间输入均衡条件,每个均衡条件以;
结束。均衡条件太长时,可以跨行书写。
例如,对3.1节的RBC模型书写模型部分,如所示:
%----- 源代码10 -----%
model;
% 定义模型的“局部变量”,以提高编程的便利性
# mar_c = (c^theta * (1-lab)^(1-theta) ) ^ (1-tau); % 局部变量的声明使用“#”命令
# mar_c1 = (c(+1)^theta * (1-lab(+1))^(1-theta) ) ^ (1-tau);
% (1) 欧拉方程
[name = 'Euler equation'] % 这是系统标签(tag),可以对每个均衡条件进行标识
mar_c/c = beta * (mar_c1/c(+1)) * (1 + alpha*exp(z)*k^(alpha-1)*lab(+1)^(1-alpha) - delta);
% (2) 劳动供给方程
[name = 'Labor supply']
((1-theta)/theta) * (c/(1-lab)) = (1-alpha)*exp(z)*k(-1)^alpha*lab^(-alpha);
% (3) 资源约束方程
[name = 'Resource constraint']
c + k - (1-delta)*k(-1) = exp(z)*k(-1)^alpha*lab^(1-alpha);
% (4) 资本积累方程
[name = 'Capital accumulation']
I = k - (1-delta)*k(-1);
% (5) 外生冲击AR(1)过程
[name = 'Technology shock']
z = rho*z(-1) + s*e;
end;
对以上的代码我们需要注意:
为了提高程序的可读性,建议在每个均衡方程的前面添加注释和编号,可以以
%
或//
开头表示单行注释可以使用系统标签(tag)对均衡条件进行标识,从而在后续进行稳态的计算和调试时,
resid
命令能够显示出该标签的编号。使用
#
命令定义局部变量,可以提高程序的易读性,在后续使用局部变量时不需要再使用#
。局部变量在本质上唯一的作用就是本文替换(Text Substitution)
此外,我们需要注意,命令model;
拥有8个选项,最常用的是linear
选项,使用方法是model(linear);
。如果使用了linear
命令,模型被声明为线型,此时均衡条件必须是手动线性化后的结果。同时,由于已经是线性化模型,稳态值本身就是0,不需要额外指定。
3.3.3 稳态或初值部分/外生冲击部分
稳态值和初值的声明是Dynare采用扰动算法的基本要求。初值声明的目的是为了让Dynare从这里开始寻找稳态值。关于稳态和初值声明会在“3.8.2 稳态求解命令:steady”中介绍;外生冲击则会在“3.8.3 确定性模拟”中详细介绍。这里仅介绍随机模拟的情况,确定性模拟会复杂一些。源代码11
介绍了如何简单地设定初始值、外生冲击的方差,计算稳态的同时计算各静态方程的残差,此时各内生变量取值稳态。
%----- 源代码11 -----%
initval; % 初值模块,设定内生变量和外生变量的初始值
k = 0.5;
c = 0.5;
lab = 0.5;
z = 0;
I = 0.5;
e = 0;
end;
shocks; % 外生冲击设定,直接设定外生冲击的方差
var e = s^2;
end;
steady; % 计算稳态
resid; % 给定内生变量的取值(通常为稳态),计算均衡条件对应的静态方程的残差
理论上初值的设置是很宽泛的,但是如果输入某些特殊值会使得Dyanre求解稳态的时候“走错方向”,找到错误的稳态。比如初始化k=0
的时候,Dynare就找不到稳态值了。从而,设置初值的时候尽量不要选择特殊的数字。
比较建议的是,如果稳态具有解析解,则把解析解直接写入*.mod
文件中作为稳态值(后面会这么做的),这样一方面避免了出现无解的情况,另一方面节省计算成本。
3.3.4 计算部分
计算部分是模型最核心的部分之一,也是最复杂的地方。所谓计算,就是在各参数已知的情况下求解抉择规则,常用的有3个命令:
确定性模拟(
simul
):在“3.8.3 确定性模拟”中介绍随机模拟(
stoch_simul
):在“3.9 随机模拟分析:stoch_simul”中介绍估计(
estimation
):在“3.10 参数估计简介”中介绍
三种不同的计算命令各有区别。粗略地说,simul
和 stoch_simul
是用于模拟外生冲击而言的。确定性模拟是指外生冲击的发生时刻和大小都已经预先知晓的模拟;随机模拟是指发生冲击的时刻或大小都是随机的模拟。而 estimation
是根据观测或统计数据,首先使用估计技术估计未知参数,然后使用估计后的参数进行随机模拟。
下面的源代码12
展示了随机模拟命令 stoch_simul
及其3个常用的选项,然后将Dynare内置命令将模拟结果保存为自定义名称的Matlab矩阵文件(*.mat
)。
%----- 源代码12 -----%
% 如果不指定模拟的次数“periods”,Dynare就不会进行模拟
stoch_simul(periods=1000, irf=400, order=1);
% 将模拟结果保存为“simudata.mat”文件
dynasave('simudata.mat');
在上面的代码中,我们应该注意:
选项
periods
:用于指定随机模拟的期数选项
irf
:用于指定脉冲响应的计算期数选项
order
: 用于指定求解的阶数,有1``2``3
三个选项
所以,这里的随机模拟命令的含义是,使用线性求解算法(order=1
)求解模型,并模拟1000期内变量的样本,计算400期脉冲响应函数。
将以上的源代码9
到源代码12
拼接起来,就是一个完整的Dynare模型文件:
/*
* 《动态随机一般均衡(DSGE)模型》教材
* 源代码9~源代码12整合,与教材上代码略有改编
* 2020年3月12日
* @爱吃汉堡薯条
* @侵删
*/
%----- 源代码9 -----%
var c k lab z I; % 内生变量声明
varexo e; % 外生变量声明
parameters beta theta delta alpha tau rho s; % 参数声明
% 参数赋值
beta = 0.987;
theta = 0.357;
delta = 0.012;
alpha = 0.4;
tau = 2;
rho = 0.95;
s = 0.01;
%----- 源代码10 -----%
model;
% 定义模型的“局部变量”,以提高编程的便利性
# mar_c = (c^theta * (1-lab)^(1-theta) ) ^ (1-tau); % 局部变量的声明使用“#”命令
# mar_c1 = (c(+1)^theta * (1-lab(+1))^(1-theta) ) ^ (1-tau);
% (1) 欧拉方程
[name = 'Euler equation'] % 这是系统标签(tag),可以对每个均衡条件进行标识
mar_c/c = beta * (mar_c1/c(+1)) * (1 + alpha*exp(z)*k^(alpha-1)*lab(+1)^(1-alpha) - delta);
% (2) 劳动供给方程
[name = 'Labor supply']
((1-theta)/theta) * (c/(1-lab)) = (1-alpha)*exp(z)*k(-1)^alpha*lab^(-alpha);
% (3) 资源约束方程
[name = 'Resource constraint']
c + k - (1-delta)*k(-1) = exp(z)*k(-1)^alpha*lab^(1-alpha);
% (4) 资本积累方程
[name = 'Capital accumulation']
I = k - (1-delta)*k(-1);
% (5) 外生冲击AR(1)过程
[name = 'Technology shock']
z = rho*z(-1) + s*e;
end;
%----- 源代码11 -----%
initval; % 初值模块,设定内生变量和外生变量的初始值
k = 0.5;
c = 0.5;
lab = 0.5;
z = 0;
I = 0.5;
e = 0;
end;
shocks; % 外生冲击设定,直接设定外生冲击的方差
var e = s^2;
end;
steady; % 计算稳态
resid; % 给定内生变量的取值(通常为稳态),计算均衡条件对应的静态方程的残差
%----- 源代码12 -----%
% 如果不指定模拟的次数“periods”,Dynare就不会进行模拟
stoch_simul(periods=1000, irf=400, order=1);
% 将模拟结果保存为“simudata.mat”文件
dynasave('simudata.mat');
执行模型文件,输出脉冲响应图像: