前置条件与学习依赖 / PREREQUISITES
数学 / 统计基础非线性方程组求根、Newton-Raphson 迭代原理、MATLAB fsolve / Python scipy.optimize 的调用与初值敏感性。
经济学理论前置一个完整 NK/RBC 模型的全部 FOC(去掉时间下标即稳态系统);理解为何可把 $Y=C=N=1$ 归一。
软件 / 计算前置MATLAB(fsolve)或 Python(scipy.optimize.fsolve);Dynare 的 steady / steady_state_model 块。
站内前置页面先学 02-first-order-conditions:有了 FOC 才能组装稳态方程组。
难度与路线位置进阶数值求解第一道坎,是 04 对数线性化的前置。
📚 基础知识库 · 本页定位

本页是 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$ 满足:

Steady State 的定义
$$f(\bar x, \bar x, \bar x, 0) = 0$$

在 DSGE 中稳态之所以重要,原因有三:

作用 1:log-linearization 的展开点
所有 $\hat x_t\equiv\ln x_t-\ln\bar x$ 都要以 $\bar x$ 为基准。稳态求错了,整个对数线性化系统就是错的。
作用 2:参数校准的锚
许多参数不是"从微观数据估出来",而是"从稳态反推"。例如 $\beta$ 由稳态实际利率 $\bar r$ 反推:$\beta=1/(1+\bar r)$。
作用 3:Dynare 求解的初值
Dynare 跑 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^{-\sigma} = \beta E_t\left[C_{t+1}^{-\sigma}(1+r_t)\right]$$

稳态下 $C_t=C_{t+1}=\bar C$,$E_t$ 消失:

代入稳态
$$\bar C^{-\sigma} = \beta \bar C^{-\sigma}(1+\bar r)$$

两边约去 $\bar C^{-\sigma}$($\bar C>0$):

稳态实际利率
$$\boxed{\;1 = \beta(1+\bar r)\quad\Longrightarrow\quad \bar r = \frac{1}{\beta}-1\;}$$

季度 $\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$,故:

稳态名义利率
$$\bar i = \bar r = \frac{1}{\beta}-1$$

2.3 资源约束与生产函数

市场出清 $Y_t=C_t$,稳态下:

资源约束
$$\bar Y = \bar C$$

生产函数 $Y_t=A_t N_t^{1-\alpha}$,稳态 $A=1$:

生产函数(稳态)
$$\bar Y = \bar N^{1-\alpha}$$

2.4 劳动供给方程

上一页推出来的劳动供给 $N_t^\varphi C_t^\sigma = w_t$,稳态:

稳态实际工资
$$\bar N^{\varphi}\,\bar C^{\sigma} = \bar w$$

2.5 实际边际成本与加成

在零通胀稳态,Calvo 摩擦完全消失(每期都有 $1-\theta$ 厂商调价,最终 $P_t^*=P_t$),厂商按弹性价格下的 markup 定价:

稳态实际边际成本
$$\bar{mc} = \frac{1}{\mathcal{M}} = \frac{\varepsilon-1}{\varepsilon}$$

另一方面,从生产函数 $Y=N^{1-\alpha}$ 推出的实际边际成本(上一页 §4.2):

mc 的生产侧表达式
$$mc_t = \frac{w_t}{(1-\alpha)A_t N_t^{-\alpha}}$$

稳态下 $A=1$,代入 $\bar{mc}=(\varepsilon-1)/\varepsilon$:

稳态实际工资(生产侧)
$$\bar w = (1-\alpha)\bar{mc}\,\bar N^{-\alpha} = (1-\alpha)\frac{\varepsilon-1}{\varepsilon}\,\bar N^{-\alpha}$$

2.6 联立求解 $\bar N$

把"劳动供给侧"和"生产侧"的 $\bar w$ 联立:

联立方程
$$\bar N^{\varphi}\,\bar C^{\sigma} = (1-\alpha)\frac{\varepsilon-1}{\varepsilon}\,\bar N^{-\alpha}$$

