
简介DSGE模型动态随机一般均衡模型是宏观经济分析的重要工具常用于货币政策、财政政策等研究。这份基于Matlab IRIS工具箱的资源面向经济学、金融学、数学及相关工科专业学生尤其适合用于课程设计、期末大作业和毕业设计中的DSGE建模实践。资源共25个文件以18个m脚本/函数和6个model文件为主体附带1个md说明文档压缩包整体约20KB轻量但结构完整。m文件承担模型求解、参数设置与结果可视化model文件定义经济结构md文档则提供使用指引内容覆盖真实经济周期RBC和新凯恩斯NK系列典型模型分支代码采用参数化编写便于调整参数观察结果变化。同时提供案例数据可直接运行配合详细注释能帮助使用者快速上手并理解建模逻辑。目前已有79人学习下载适合具备一定Matlab和经济学基础的读者通过具体实例深入掌握DSGE模型的构建、验证与扩展方法。1. 为什么IRIS里的DSGE不是“打开即用”而是“搭建好了可直接改”第一次解压 DSGE_IRIS-master 时我习惯性地找数据表格或 GUI 界面结果只看到 README.md、RBC、NK_WAGE、NK_INV、NK_GOV、NK_TANK、NK_PRICE 这些目录以及一堆 .m 文件和 .mod 文件。真正把这些目录跑起来的不是双击而是 Matlab 命令行里的 model、sstate、solve、irf 这一串 IRIS 工具箱指令。IRIS 做的是把 DSGE 建模中变量声明、参数赋值、方程写入、稳态求解和线性近似这些步骤收编成一套声明式语法你在模型文件里写结构工具箱负责把它转成可求解的马尔可夫系统。它对“能打开”的定义是严格的Matlab 版本和 IRIS 版本必须匹配mex 文件必须能被当前架构直接调用模型文件里的每个变量和每个方程必须严格对齐。这篇帖子按 DSGE_IRIS-master 的实际使用顺序先把文件结构讲清楚然后给出不同 Matlab 版本下的安装验证方法再拆 NK_TANK 的参数化修改最后落到稳态求解失败的定位技巧。适用范围可以从本科课程设计到研究生论文基准模型关键是你得习惯从命令行而不是菜单栏去看结果。2. 模型语言与文件结构RBC和NK系列到底被拆成了什么2.1 IRIS把DSGE工程分成声明区、方程区和运行脚本IRIS 的模型文件通常采用 .mod 扩展名也有个别工程用 .model。我在实际项目里见过最多的是 .mod所以下面用它举例。一个最小的 RBC 模型文件会包含四个必须的声明区!variables 声明内生变量!parameters 声明参数!shocks 声明外生冲击!equations 写经济系统的一阶条件和均衡条件。IRIS 按变量在声明区里出现的顺序给变量编号方程区里的每个方程会和一个内生变量自动配对这意味着变量顺序不能随便改否则后续显示的脉冲响应图会变成另一套顺序。这个设计初看是限制实际是保障它迫使你在写方程之前先把模型分类理清而不是像手写线性化系统那样自己维护变量索引表。!variables y, c, i, k, a, r !parameters beta, alpha, delta, rho, sigma_a !shocks eps_a !equations y a * k(-1)^alpha; c i y; k (1-delta) * k(-1) i; a rho * a(-1) eps_a; r beta * (c/c(-1))^(-1) * (alpha * y(1)/k (1-delta));这段代码是用典型写法还原的 RBC 骨架不是 DSGE_IRIS-master 里某一文件原样。注意方程里的 k(-1) 表示 t-1 期资本y(1) 表示 t1 期产出。IRIS 用括号而不是下标来表示时滞和前瞻这是它的模型语言和 Dynare 最明显的差别。方程区的最后一行是欧拉方程写成消费跨期替代与资本边际收益的关系IRIS 会自动对变量做线性展开不需要你事先推导出完整的 log-linear 系统。参数 alpha 和 delta 控制稳态资本比beta 直接影响利率rho 和 sigma_a 决定技术冲击的持续性和波动幅度。加载时在命令窗口执行m model(rbc.mod)IRIS 就会检查方程个数与内生变量个数是否一致并在模型对象 m 里保存全部声明信息。2.2 从DSGE_IRIS-master能认出哪些标准模型DSGE_IRIS-master 的子目录结构其实已经暴露了模型演化主线。RBC 是底层的实际经济周期模型没有名义摩擦适合做新人的第一个对象NK_PRICE 加入 Calvo 价格粘性是理解货币政策传导的入门款NK_WAGE 再把工资设定摩擦放进去这时消费与劳动替代弹性都会影响工资加成NK_INV 调整的是投资调整成本通常带着二次型调整成本参数NK_GOV 加入政府购买和财政融资方式适合做财政乘数实验NK_TANK 对应的是 TANK 模型把家庭分成能进入资产市场的高资产家庭和完全按当期收入消费的流动性约束家庭。这个家族关系从 IRIS 的写法上看得更清楚摩擦项往往就是方程区里多一行、!parameters 里多两个参数所以从 RBC 到 NK_TANK 的跳跃没有想象中那么大。目录/模型主要摩擦最值得关注的参数区RBC无名义摩擦仅技术冲击alpha, delta, rho, sigma_aNK_PRICECalvo 价格粘性theta_p, kappa_pNK_WAGE工资粘性 价格粘性theta_w, kappa_w, 家庭劳动替代弹性NK_INV投资调整成本phi_i, deltaNK_GOV政府购买冲击与融资gy, rho_gNK_TANK两类家庭流动性约束家庭占比lambda_tank这张表是读 README.md 和打开 mod 文件前的快速索引。我一般会先搜索一下 !parameters 块里有没有 theta_w、phi_i、lambda_tank 这类特征参数再决定从哪个模型开始改。如果你只做技术冲击的 IRFRBC 够用如果课程设计要求包含价格粘性下的货币政策分析直接进入 NK_PRICE 或者 NK_TANK 更合适。需要注意IRIS 不要求参数名必须用上面这些符号每个工程作者都有自己的命名习惯所以先跑通模型的原始状态再按你要研究的渠道去改而不是一上来就重建文件。2.3 先跑通模型解析再谈稳态拿到模型文件后不要急着去读几百行方程先在命令窗口执行 model 加载。加载成功并打印变量、参数和方程数说明这个工程至少没有语法层面问题。接着用 check(m) 让 IRIS 检查每个方程是否都分配到了唯一的内生变量再用 sstate(m) 求稳态。这里有一个常见的失败模式模型文件本身语法正确但稳态需要给定合理初值IRIS 默认从 0 出发对包含对数变量或比率变量的模型会直接报“Cannot find a steady state”。所以模型解析通过不等于模型可求解你需要把 solve 放在 sstate 之后顺序反了经常得到发散的解。这一节先记住这个顺序model → assign → sstate → solve → irf。3. Matlab 2014到2024a之间装对IRIS工具箱并跑通第一个案例3.1 版本匹配旧Matlab与新IrisT的兼容边界IRIS 工具箱在长期维护中经历过一次明显的改名早期版本由 irisstartup.m 启动后来演变成 iris.startup。这个改动直接影响你在不同 Matlab 版本下的安装方式。DSGE_IRIS-master 这类目录名常出现在较早期的 IRIS 工程中如果你手里的 Matlab 是 2014a用老版本 IRIS 会非常省事如果工作环境是 2019a老版本和新版 IrisT 共存的可能性存在但需要仔细对照 release note到 2024a 时要优先考虑新版 IrisT因为新版本 Matlab 对旧版 mex 文件的兼容性收得很紧经常出现类似 Invalid MEX-file 的错误。这个错误不是模型写错而是 IRIS 自带的二进制文件是用旧编译器生成的Matlab 无法在当前动态库里加载它。ver(iris)在命令窗口先执行这个命令确认当前 IRIS 是否已经被识别。如果返回空矩阵说明工具箱路径没有加进去如果提示找不到对应目录说明 Matlb 的搜索路径里完全没有 IRIS。别把 ver 返回的 IRIS 版本和模型文件里的 DSGE 版本混为一谈前者是工具箱本身的版本号后者是模型按经济理论分代的信息。3.2 安装步骤以DSGE_IRIS-master目录为例先把压缩包解压到没有空格的路径我习惯把 DSGE_IRIS-master 直接放在一个总的工具目录下比如 D:\Tools\DSGE_IRIS-master这样 genpath 展开时不会踩到中文路径的坑。然后用下面这段启动逻辑替代手工 addpathtoolbox_path D:\Tools\DSGE_IRIS-master; if exist(fullfile(toolbox_path, irisstartup.m), file) addpath(toolbox_path); irisstartup; elseif exist(fullfile(toolbox_path, iris.startup.m), file) addpath(toolbox_path); iris.startup; else addpath(genpath(toolbox_path)); iris.startup; end这段代码不是让你在命令行手工操作而是建议把一个 start_iris.m 放到 Matlab 默认路径里每次开 Matlab 直接输入 start_iris。逻辑是先找老版入口 irisstartup.m找到就用老方式启动找不到再找新版入口 iris.startup.m两个都没有就退化为把整个目录递归加进路径再尝试新版启动。注意 addpath 后面建议用全路径不要用相对路径IRIS 启动脚本会自己判断当前目录和工具箱根目录的关系如果你用 cd 切到模型文件所在目录来运行 start_iris工具箱根目录的计算可能会错。参数上也不需要额外配置关键是 toolbox_path 必须指向 DSGE_IRIS-master 本身而不是它的上一级否则 genpath 会把不该加的东西也扫进来启动时间会明显变慢。启动完成后再执行一次 ver(iris)或者直接输入 iris.版本检查命令不同版本命令不一样但只要不再提示未定义就说明路径已经生效。如果你的 Matlab 是 2024a且 IRIS 在启动阶段打印了 mex 编译警告建议在工具箱根目录找带 mex 的编译脚本重新编译不要跳过这一步否则后面 solve 阶段会出现无法预测的崩溃。3.3 命令行验证模型加载、稳态检查和首次IRF安装完成后进入 NK_PRICE 或 RBC 目录用一段简短的验证脚本确认整个链路通cd(D:\Tools\DSGE_IRIS-master\NK_PRICE); m model(nk_price.mod); % 解析模型文件 m sstate(m); % 求稳态 m solve(m); % 一阶近似求解 irf(m, Range, 1:20); % 给1单位技术冲击并画IRFmodel 函数读文件时会输出变量列表、参数列表和方程数如果这里就报错优先看报错里提到的行号sstate 报错通常有两种一是初值问题二是某个参数导致方程无实数解solve 报错则集中在模型有单位根或变量顺序错位。irf 的 Range 参数是冲击发生后的期数这里设置 20 期默认脉冲是模型里声明的第一个冲击。如果想看财政冲击晚点在 assign 阶段修改冲击方差再用 Select 参数指定。首次验证最重要的目标是看到一张不报错的图而不是立刻判断参数是否符合直觉因为图的经济含义要在校准阶段才谈得上。4. 参数化编程把NK_TANK的校准值改成你自己的4.1 先找到!parameters、!shocks和方程里的对应关系打开 NK_TANK 对应的 mod 文件先不要读方程把 !parameters 块原样复制出来对照 README.md 里的参数说明逐个确认含义。IRIS 的参数化编程体现在两点一是参数可以在模型文件里赋初值二是模型对象可以用 assign 函数在内存里覆盖这些值不需要每次改文件。这就意味着你可以把模型文件当成一个模板把经验校准和模拟实验分成两层。我一般会先在 !parameters 块旁边用中文注释记录参数来源IRIS 兼容 UTF-8但要注意文件编码必须是 Matlab 能识别的格式否则注释乱码或变量名误读。常见参数名含义典型校准区间修改后的直接影响beta主观贴现因子0.96~0.995稳态利率和资本存量sigma相对风险厌恶系数1~3消费跨期替代弹性theta_wCalvo工资粘性概率0.5~0.9工资通胀惯性phi_i投资调整成本系数0~4投资对边际q的敏感度lambda_tank流动性约束家庭占比0~0.5财政乘数大小gy政府购买占总产出比例0.15~0.25稳态财政支出水平这张表里的具体名字不一定和 DSGE_IRIS-master 里逐字对应但思路一致先把每个参数的位置标出来再决定是调 beta 还是调 theta_w。调整参数前建议跑一次原始模型把所有 IRF 图存下来作为 baseline这样后面每次只改一个参数对比更干净。TANK 模型里最值得做的是把 lambda_tank 从 0 推到 0.3你会看到政府购买冲击对消费的响应出现明显翻转这正是 TANK 模型区别于 RANK 模型的核心。4.2 修改偏好、价格粘性和财政参数后重新求解模型文件里参数初值可以直接改也可以不改文件用 assign 覆盖。我倾向于不改文件里的初值而是把实验参数写在运行脚本里因为这样可以保留模型原始校准也方便批量跑。下面这段是从一个实际跑过的脚本里抽出来的核心部分m0 model(nk_tank.mod); m_base sstate(m0); m_base solve(m_base); % 实验1只把贴现因子调高 m1 assign(m0, beta, 0.995); m1 sstate(m1); m1 solve(m1); % 实验2高工资粘性 高流动性约束家庭比例 m2 assign(m0, {theta_w, lambda_tank}, {0.85, 0.3}); m2 sstate(m2); m2 solve(m2); irf(m1, Range, 1:30, Select, {eps_g}); figure; irf(m2, Range, 1:30, Select, {eps_g});assign 的第一个参数是模型对象第二个参数是参数名第三个参数是参数值。单个参数可以直接传字符和数值多个参数要用元胞数组包起来这样参数名和参数值能一一对应。Select参数指定只画 eps_g 冲击也就是 NK_TANK 里代表政府购买冲击的那个外生变量如果模型里定义的冲击名不是 eps_g可以从 !shocks 区块复制完整名称。IRF 的对比图里m1 的消费响应通常更平坦m2 则会在财政冲击后出现一段正消费响应原因是流动性约束家庭没有资产缓冲会把当期额外收入很快花掉。4.3 用脚本批量跑脉冲响应避免每个参数都开模型课程设计里经常需要画“不同参数取值下的IRF对比”逐个改参数再重新加载模型效率太低。更稳的做法是把参数组合放进一个循环利用 assign、sstate、solve 三条命令在内存里反复覆盖模型对象param_grid [0.985, 2.0, 0.75, 0.2; 0.990, 2.0, 0.75, 0.2; 0.990, 2.0, 0.85, 0.3; 0.995, 1.5, 0.85, 0.3]; labels {base,high_beta,sticky_wage_tank,low_sigma_tank}; irf_store struct(); for i 1:size(param_grid, 1) mi m0; mi assign(mi, {beta,sigma,theta_w,lambda_tank}, ... num2cell(param_grid(i,:))); mi sstate(mi); mi solve(mi); irf_store.(labels{i}) irf(mi, Range, 1:40, Select, {eps_a}); end这段代码的要点是每次循环都从 m0 这个原始模型重新开始避免上一次实验的参数污染下一次结果assign 右侧的 num2cell 把一行参数转成元胞数组正好对上左侧四个参数名。跑完之后检查 irf_store如果某个参数组合导致 sstate 报错Matlab 会中断循环这时把 try-catch 包在循环体里就能把失败的组合记录下来。注意 IRIS 的 irf 返回的是一个包含多个字段的结构体字段名对应变量名取数时要么直接画图要么把响应序列存下来自己拼数据表。参数化编程的收益在模型文件超过 100 行之后会非常明显你不需要去找第 47 行的常数只需要维护一张参数网格和一个循环。5. 收尾技巧把IRIS“稳态找不到”的报错变成可定位的问题5.1 先区分稳态数值问题还是模型设定问题IRIS 在 sstate 阶段报“Cannot find a steady state”时第一反应不是去调求解器而是先判断是哪种原因。数值原因通常是初值给得太远或者参数超出理论可行域模型设定原因是方程区里存在单位根、遗漏方程或变量顺序错位IRIS 会提示哪些方程没有收敛或者某个变量没有出现在任何方程里。我的做法是把 !parameters 块的参数全部恢复成原始值跑一遍 sstate如果原始参数能收敛而你的参数不能那就是参数问题如果原始参数本来也失败那问题出在模型文件或者路径配置而不是实验设置。这个对照实验能省掉至少一小时盲调。5.2 用!log_variables给稳态求解器降低难度IRIS 默认对变量求水平方程但技术冲击模型里产出、消费、投资都带增长趋势的近似。可以在模型文件声明区加入一块对数变量声明让 IRIS 在稳态求解时先做对数变换。!log_variables y, c, i, k, a把这段放到 !variables 之后、!parameters 之前IRIS 会优先对这几个变量取对数稳态方程组的搜索空间会从几十个量级范围缩到零点几到几之间。注意不要对利率、通胀率等本身已经是率变量的小数变量取对数那会让稳态初值变成负数反而更难收敛。加入后用 sstate(m0) 重新求一遍稳态再看 check 输出里每个方程的残差如果残差量级在 1e-6 以下说明求解成功如果还有个别方程残差偏高优先检查那个方程里的变量是否全部出现在 !log_variables 列表里或者是否存在 k(-1) 与 k 同时出现时初值不一致。IRIS 的日志面板里通常会给出去稳态失败时优化器迭代的路径沿着路径找是哪几个变量从一开就不动或发散比盯着报错字符串更有效。5.3 用网格扫描框定参数合法区间最后一个可复现的技巧把稳态失败当成参数扫描的一个结果而不是中断信号。用 try-catch 把 sstate 包起来循环扫描 beta 或 lambda_tank把能收敛的参数存进一个合法表把失败的参数记录到另一个数组。这样你就能得到一个“参数可行域”的概念而不是只知道某个点失败。把失败参数和收敛参数连同对应的 IRF 一起保存论文的稳健性检验部分直接用这一份循环结果就能画图。初始校准结果先存成 m_base.mat每轮循环开头用 load(m_base.mat) 回填模型对象再继续扫描下一个参数点这样即使 IRIS 中途抛出稳态异常你也能准确知道是哪一轮参数组合导致的。本文还有配套的精品资源点击获取