DSGE笔记系列1:Dynare基本应用(1)

内容为《动态随机一般均衡(DSGE)模型》的笔记,李向阳老师著,清华大学出版社出版。

我只将个人会用到的知识作了笔记,并对教材较难理解的部分做了进一步阐述。为了更易于理解,我还对教材上的一些部分(包括代码和正文)做了修改。

仅供学习参考,请勿转载,侵删!

第3章 · Dynare基本应用(1)

本章将会介绍一个简单的RBC模型以显示“如何在Dynare中编写一个完整的模型文件”。

3.1 介绍一个简单的模型

(1) 数学建模

假设一个代表性家庭(\text{Household},以后用上标 ^H 表示)选择C_t和劳动L_t来最大化其终身贴现效用:

\max \limits_{C_t,L_t}E_0\sum_{t=0}^\infty\beta^t\frac{(C_t^\theta(1-L_t)^{1-\theta})^{1-\tau}}{1-\tau} \tag{3.1.1}

其中 \theta\tau 为参数,并且有 1>\beta>0 为贴现因子。此效用函数表明消费和劳动不可分。最大化问题面临的资源约束为:

C_t+I_t = \exp(Z_t) K_t^\alpha L_t^{1-\alpha} \tag{3.1.2}

其中,1>\alpha>0 为产出的资本份额,I_t 为投资,资本存量 K_t 遵循经典的积累方程:

K_{t+1} = I_t + (1-\delta)K_t \tag{3.1.3}

其中,1>\delta>0 为折旧率参数。另外,还定义外生冲击 Z_t 服从简单的 AR(1) 过程:

Z_t = \rho Z_{t-1} + s \epsilon_t, \ \epsilon_t \sim N(0,1) \tag{3.1.4}

其中,s>0 为扰动参数,1>\rho>0 为外生冲击持续性参数,越接近于1,持续性越强。


(2) 模型求解

对问题 (3.1.1) 及其面临的约束进行求解(对于离散的无穷贴现问题,统一采用\text{Lagrange}方法求解,统一记\text{Lagrange Function}L ),可以得到关于 C_tL_t\text{F.O.C}为:

\frac{(C_t ^\theta(1-L_t) ^{1-\theta})^{1-\tau}}{C_t} \\ = \beta E_t \left( \frac{(C_{t+1} ^\theta(1-L_{t+1}) ^{1-\theta})^{1-\tau}}{C_{t+1}}(1+\alpha\exp(Z_t) K_{t+1}^{\alpha-1} L_{t+1}^{1-\alpha} - \delta) \right) \tag{3.1.5}

\frac{1-\theta}{\theta} \frac{C_t}{1-L_t} = (1-\alpha)\exp(Z_t) K_t^\alpha L_t^{-\alpha} \tag{3.1.6}

因此,模型的均衡由5个内生变量\{C_t,L_t,K_t,Z_t,I_t\},以及下面5个均衡方程构成:

  1. Euler方程\frac{\partial L^H}{\partial C_t} = 0(3.1.5)

  2. 劳动供给方程\frac{\partial L^H}{\partial L_t} = 0(3.1.6)

  3. 资源约束方程:(3.1.2)

  4. 资本积累方程:(3.1.3)

  5. 技术变量的 AR(1) 过程: (3.1.4)

3.2 Dynare内生变量的分类和书写规范

3.2.1 Dynare内生变量的分类

在Dynare中,内生变量根据时间下标被分成4类,如下表(3.1)所示:

内生变量类型 定义 内生变量个数存储位置
静态变量 仅仅出现时间下标 t M._nstatic
前向变量 仅仅出现时间下标 tt+1 M._nfwrd
后向变量 仅仅出现时间下标 tt-1 M._npred
混合变量 同时出现 tt+1t-1 M._nboth

针对第3.1节的简单模型,可以观察均衡条件,并对模型变量\{C_t,L_t,K_t,Z_t\}进行归类:

  • C_tL_t 都仅出现了 tt+1,属于前向变量

  • Z_t 属于标准的后向变量

  • I_t 属于标准的静态变量

  • 存量变量比较特殊:虽然存量变量出现了tt+1,但存量变量是在 t 期末被决定,故属于后向变量。所以在Dynare编程中,K_{t+1}K_t 要写成 K_tK_{t-1} (在3.1.2节会解释!)

按照效用函数的不同设定,在通常情况下,如果:

  • 效用函数为 C_tL_t 的可加可分函数时,L_t 为静态变量

  • 效用函数为 C_tL_t 的不可分函数时,L_t 为非静态变量

  • 效用函数引入消费习惯的设定,C_t 变为混合变量