用 $\bar C=\bar Y=\bar N^{1-\alpha}$ 把 $\bar C$ 换掉:

代入 C = N^{1-alpha}
$$\bar N^{\varphi}\cdot \left(\bar N^{1-\alpha}\right)^{\sigma} = (1-\alpha)\frac{\varepsilon-1}{\varepsilon}\,\bar N^{-\alpha}$$

左边指数相加:$\varphi + (1-\alpha)\sigma$;把右边 $\bar N^{-\alpha}$ 移到左边:

合并指数
$$\bar N^{\,\varphi+(1-\alpha)\sigma+\alpha} = (1-\alpha)\frac{\varepsilon-1}{\varepsilon}$$

解出 $\bar N$:

一般解
$$\bar N = \left[(1-\alpha)\frac{\varepsilon-1}{\varepsilon}\right]^{\frac{1}{\varphi+(1-\alpha)\sigma+\alpha}}$$

03 归一化:为什么 $Y=C=N=1$

上面的一般解 $\bar N$ 不是 1。但本工作站要求的零通胀稳态是 $\bar Y=\bar C=\bar N=1$。这是 DSGE 文献里的一个标准归一化(normalization)技巧,做法是在效用函数的劳动负效用项里加一个缩放系数 $\chi$:

带缩放系数的效用
$$U(C_t,N_t)=\frac{C_t^{1-\sigma}}{1-\sigma}-\chi\,\frac{N_t^{1+\varphi}}{1+\varphi}$$

此时劳动供给方程变成:

修正后的劳动供给
$$\chi\,\bar N^{\varphi}\,\bar C^{\sigma} = \bar w$$

联立后:

含 chi 的解
$$\chi\,\bar N^{\varphi+(1-\alpha)\sigma+\alpha} = (1-\alpha)\frac{\varepsilon-1}{\varepsilon}$$

选择 $\chi$ 使得 $\bar N=1$

归一化
$$\chi = (1-\alpha)\frac{\varepsilon-1}{\varepsilon}$$

代入 $\alpha=0.25, \varepsilon=9$:$\chi = 0.75\times 8/9 = 2/3 \approx 0.667$。这就是 Galí (2015) 在第三章脚注里做的归一化。归一化后稳态解极为干净:

零通胀归一化稳态
$$\boxed{\;\bar N=1,\qquad \bar Y=\bar C=1,\qquad \bar w=1,\qquad \bar{mc}=\frac{\varepsilon-1}{\varepsilon},\qquad \bar r=\bar i=\frac{1}{\beta}-1,\qquad \bar\pi=0\;}$$
为什么要归一化?

因为稳态的"水平值"本身没有经济含义——真正有含义的是变量围绕稳态的偏离 $\hat x_t=\ln x_t-\ln\bar x$。把 $\bar N=1$ 选成 1,对数偏离就是百分比偏离,论文里画图、写系数都方便。这相当于把"工作小时数的单位"选成了"稳态年工时"。

04 数值求解:MATLAB fsolve

当模型扩展到含资本、含调整成本、含多种冲击时,解析解往往求不出来。这时用 MATLAB 的 fsolve 数值求解。下面是 baseline 模型的 fsolve 完整代码。

matlab · solve_ss.m
% ============================================================
% 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 块解耦,改方程时容易同步。

dynare · baseline_nk_ss.mod(含 steady_state_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);
steady_state_model 块的纪律

① 块内每一行是一条赋值(=号两边),不是方程;② 必须按因果顺序写:先写外生归一化的(pi=0),再写从它推出的(r=1/beta-1);③ 所有 var 声明的变量必须在块内出现一次,否则 Dynare 报警告 "The following variable(s) have no steady state"。

06 稳态初值设定技巧

当模型复杂到写不出解析稳态时,Dynare 会调用数值求解器(基于 steady; 后的 initial guess)。初值 guess 的好坏直接决定能否收敛。下面是经过大量项目验证的技巧:

