稳态求解:解析推导、fsolve 数值解与 Dynare steady_state_model
Steady state 是 DSGE 的"锚"。本页先解析求解零通胀稳态($Y=C=N=1, r=1/\beta-1$),再用 MATLAB fsolve 数值验证,最后写进 Dynare 的 steady_state_model 块。
本页是 DSGE 基础知识库页面。定位:先单独学会这个工具,再到模型分支里看它怎么用。不必一次学完所有分支——把"稳态求解"这门工具吃透后,再带着它去具体模型里查阅。
在哪些模型分支中使用:稳态是所有 DSGE 分支的"锚"—— RBC 基准模型 · NK 三方程 · 中尺度 SW · 小国开放经济 · 金融摩擦 BGG/GK · 财政与货币规则 · TANK两主体 · HANK · 适应性学习
01 什么是稳态 steady state
Steady state(稳态)是动态系统在没有任何外生冲击时,所有内生变量保持不变的那个点。正式地说,对一个由 $E_t f(x_{t+1}, x_t, x_{t-1}, \varepsilon_t)=0$ 描述的模型,稳态 $\bar x$ 满足:
在 DSGE 中稳态之所以重要,原因有三:
steady; 命令时,从你给的初值 guess 出发迭代求解。初值差太远,牛顿法就不收敛。本工作站 baseline 模型求的是零通胀稳态(zero-inflation steady state):外生技术 $A$ 归一化为 1,通胀 $\pi=0$,所有实际量 $Y,C,N,w$ 都为常数。
02 零通胀稳态:解析推导
把上一页推出来的 FOC 全部写下来,然后令 $C_t=C_{t+1}=\bar C$,$N_t=N_{t+1}=\bar N$,$\pi_t=\pi_{t+1}=0$,$A=1$。逐条推。
2.1 欧拉方程 → 实际利率
欧拉方程:
稳态下 $C_t=C_{t+1}=\bar C$,$E_t$ 消失:
两边约去 $\bar C^{-\sigma}$($\bar C>0$):
季度 $\beta=0.99$ 时,$\bar r\approx 0.0101$(季度),年化约 $4\%$,与 US 长期平均实际利率吻合。
2.2 Fisher 方程 → 名义利率
Fisher 方程 $r_t=i_t-E_t\pi_{t+1}$ 在零通胀稳态下 $\pi=0$,故:
2.3 资源约束与生产函数
市场出清 $Y_t=C_t$,稳态下:
生产函数 $Y_t=A_t N_t^{1-\alpha}$,稳态 $A=1$:
2.4 劳动供给方程
上一页推出来的劳动供给 $N_t^\varphi C_t^\sigma = w_t$,稳态:
2.5 实际边际成本与加成
在零通胀稳态,Calvo 摩擦完全消失(每期都有 $1-\theta$ 厂商调价,最终 $P_t^*=P_t$),厂商按弹性价格下的 markup 定价:
另一方面,从生产函数 $Y=N^{1-\alpha}$ 推出的实际边际成本(上一页 §4.2):
稳态下 $A=1$,代入 $\bar{mc}=(\varepsilon-1)/\varepsilon$:
2.6 联立求解 $\bar N$
把"劳动供给侧"和"生产侧"的 $\bar w$ 联立:
用 $\bar C=\bar Y=\bar N^{1-\alpha}$ 把 $\bar C$ 换掉:
左边指数相加:$\varphi + (1-\alpha)\sigma$;把右边 $\bar N^{-\alpha}$ 移到左边:
解出 $\bar N$:
03 归一化:为什么 $Y=C=N=1$
上面的一般解 $\bar N$ 不是 1。但本工作站要求的零通胀稳态是 $\bar Y=\bar C=\bar N=1$。这是 DSGE 文献里的一个标准归一化(normalization)技巧,做法是在效用函数的劳动负效用项里加一个缩放系数 $\chi$:
此时劳动供给方程变成:
联立后:
选择 $\chi$ 使得 $\bar N=1$:
代入 $\alpha=0.25, \varepsilon=9$:$\chi = 0.75\times 8/9 = 2/3 \approx 0.667$。这就是 Galí (2015) 在第三章脚注里做的归一化。归一化后稳态解极为干净:
因为稳态的"水平值"本身没有经济含义——真正有含义的是变量围绕稳态的偏离 $\hat x_t=\ln x_t-\ln\bar x$。把 $\bar N=1$ 选成 1,对数偏离就是百分比偏离,论文里画图、写系数都方便。这相当于把"工作小时数的单位"选成了"稳态年工时"。
04 数值求解:MATLAB fsolve
当模型扩展到含资本、含调整成本、含多种冲击时,解析解往往求不出来。这时用 MATLAB 的 fsolve 数值求解。下面是 baseline 模型的 fsolve 完整代码。
% ============================================================
% solve_ss.m —— 用 fsolve 数值求解 baseline NK 模型稳态
% 内生变量 x = [Y; C; N; w; mc; r; i; pi]
% ============================================================
clear; clc;
% --- 1. 校准参数 ---
p.beta = 0.99;
p.sigma = 1.0;
p.phi = 5.0;
p.alpha = 0.25;
p.eps = 9.0;
p.chi = (1-p.alpha)*(p.eps-1)/p.eps; % 归一化系数 -> N=1
% --- 2. 定义稳态方程组 ---
ss_eq = @(x) [
x(1) - x(2); % (1) Y = C
x(1) - x(3)^(1-p.alpha); % (2) Y = N^(1-alpha), A=1
p.chi*x(3)^p.phi * x(2)^p.sigma - x(4); % (3) 劳动供给: chi*N^phi*C^sigma = w
x(4) - (1-p.alpha)*x(5)*x(3)^(-p.alpha); % (4) mc = w / ((1-alpha)*N^(-alpha))
x(5) - (p.eps-1)/p.eps; % (5) 稳态加成 mc = (eps-1)/eps
1/p.beta - (1+x(6)); % (6) 欧拉: 1 = beta*(1+r)
x(7) - x(6) - x(8); % (7) Fisher: i = r + pi
x(8) % (8) 零通胀稳态 pi = 0
];
% --- 3. 初值 guess ---
x0 = [1; 1; 1; 1; (p.eps-1)/p.eps; 1/p.beta-1; 1/p.beta-1; 0];
% --- 4. fsolve 求解 ---
opts = optimoptions('fsolve','Display','iter','TolFun',1e-10);
[x, fval, exitflag] = fsolve(ss_eq, x0, opts);
% --- 5. 输出 ---
fprintf('\n===== 稳态解 =====\n');
fprintf('Y = %.6f\n', x(1));
fprintf('C = %.6f\n', x(2));
fprintf('N = %.6f\n', x(3));
fprintf('w = %.6f\n', x(4));
fprintf('mc = %.6f\n', x(5));
fprintf('r = %.6f (年化 %.4f%%)\n', x(6), 4*x(6)*100);
fprintf('i = %.6f\n', x(7));
fprintf('pi = %.6f\n', x(8));
fprintf('残差范数 = %.2e\n', norm(fval));
运行结果应该是:$Y=C=N=w=1$,$mc=8/9\approx 0.8889$,$r=i=0.0101$,$\pi=0$,残差接近 $10^{-10}$。如果初值给得离谱(例如 $x_0(3)=100$),fsolve 可能收敛到另一个根或不收敛——这就是为什么需要 §6 的初值技巧。
05 Dynare steady_state_model 块写法
Dynare 提供 steady_state_model; 块让你直接写出稳态变量的解析表达式。它的优点:① Dynare 跑 steady; 时不用做迭代,直接算;② 与 model 块解耦,改方程时容易同步。
% ============================================================
% baseline_nk_ss.mod —— 完整可运行的 baseline NK 模型
% ============================================================
// ---------- 变量 ----------
var Y C N w mc r i pi y_gap;
varexo eps_a eps_m;
// ---------- 参数 ----------
parameters beta sigma phi alpha eps_p chi kappa rho_a rho_i phi_pi phi_y;
beta=0.99; sigma=1.0; phi=5.0; alpha=0.25;
eps_p=9.0;
chi = (1-alpha)*(eps_p-1)/eps_p; % 归一化 -> N_ss = 1
kappa = (1-0.75)*(1-beta*0.75)/0.75 * (sigma+phi); % theta=0.75
rho_a=0.9; rho_i=0.8; phi_pi=1.5; phi_y=0.125;
// ---------- 模型方程(对数线性化后)----------
model;
y_gap = y_gap(+1) - (1/sigma)*r;
r = i - pi(+1);
pi = beta*pi(+1) + kappa*y_gap;
i = rho_i*i(-1) + (1-rho_i)*(phi_pi*pi + phi_y*y_gap) + eps_m;
end;
// ---------- 稳态(关键块)----------
steady_state_model;
% --- 零通胀归一化稳态 ---
pi = 0;
r = 1/beta - 1;
i = r;
N = 1;
Y = N^(1-alpha); % = 1
C = Y;
w = N^phi * C^sigma / chi; % 注意归一化 chi
mc = (eps_p-1)/eps_p;
y_gap = 0;
end;
// ---------- 冲击 ----------
shocks;
var eps_a; stderr 0.01;
var eps_m; stderr 0.0025;
end;
// ---------- 求解 ----------
steady;
check;
stoch_simul(irf=20, nograph);
① 块内每一行是一条赋值(=号两边),不是方程;② 必须按因果顺序写:先写外生归一化的(pi=0),再写从它推出的(r=1/beta-1);③ 所有 var 声明的变量必须在块内出现一次,否则 Dynare 报警告 "The following variable(s) have no steady state"。
06 稳态初值设定技巧
当模型复杂到写不出解析稳态时,Dynare 会调用数值求解器(基于 steady; 后的 initial guess)。初值 guess 的好坏直接决定能否收敛。下面是经过大量项目验证的技巧:
steady_state_model;,而不是让 Dynare 数值猜。这样每次改参数,稳态可复现、可审计。options_.debug=1; 打开看残差。① 跑 steady; 看哪条方程残差最大;② 检查 model 块里是不是把 A(+1) 写成了 A(1);③ 检查有没有变量在 model 块里从没出现(声明了但没用);④ 把 qz_zero_threshold 临时调大;⑤ 实在不行,用外部 fsolve 算稳态,再用 initval; 块把数值喂给 Dynare。
07 论文案例与常见错误
7.1 论文案例(英文经典)
7.2 论文案例(中文顶刊)
7.3 稳态阶段的常见错误(≥3 条)
按用户给出的效用函数 $U=C^{1-\sigma}/(1-\sigma)-N^{1+\varphi}/(1+\varphi)$ 直接求稳态,得到的 $\bar N$ 不是 1(数值大约是 $(0.75\times 8/9)^{1/(5+0.75+0.25)}\approx 0.93$)。这时如果你硬把 $\bar N=1$ 写进 steady_state_model;,model 块残差不会为 0。正确做法:要么按本工作站 §3 引入 $\chi$ 归一化,要么按一般解 $\bar N=0.93$ 写进 steady_state_model。
零通胀稳态 $\bar\pi=0$,但很多人误写成 $\bar\pi=1$(因为 price level 增长了 1 倍)。$\pi_t$ 已经是对数通胀 $\ln(P_t/P_{t-1})$,稳态就是 0。
Dynare 默认模型是季度模型,但论文图表是年化。季度稳态利率 $\bar r=0.01$,年化要乘 4 或写成 $400\times\bar r\%$。在写 steady_state_model; 时不要混用季度与年化。
Dynare 4.x+ 中,如果你写了 steady_state_model;,就不需要再写 initval;。同时写两块会冲突,Dynare 优先用 initval。建议二选一,新项目统一用 steady_state_model;。
7.4 进阶
- 下一步:05 · log-linearization(对数线性化),把本页求出来的稳态 $\bar x$ 作为展开点。
- Dynare 手册 Ch. 4 "The steady state file" 讲复杂模型稳态求解的工程化做法。
- 当模型有多个稳态(multiple steady states)时,需要用 continuation method(同伦法),参阅 Juillard (2006) 的 Dynare technical guide。