一般而言,内生变量只能属于上述4种变量的其中一类,所以上述的分类是内生变量类型的一个完全划分。从而4种内生变量个数之和为整个模型所有内生变量个数(M._endo_nbr),即:

\text{M._endo_nbr} \equiv \text{M._nstatic} + \text{M._nfwrd} + \text{M._npred} + \text{M._nboth}

一般而言,模型中内生状态变量的个数(M._nspred)为后向变量和混合变量的个数之和:
\text{M._nspred} \equiv \text{M._npred} + \text{M._nboth}

此外,相对于静态变量而言,另外三者统称为动态变量(M._ndynamic),有:

\text{M._ndynamic} \equiv \text{M._nfwrd} + \text{M._npred} + \text{M._nboth}

关于本节关于变量的逻辑,可以归类在图3.1中:


3.1.2 Dynare内生变量的书写规范

(1) 命名规范

Dynare运行在Matlab以上,内生变量规范要遵循Matlab的命名规范,一般:

  1. 尽量不要使用Matlab和Dynare内置函数的名字作为变量

  2. 不要在变量或参数中包含特殊字符

  3. Dynare对变量是大小写敏感的

  4. 尽量不要使用小写字母i,以免与Matlab的复数单位 i 混淆

(2) 时间下标约定

在Dynare中,变量的下标是根据该变量的决定时期来确定的。一般来说, t 期变量(流量变量)是由 t-1 期的变量(内生和外生变量)和 t 期初实现的外生冲击共同决定的。所以,从这个意义上说,存量变量(Stock Variables)t 期末被决定,或者说在流量变量决定后再决定。一个经典的例子就是资本存量,根据:

K_{t+1} = I_t + (1-\delta)K_t

投资 I_tt 期被决定,从而 K_{t+1} 形式上虽然是 t+1 期变量,本质上是 t+1预先决定的变量,它是在 {t} 期末就被决定的,因此也被写成:

K_{t} = I_t + (1-\delta)K_{t-1}

从而,时期 t 可以虚拟地看成是由三部分构成:

  • 初期:外生冲击实现

  • 中期:当期变量决定

  • 期末:存量变量决定

在Dynare编程中,对各种时间下标的语法见下表(3.2):

变量形式 书写形式
x_{t+2} x(+2),x(2)
x_{t+1} x(+1),x(1)
x x
x_{t-1} x(-1)
x_{t-2} x(-2)

只有极少数的情况下会出现 t+2t-2 期的情况。如果出现,Dynare会自动引入辅助变量(Auxiliary Variables),无需编程者操心。


3.2.3 Dynare内生变量的排序

在Dynare中,有两种内生变量的排序,用于不同的场合:

  • 声明顺序:根据模型文件书写时 var 命令的先后次序排序,例如:
 var c k lab z I;

就表示内生变量按照 C_t, K_t, L_t, Z_t,I_t 的顺序出存在 \text{M._endo_names}

  • 决策规则顺序:首先是静态变量,然后后向变量,然后混合变量,最后前向变量;同一种变量的排序按照声明顺序排列

3.3 Dynare文件基本结构

由于Dynare语法规则多,并且随着版本更新会删除和新增一些命令,教材只罗列了常用的语法规则。一般来说,一个模型文件(*.mod)由5个部分组成:

  1. 前导部分(Preamble)

  2. 模型声明部分(Model)

  3. 稳态值或初始值声明部分(Steady state or initial values)

  4. 外生冲击声明部分(Shocks)

  5. 模型计算部分(Computation)

下面会逐一讲解。


3.3.1 前导部分

这里主要完成模型声明的前期准备工作,包括3个部分:

  1. 内生变量声明(var命令)

  2. 外生变量声明(varexo命令)

  3. 参数声明(parameters命令)

  4. 参数赋值(直接赋值)

针对第一节的模型,对应模型文件的前导部分可以写成源代码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;   

前导部分的三个声明命令 varvarexoparameters是可以在一个*.mod文件中反复使用的,这样可以提高模型文件的可读性。Dyanre会自动处理,无需编者操心。


3.3.2 模型部分

在结束前面的前导部分声明后,即可声明模型部分,即模型的各个均衡条件。模型部分以model;开始,以end;结束,在两个命令之间输入均衡条件,每个均衡条件以;结束。均衡条件太长时,可以跨行书写。

例如,对3.1节的RBC模型书写模型部分,如源代码10所示:

%----- 源代码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 参数估计简介”中介绍

三种不同的计算命令各有区别。粗略地说,simulstoch_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');

执行模型文件,输出脉冲响应图像:


上述模型文件的IRF图像
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,000评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,745评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,561评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,782评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,798评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,394评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,952评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,852评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,409评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,483评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,615评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,303评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,979评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,470评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,571评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,041评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,630评论 2 359