技巧 1:先写解析稳态,再让 Dynare 解
即使模型复杂,也尽量在 paper 附录里手推解析稳态。把解析稳态写进 steady_state_model;,而不是让 Dynare 数值猜。这样每次改参数,稳态可复现、可审计。
技巧 2:外生过程稳态 = 0
AR(1) 过程 $x_t=\rho x_{t-1}+\varepsilon_t$ 的稳态是 $\bar x=0$(因为冲击 $\varepsilon$ 均值为 0)。所以技术水平 $A$ 的稳态设为 1(水平值)或 0(对数偏离),不要设成别的。
技巧 3:利率类变量从 beta 反推
所有"利率"类变量初值:$\bar r=1/\beta-1$,$\bar i=\bar r+\bar\pi$。不要凭感觉写 0.01 或 0.05。
技巧 4:规模类变量从生产函数反推
$Y, C, N, K$ 等规模变量,用 §2 的联立公式写,不要全写 1。例如含资本的模型 $\bar K/\bar Y=\frac{\delta}{\alpha(1/\beta-1+\delta)}$,代入参数直接算。
技巧 5:不收敛时先检查方程数量
Dynare 报 "Impossible to find the steady state" 时,90% 是 model 块方程数量与 var 数量不一致,或某条方程有除零。先把 options_.debug=1; 打开看残差。
Dynare 找不到稳态时的诊断顺序

① 跑 steady; 看哪条方程残差最大;② 检查 model 块里是不是把 A(+1) 写成了 A(1);③ 检查有没有变量在 model 块里从没出现(声明了但没用);④ 把 qz_zero_threshold 临时调大;⑤ 实在不行,用外部 fsolve 算稳态,再用 initval; 块把数值喂给 Dynare。

07 论文案例与常见错误

7.1 论文案例(英文经典)

English · 教材
Monetary Policy, Inflation, and the Business Cycle, Ch. 3.5: "The Steady State"
Jordi Galí, Princeton UP, 2015 (2nd ed.)
Galí 教材 §3.5 完整推导出 baseline NK 模型零通胀稳态(eq. 3.20—3.24),并讨论了"为什么把稳态就业率归一化为 1"。本工作站 §2、§3 的推导与其完全对应。
English · AER
Shocks and Frictions in US Business Cycles: A Bayesian DSGE Approach, Appendix A: "Steady State"
Frank Smets & Rafael Wouters, AER, 2007, 97(3)
SW 模型稳态比 baseline 复杂得多:含资本、habit、wage markup。其附录 A 把稳态解析公式逐条列出,是"复杂模型如何求稳态"的范本。读其附录 A 前两页即可。

7.2 论文案例(中文顶刊)

中文 · 经济研究
预期与经济波动——预期冲击是驱动中国经济波动的主要力量吗?
庄子罐、崔小勇、龚六堂、邹恒甫,《经济研究》,2012 年第 8 期
论文第 3.2 节"参数校准"部分,把稳态资本产出比 $\bar K/\bar Y$ 用中国宏观数据校准(约 2.2),再反推折旧率 $\delta$。是"从稳态矩反推参数"的标准做法。
中文 · 金融研究
我国DSGE模型的开发及在货币政策分析中的应用
刘斌,《金融研究》,2008 年第 10 期
论文表 1 列出了所有参数的校准值与稳态矩的对应关系。读其表 1 与脚注,看中国学者如何把稳态利率、稳态通胀、稳态资本产出比校准到中国数据。

7.3 稳态阶段的常见错误(≥3 条)

错误 1:忘记归一化系数 $\chi$

按用户给出的效用函数 $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。

错误 2:稳态通胀设错

零通胀稳态 $\bar\pi=0$,但很多人误写成 $\bar\pi=1$(因为 price level 增长了 1 倍)。$\pi_t$ 已经是对数通胀 $\ln(P_t/P_{t-1})$,稳态就是 0。

错误 3:利率没年化换算

Dynare 默认模型是季度模型,但论文图表是年化。季度稳态利率 $\bar r=0.01$,年化要乘 4 或写成 $400\times\bar r\%$。在写 steady_state_model; 时不要混用季度与年化。

错误 4:Steady state 写了但 initval 块没对应

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。