From 1d84faa24c19ab4fded0f6e433fe727002129398 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:13 +1000 Subject: [PATCH 01/21] Update translation: lectures/phillips_adaptive.md --- lectures/phillips_adaptive.md | 476 ++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 lectures/phillips_adaptive.md diff --git a/lectures/phillips_adaptive.md b/lectures/phillips_adaptive.md new file mode 100644 index 0000000..09dd8b3 --- /dev/null +++ b/lectures/phillips_adaptive.md @@ -0,0 +1,476 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 适应性预期与费尔普斯问题 + headings: + Overview: 概览 + Adaptive expectations: 适应性预期 + The Phelps problem: 费尔普斯问题 + The Phelps problem::Casting the problem in LQ form: 将问题转化为 LQ 形式 + The Phelps problem::A proposition: 一个命题 + Disinflation paths: 反通货膨胀路径 + The general Phelps problem: 一般化的费尔普斯问题 + Testing the natural-rate hypothesis: 检验自然率假说 + Sacrifice ratios and the subversion of the Phelps model: 牺牲率与费尔普斯模型的颠覆 + Exercises: 练习 +--- + +(phillips_adaptive)= +```{raw} jupyter +
+ + QuantEcon + +
+``` + +# 适应性预期与费尔普斯问题 + +```{contents} Contents +:depth: 2 +``` + +除了 Anaconda 中已有的库之外,本讲座还将使用以下库: + +```{code-cell} ipython3 +:tags: [hide-output] + +!pip install quantecon +``` + +## 概览 + +> 他们无法望向远方, +> 他们无法看透深处, +> 但这何时曾是 +> 他们守望的障碍? +> +> ——罗伯特·弗罗斯特 + +本讲座延续了 {doc}`phillips_credibility` 中开始研究的菲利普斯曲线权衡关系。 + +本讲座遵循 {cite}`Sargent1999` 第 5 章的内容。 + +我们将描述: + +* 凯根-弗里德曼适应性预期假设, +* {cite}`Phelps1967` 如何用它来构建一个政府控制问题,以及 +* 适应性预期在早期自然率假说计量经济学检验中所起的作用。 + +其核心对象是**费尔普斯问题**:一个理性的政府在解决一个最优控制问题,而公众则用一个固定的、机械式的适应性法则来预测通货膨胀。 + +与 {doc}`phillips_credibility` 中的单期模型不同,现在政府考虑到经济会持续多个时期,并且今天的通货膨胀会影响明天的预期。 + +这种跨期联系可以改善结果,在极限情形下,甚至能维持拉姆齐结果。 + +费尔普斯问题是一个线性二次型(LQ)控制问题,因此我们用 QuantEcon 的 {doc}`LQ 控制 ` 工具来求解它。 + +让我们从一些导入开始: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +import quantecon as qe +``` + +## 适应性预期 + +{cite}`Phelps1967` 为一个自然率模型构建了一个控制问题。 + +他放弃了公众的理性预期假设,但保留了政府的理性预期,并给公众分配了一个特定的机械式预测法则,而这个法则是政府已知的。 + +公众使用米尔顿·弗里德曼和 {cite}`Cagan` 的适应性预期方案: + +```{math} +:label: pa_adaptive + +x_t - x_{t-1} = (1 - \lambda)(y_{t-1} - x_{t-1}), \qquad \lambda \in (0, 1), +``` + +其中 $x_t$ 是公众对通货膨胀的预期,$y_t$ 是通货膨胀率。 + +重新整理后得到 $x_t = \lambda x_{t-1} + (1 - \lambda) y_{t-1}$,因此预期通货膨胀是过去通货膨胀的几何分布滞后, + +```{math} +:label: pa_geom + +x_t = (1 - \lambda) \sum_{i=1}^{\infty} \lambda^{i-1} y_{t-i} . +``` + +注意,{eq}`pa_adaptive` 是 {doc}`phillips_credibility` 中最小二乘学习算法的一个*常数增益*版本,其中常数 $(1 - \lambda)$ 起到了那里递减增益 $t^{-1}$ 所起的作用。 + +方程 {eq}`pa_geom` 具有一个**归纳性质**:如果政府持续重复一个恒定的 $y_t = \tilde y$ 政策,最终公众会逐渐将 $x_t \approx \tilde y$ 作为其预期。 + +权重 $(1 - \lambda)\lambda^{i-1}$ 之和为一,因此一个永久维持的通货膨胀率最终会被完全预期到。 + +让我们用数值方法验证这个归纳性质。 + +```{code-cell} ipython3 +def adaptive_forecast(y, λ, x0=0.0): + "Simulate x_t = λ x_{t-1} + (1-λ) y_{t-1}." + T = len(y) + x = np.empty(T) + x[0] = x0 + for t in range(1, T): + x[t] = λ * x[t - 1] + (1 - λ) * y[t - 1] + return x + +T = 60 +y_const = np.full(T, 10.0) # a constant inflation policy + +fig, ax = plt.subplots(figsize=(9, 4.5)) +for λ in [0.7, 0.9]: + x = adaptive_forecast(y_const, λ) + ax.plot(x, lw=1.5, label=rf'$\lambda = {λ}$') +ax.axhline(10.0, color='k', ls='--', lw=1, label='policy $\\tilde y$') +ax.set_xlabel('$t$') +ax.set_ylabel('expected inflation $x_t$') +ax.legend() +plt.show() +``` + +在恒定政策下,公众的预期会收敛到该政策,$\lambda$ 越大,收敛速度越慢。 + +正如我们下面所讨论的,索洛和托宾在检验自然率假说时正是利用了这个归纳性质。 + +## 费尔普斯问题 + +经济永远重复运行,政府用如下贴现准则来评估结果序列: + +```{math} +:label: pa_criterion + +V^g = (1 - \delta) \sum_{t=1}^{\infty} \delta^{t-1} p(U_t, y_t), +\qquad p(U_t, y_t) = - \frac{1}{2}(U_t^2 + y_t^2), +\qquad \delta \in (0, 1] . +``` + +当 $\delta = 1$ 时,我们在均值极限(切萨罗)意义上理解 {eq}`pa_criterion`。 + +政府通过选择通货膨胀 $y_t$ 的规则来最大化 {eq}`pa_criterion`,同时受制于适应性预期方案 {eq}`pa_adaptive` 和预期增广的菲利普斯曲线: + +```{math} +:label: pa_phillips + +U_t = U^* - \theta(y_t - x_t) . +``` + +由于预期通货膨胀 $x_t$ 在第 $t$ 期开始时就已预先确定,因此它是唯一的内生状态变量。 + +因此,政府的问题是一个带有以下要素的贴现 LQ 控制问题: + +* 状态 $s_t = \begin{bmatrix} 1 & x_t \end{bmatrix}'$, +* 控制 $y_t$,以及 +* 转移方程 $x_{t+1} = \lambda x_t + (1 - \lambda) y_t$。 + +### 将问题转化为 LQ 形式 + +令 $U_t = a' s_t - \theta y_t$,其中 $a = \begin{bmatrix} U^* & \theta \end{bmatrix}'$。 + +那么每期损失 $\tfrac{1}{2}(U_t^2 + y_t^2)$ 等于 + +$$ +\frac{1}{2}\left[ s_t'(a a') s_t + (\theta^2 + 1) y_t^2 - 2 \theta \, y_t \, (a' s_t) \right] . +$$ + +将其与 QuantEcon 的 LQ 损失 $s_t' R s_t + y_t' Q y_t + 2 y_t' N s_t$ 进行匹配,并将转移方程与 $s_{t+1} = A s_t + B y_t$ 进行匹配,得到 + +$$ +R = \tfrac{1}{2} a a', \quad +Q = \tfrac{1}{2}(\theta^2 + 1), \quad +N = -\tfrac{1}{2}\theta\, a', \quad +A = \begin{bmatrix} 1 & 0 \\ 0 & \lambda \end{bmatrix}, \quad +B = \begin{bmatrix} 0 \\ 1 - \lambda \end{bmatrix} . +$$ + +贴现因子为 $\beta = \delta$;{eq}`pa_criterion` 中的缩放因子 $(1 - \delta)$ 不会影响最优策略。 + +```{code-cell} ipython3 +class PhelpsProblem: + """ + The Phelps optimal-control problem: a rational government facing a + public that forecasts inflation adaptively with parameter λ. + """ + + def __init__(self, θ=1.0, U_star=5.0, λ=0.7, δ=0.96): + self.θ, self.U_star, self.λ, self.δ = θ, U_star, λ, δ + + a = np.array([[U_star], [θ]]) + R = 0.5 * (a @ a.T) + Q = np.array([[0.5 * (θ**2 + 1)]]) + N = -0.5 * θ * a.T + A = np.array([[1.0, 0.0], [0.0, λ]]) + B = np.array([[0.0], [1 - λ]]) + + # δ = 1 (limit of means) is handled as the limit δ → 1 + β = min(δ, 1 - 1e-7) + self.lq = qe.LQ(Q, R, A, B, N=N, beta=β) + P, F, d = self.lq.stationary_values() + + # optimal rule y_t = f1 + f2 x_t + self.f1, self.f2 = -F[0, 0], -F[0, 1] + + def simulate(self, x0=12.0, T=60): + "Disinflation path (U_t, y_t) starting from expectation x0." + θ, U_star, λ = self.θ, self.U_star, self.λ + U, y, x = np.empty(T), np.empty(T), x0 + for t in range(T): + y[t] = self.f1 + self.f2 * x + U[t] = U_star - θ * (y[t] - x) + x = λ * x + (1 - λ) * y[t] + return U, y +``` + +最优规则的形式为 $y_t = f_1 + f_2 x_t$,其中 $f_1 \neq 0$ 且 $f_2 \neq 1$。 + +这些不等式反映了公众并未使用最优的预测规则;如果反而是 $f_1 = 0$ 且 $f_2 = 1$,那么我们将在所有历史情形下得到 $y_t = x_t$。 + +```{code-cell} ipython3 +pp = PhelpsProblem(θ=1.0, U_star=5.0, λ=0.7, δ=0.96) +print(f"optimal rule: y_t = {pp.f1:.3f} + {pp.f2:.3f} x_t") +``` + +### 一个命题 + +费尔普斯问题之所以有趣,原因在于以下结果。 + +```{prf:proposition} δ = 1 最终维持拉姆齐结果 +:label: pa_prop + +在没有贴现的情况下($\delta = 1$),政府会将 $y_t$ 驱动至 $0$,即拉姆齐结果。 +``` + +当 $\delta = 1$ 时,$\lambda$ 决定了向拉姆齐结果收敛的速度。 + +当 $\delta < 1$ 时,$y_t$ 的极限点取决于 $\lambda$ 与 $\delta$ 之间的比较关系。 + +当 $\lambda < \delta$ 且 $\delta$ 接近 $1$ 时,政府的政策最终会近似达到拉姆齐结果。 + +在过渡路径上,公众的预期是错误的,但在稳态下由于归纳性质的作用,公众的预期是正确的。 + +## 反通货膨胀路径 + +现在我们来重现 {cite}`Sargent1999` 第 5 章中的反通货膨胀实验。 + +设 $\theta = 1$ 且 $U^* = 5$,并从 20 世纪 70 年代末的初始条件 $x_{-1} = y_{-1} = 12$ 开始政府的问题,这意味着 $U = U^* = 5$。 + +下表记录了在选定滞后期下失业率 $U$ 和通货膨胀率 $y$ 的路径,涉及两个贴现因子 $\delta \in \{0.96, 1\}$ 和两个适应性参数 $\lambda \in \{0.7, 0.9\}$。 + +```{code-cell} ipython3 +def disinflation_table(δ, lags=(1, 5, 20, 50)): + rows = [] + for λ in [0.7, 0.9]: + U, y = PhelpsProblem(λ=λ, δ=δ).simulate(x0=12.0, T=max(lags) + 1) + for lag in lags: + rows.append((λ, lag, U[lag - 1], y[lag - 1])) + return rows + +for δ in [0.96, 1.0]: + print(f"\n δ = {δ}") + print(f" {'λ':>4} {'lag':>4} {'U':>7} {'y':>7}") + for λ, lag, U, y in disinflation_table(δ): + print(f" {λ:>4} {lag:>4} {U:>7.1f} {y:>7.1f}") +``` + +在每种参数设置下,政府都会制造一场重大衰退,并立即将通货膨胀率降低到超过其最终极限值一半以上的程度。 + +在贴现情形($\delta = 0.96$)中,通货膨胀率最终稳定在一个正值水平,且政府在 $\lambda = 0.9$ 时接受比 $\lambda = 0.7$ 时更长但更温和的衰退。 + +在无贴现情形($\delta = 1$)中,通货膨胀率会一直被驱动到拉姆齐值零,$\lambda$ 越大速度越慢。 + +让我们绘制完整的反通货膨胀路径。 + +```{code-cell} ipython3 +fig, axes = plt.subplots(1, 2, figsize=(11, 4.5)) + +for δ, ax in zip([0.96, 1.0], axes): + for λ in [0.7, 0.9]: + U, y = PhelpsProblem(λ=λ, δ=δ).simulate(x0=12.0, T=60) + ax.plot(y, lw=1.5, label=rf'$\lambda = {λ}$') + ax.set_title(rf'$\delta = {δ}$') + ax.set_xlabel('$t$') + ax.set_ylabel('inflation $y_t$') + ax.legend() + +plt.tight_layout() +plt.show() +``` + +无贴现问题将通货膨胀驱动至拉姆齐结果;而有贴现问题则未能达到这一水平。 + +## 一般化的费尔普斯问题 + +对于政府的控制问题而言,重要的是菲利普斯曲线的*简化形式*,而不是确定 $x_t$ 的底层结构。 + +有必要陈述费尔普斯问题的一个更一般化版本,其中政府的模型是一个简化形式的分布滞后菲利普斯曲线。 + +定义向量 + +$$ +X_{U,t} = \begin{bmatrix} U_{t-1} & \cdots & U_{t-m_U} \end{bmatrix}', +\qquad +X_{y,t} = \begin{bmatrix} y_{t-1} & \cdots & y_{t-m_y} \end{bmatrix}', +$$ + +以及状态向量 $X_t = \begin{bmatrix} X_{U,t}' & X_{y,t}' & 1 \end{bmatrix}'$,其中收集了 $t-1$ 期及更早时期的信息。 + +我们可以写出两条简化形式的菲利普斯曲线,它们仅在*拟合方向*上有所不同: + +$$ +\text{古典型:} \quad U_t = \gamma' X_{C,t} + \varepsilon_{C,t}, +\qquad X_{C,t} = \begin{bmatrix} y_t & X_{t-1}' \end{bmatrix}', +$$ + +$$ +\text{凯恩斯型:} \quad y_t = \beta' X_{K,t} + \varepsilon_{K,t}, +\qquad X_{K,t} = \begin{bmatrix} U_t & X_{t-1}' \end{bmatrix}' . +$$ + +下标 $C$ 和 $K$ 分别代表*古典型*(将 $U$ 对 $y$ 回归)和*凯恩斯型*(将 $y$ 对 $U$ 回归)。 + +一般化的**费尔普斯问题**是要选择一个控制规律 $\hat y_t = h X_{t-1}$,以在受政府所信奉的菲利普斯曲线以及 $y_t = \hat y_t + v_{2t}$(其中 $v_{2t}$ 为控制误差)约束的条件下,最大化 {eq}`pa_criterion` 的期望值。 + +这诱导出一个从政府信念 $\gamma$ 到其决策规则 $h$ 的映射: + +```{math} +:label: pa_map + +h = h(\gamma) . +``` + +上文所求解的具体问题是一个特殊情形,其中通过将适应性预期假设 {eq}`pa_adaptive` 代入菲利普斯曲线 {eq}`pa_phillips`,对 $\gamma$ 施加了限制。 + +一旦完成这种代换,状态变量 $x_t$ 就从视野中消失了。 + +这些对象——$\gamma$、$\beta$、$h(\gamma)$,以及两种拟合方向——正是我们在 {doc}`phillips_self_confirming` 中定义**自我确认均衡**所需要的关键要素。 + +```{note} +**归纳假设**是这样一种限制:在凯恩斯型菲利普斯曲线 $y_t = \beta' X_{K,t} + \varepsilon_{K,t}$ 中,滞后 $y$ 值上的权重之和为一(等价地,在古典形式中,当期与滞后 $y$ 值上的权重之和为零)。在适应性预期下,这一点成立,因为 {eq}`pa_geom` 中的权重之和为一。 +``` + +## 检验自然率假说 + +罗伯特·索洛和詹姆斯·托宾 {cite}`Solow1968,Tobin1968` 利用归纳假设检验了自然率假说。 + +将几何分布滞后 {eq}`pa_geom` 代入一条反转的菲利普斯曲线,得到 + +```{math} +:label: pa_invphill + +y_t = (1 - \lambda) \sum_{i=1}^{\infty} \lambda^{i-1} y_{t-i} + + \theta^{-1}(U^* - U_t) . +``` + +他们提出通过运行如下回归来检验自然率假说: + +```{math} +:label: pa_tobin + +y_t = b_0 + b_1 (1 - \lambda) \sum_{i=1}^{\infty} \lambda^{i-1} y_{t-i} + + b_2 U_t + \varepsilon_t , +``` + +并将 $b_1 < 1$ 的发现解读为存在斜率为 $b_1 - 1$ 的通货膨胀与失业之间长期权衡关系的证据。 + +早期的实证研究发现 $b_1 < 1$,因此拒绝了自然率假说,转而支持一种长期权衡关系。 + +{cite}`KingWatson1994` 及其他学者后来指出,这种拒绝与不拒绝的模式,与通货膨胀率在 20 世纪 60 年代之后(而非之前)呈现单位根这一趋势是一致的,因此当 $y_t$ 存在单位根时,单位和限制条件 $b_1 = 1$ 与理性预期是*相容*的。 + +从费尔普斯控制问题的视角来看,自然率假说是否成立是次要的:无论 $b_1 = 1$ 是否成立,费尔普斯问题都会为通货膨胀-失业选择赋予有趣的动态特征。 + +## 牺牲率与费尔普斯模型的颠覆 + +尽管费尔普斯的控制问题在归纳假设下对维持拉姆齐结果具有令人鼓舞的意义,但它也带有一段不光彩的历史。 + +在费尔普斯问题中,对于固定的 $\delta < 1$,总能找到一个足够接近 $1$ 的 $\lambda$,使得高通胀预期会让政府想要避免进行反通货膨胀。 + +在 20 世纪 70 年代末,具有较长预期调整滞后的模型被用来建议*不要*降低通货膨胀。 + +关于**牺牲率**——即将通货膨胀降低一个百分点所需放弃的估计国内生产总值数量——的估计值被广泛流传。 + +需要吸取并延续下去的教训是:激活归纳假设最终可以带来更好的结果,但以费尔普斯、托宾和索洛所使用的形式,归纳假设背离了理性预期。 + +在 {doc}`phillips_misspecified` 和 {doc}`phillips_self_confirming` 中,我们赋予政府和公众更多的对称性,将类似 {eq}`pa_adaptive` 的更新方案应用于函数而非数字,并将 $\lambda$ 从一个自由参数转变为一个均衡结果。 + +这里所求解的 LQ 费尔普斯问题会在 {doc}`phillips_learning`、{doc}`phillips_escaping_nash` 和 {doc}`phillips_priors` 中再次出现,在那些讲座中,一个进行学习的政府每期都重新求解该问题——而激活归纳假设正是触发沃尔克式稳定化措施的原因。 + +## 练习 + +```{exercise-start} +:label: pa_ex1 +``` + +上文的命题指出,当 $\delta \to 1$ 时,政府会将通货膨胀驱动到拉姆齐值 $0$。 + +对于 $\lambda = 0.8$,请针对贴现因子网格 $\delta \in \{0.90, 0.92, \ldots, 0.99\}$,计算极限通货膨胀率 $y_\infty$(即经过长时间模拟后 $y_t$ 所稳定到的值)。 + +将 $y_\infty$ 对 $\delta$ 作图,并确认随着 $\delta \to 1$,该值向零递减。 + +```{exercise-end} +``` + +```{solution-start} pa_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +δ_grid = np.arange(0.90, 0.995, 0.01) +y_inf = [] +for δ in δ_grid: + U, y = PhelpsProblem(λ=0.8, δ=δ).simulate(x0=12.0, T=400) + y_inf.append(y[-1]) + +fig, ax = plt.subplots(figsize=(8, 4.5)) +ax.plot(δ_grid, y_inf, 'o-') +ax.set_xlabel(r'discount factor $\delta$') +ax.set_ylabel(r'limiting inflation $y_\infty$') +plt.show() +``` + +随着 $\delta$ 向一上升,政府愿意接受为获得低预期通货膨胀的长期收益所需的过渡性衰退,因此极限通货膨胀率会向拉姆齐值零下降。 + +```{solution-end} +``` + +```{exercise-start} +:label: pa_ex2 +``` + +直接验证最优策略的归纳性质。 + +以 $\delta = 0.96$ 且 $\lambda = 0.7$ 的贴现问题为例,模拟一条较长的反通货膨胀路径。 + +检验在稳态下,公众的预期 $x_t$ 是否等于实际通货膨胀率 $y_t$(即公众在极限情形下*不会*被欺骗),尽管在过渡路径上预期是错误的。 + +```{exercise-end} +``` + +```{solution-start} pa_ex2 +:class: dropdown +``` + +```{code-cell} ipython3 +pp = PhelpsProblem(θ=1.0, U_star=5.0, λ=0.7, δ=0.96) +U, y = pp.simulate(x0=12.0, T=200) + +# reconstruct the expectation path implied by the adaptive rule +x = adaptive_forecast(np.concatenate([[12.0], y]), λ=0.7, x0=12.0)[1:] + +print(f"steady-state inflation y_∞ = {y[-1]:.4f}") +print(f"steady-state expectation x_∞ = {x[-1]:.4f}") +print(f"gap = {y[-1] - x[-1]:.2e}") +``` + +在稳态下,预期通货膨胀率与实际通货膨胀率一致,这证实了归纳性质使得公众的预测在极限情形下是正确的。 + +```{solution-end} +``` \ No newline at end of file From 8115c4550f146b65c1afcef1d673fa42eceef760 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:14 +1000 Subject: [PATCH 02/21] Update translation: .translate/state/phillips_adaptive.md.yml --- .translate/state/phillips_adaptive.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_adaptive.md.yml diff --git a/.translate/state/phillips_adaptive.md.yml b/.translate/state/phillips_adaptive.md.yml new file mode 100644 index 0000000..4e4bbb3 --- /dev/null +++ b/.translate/state/phillips_adaptive.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 8 +tool-version: 0.23.0 From 8e2aa77701127c1d01e9cb7e9d3a15ce62e40843 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:15 +1000 Subject: [PATCH 03/21] Update translation: lectures/phillips_credibility.md --- lectures/phillips_credibility.md | 510 +++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 lectures/phillips_credibility.md diff --git a/lectures/phillips_credibility.md b/lectures/phillips_credibility.md new file mode 100644 index 0000000..2acf39b --- /dev/null +++ b/lectures/phillips_credibility.md @@ -0,0 +1,510 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 信誉问题 + headings: + Overview: 概述 + A one-period economy: 单期经济 + Nash and Ramsey outcomes: 纳什和拉姆齐结果 + Nash and Ramsey outcomes::A picture of the two outcomes: 两种结果的图示 + Best response dynamics: 最优反应动态 + Least squares learning converges to Nash: 最小二乘学习收敛于纳什结果 + More foresight: 更多的前瞻性 + 'Appendix: stochastic approximation': 附录:随机逼近 + Exercises: 练习 +--- + +(phillips_credibility)= +```{raw} jupyter + +``` + +# 信誉问题 + +```{contents} Contents +:depth: 2 +``` + +## 概述 + +本讲座描述了一个由 {cite}`KydlandPrescott1977` 以及罗伯特·巴罗和大卫·戈登所研究的那种基本预期菲利普斯曲线模型。 + +这是基于 {cite}`Sargent1999` 各章内容的系列讲座中的第一讲。 + +那些章节形式化了: + +* 发现菲利普斯曲线所激发的通胀诱惑; +* 承诺技术在抵御这种诱惑方面的价值;以及 +* 声誉机制作为承诺替代品的脆弱性。 + +在整个讲座中,我们只使用理性预期这一均衡概念。 + +政府和私人部门决策*时序*上的改变会诱发不同的经济体,产生不同的结果。 + +每当政府希望比其必须做出决策的时间更早地做出决策时,它就面临**信誉问题**。 + +我们将比较两种时序协议下的结果: + +* 在其中一种协议下,政府在私人部门形成其预期*之前*选择通货膨胀率,因此政府会考虑其选择将如何影响这些预期。 +* 在另一种协议下,政府在私人部门已经形成其预期*之后*选择通货膨胀率。 + +第二种协议下结果的恶化程度衡量了无法承诺所造成的损失。 + +我们还研究了两种收敛于无承诺(纳什)结果的*非均衡*动态: + +* 最优反应动态,以及 +* 最小二乘学习。 + +让我们从一些标准的导入开始: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +``` + +## 单期经济 + +尽管信誉问题本质上是动态的,但在不同的期内时序模式下,可以在一个单期模型中描述它们。 + +这为后续讲座中的多期分析做好了准备。 + +我们用南希·斯托基(Nancy Stokey)在 {cite}`stokey1989reputation` 中所使用的术语来描述 {cite}`KydlandPrescott1977` 的单期模型的一个版本。 + +设 $(U, y, x)$ 分别为失业率、通货膨胀率,以及公众对通货膨胀率的预期。 + +政府的单期收益为: + +```{math} +:label: pc_payoff + +- \frac{1}{2} \left( U^2 + y^2 \right) . +``` + +失业率由一条预期增广的菲利普斯曲线决定: + +```{math} +:label: pc_phillips + +U = U^* - \theta (y - x), \qquad \theta > 0 . +``` + +该方程表明,只有当出现意外的通胀或通缩时,失业率才会偏离自然率 $U^*$。 + +将 {eq}`pc_phillips` 代入 {eq}`pc_payoff`,可将政府的收益表示为函数 $r(x, y)$: + +```{math} +:label: pc_r + +r(x, y) = - \frac{1}{2} \left[ \left(U^* - \theta (y - x)\right)^2 + y^2 \right] . +``` + +我们使用以下概念。 + +**理性预期均衡:** 满足 {eq}`pc_phillips` 且 $y = x$ 的三元组 $(U, x, y)$。 + +**政府(单期)最优反应:** 给定公众的预期 $x$,设定 $y$ 的决策规则 $B(x) = \operatorname{argmax}_y r(x, y)$。 + +**纳什均衡:** 满足 (i) $x = y$,以及 (ii) $y = B(x)$ 的二元组 $(x, y)$。 + +**拉姆齐问题:** $\max_y r(y, y)$。*拉姆齐结果*是达到最大值的 $y$。 + +**最优反应动态:** 动态系统 $y_t = B(y_{t-1})$,给定 $y_0$。 + +理性预期均衡是位于菲利普斯曲线上、且给定 $x$ 时私人主体不会被欺骗的三元组 $(U, x, y)$。 + +将 $x = y$ 代入菲利普斯曲线 {eq}`pc_phillips` 表明,在任何理性预期均衡中 $U = U^*$。 + +这确定了 $U^*$ 为自然失业率。 + +## 纳什和拉姆齐结果 + +纳什均衡建立在给定预期状态 $x$ 时政府的最优反应之上,同时结合市场的反应 $x = y$,即对给定 $y$ 的理性预期。 + +在固定 $x$ 的情况下,对 {eq}`pc_r` 关于 $y$ 求最大化,得到政府的最优反应函数: + +```{math} +:label: pc_B + +y = B(x) = \frac{\theta}{\theta^2 + 1} U^* + \frac{\theta^2}{\theta^2 + 1} x . +``` + +纳什均衡设定 $x = y = B(x)$,由此得到: + +$$ +y^N = x^N = \theta U^*, \qquad U = U^* . +$$ + +拉姆齐问题则在最大化*之前*就施加 $x = y$,因此它最大化 $r(y, y) = -\tfrac{1}{2}(U^{*2} + y^2)$,得到拉姆齐结果: + +$$ +y^R = x^R = 0, \qquad U = U^* . +$$ + +因此 $r(x^R, y^R) = -\tfrac{1}{2} U^{*2}$,而 $r(x^N, y^N) = -\tfrac{1}{2}(1 + \theta^2) U^{*2}$。 + +两种结果都实现了自然率 $U^*$,但纳什均衡以正的通货膨胀率实现它,因此收益严格更低。 + +让我们把这些公式整理到一个类中。 + +```{code-cell} ipython3 +class CredibilityModel: + """ + A one-period expectational Phillips curve economy. + """ + + def __init__(self, θ=1.0, U_star=5.0): + self.θ, self.U_star = θ, U_star + + def phillips(self, y, x): + "Unemployment implied by inflation y and expected inflation x." + return self.U_star - self.θ * (y - x) + + def r(self, x, y): + "Government one-period payoff." + U = self.phillips(y, x) + return -0.5 * (U**2 + y**2) + + def B(self, x): + "Government best response to expected inflation x." + θ = self.θ + return θ / (θ**2 + 1) * self.U_star + θ**2 / (θ**2 + 1) * x + + def nash(self): + "Nash equilibrium inflation (= expected inflation)." + return self.θ * self.U_star + + def ramsey(self): + "Ramsey inflation (= expected inflation)." + return 0.0 +``` + +```{code-cell} ipython3 +cm = CredibilityModel() + +y_N, y_R = cm.nash(), cm.ramsey() +print(f"Nash inflation y^N = {y_N:.2f}") +print(f"Ramsey inflation y^R = {y_R:.2f}") +print(f"Nash payoff r = {cm.r(y_N, y_N):.3f}") +print(f"Ramsey payoff r = {cm.r(y_R, y_R):.3f}") +``` + +纳什结果的收益比拉姆齐结果的收益差。 + +政府会更愿意实现拉姆齐结果,但如果没有一种能在公众形成预期*之前*承诺 $y = 0$ 的技术,它就无法实现这一结果。 + +纳什均衡由这样一种时序协议支持:政府在私人部门形成预期*之后*才做出决策。 + +拉姆齐结果则与这样一种时序协议相关联:政府*首先*做出选择,并且知道在理性预期均衡中,公众的预期会随其选择而变化,因为 $y = x$。 + +### 两种结果的图示 + +政府的无差异曲线是 $(U, y)$ 空间中以原点为中心的圆,因为收益 {eq}`pc_payoff` 仅依赖于 $U^2 + y^2$。 + +对于给定的预期 $x$,菲利普斯曲线 {eq}`pc_phillips` 是 $(U, y)$ 空间中一条向下倾斜的直线。 + +给定 $x$ 时,政府对 $y$ 的最优反应出现在无差异曲线与由 $x$ 索引的菲利普斯曲线相切的位置。 + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(7, 6)) + +U_grid = np.linspace(0, 12, 200) + +# a family of Phillips curves indexed by expected inflation x +for x in [0.0, y_N / 2, y_N]: + # U = U_star - θ (y - x) => y = x + (U_star - U) / θ + y_line = x + (cm.U_star - U_grid) / cm.θ + ax.plot(U_grid, y_line, 'C0', lw=1) + +# government indifference curves (circles U^2 + y^2 = const) +ξ = np.linspace(0, 2 * np.pi, 200) +for R in [y_R, np.hypot(cm.U_star, y_N)]: + if R > 0: + ax.plot(R * np.cos(ξ), R * np.sin(ξ), 'C1--', lw=1) + +ax.plot(cm.U_star, y_N, 'ko') +ax.annotate('Nash', (cm.U_star, y_N), (cm.U_star + 0.4, y_N + 0.4)) +ax.plot(cm.U_star, y_R, 'ko') +ax.annotate('Ramsey', (cm.U_star, y_R), (cm.U_star + 0.4, y_R + 0.4)) + +ax.set_xlim(0, 12) +ax.set_ylim(0, 10) +ax.set_xlabel('unemployment $U$') +ax.set_ylabel('inflation $y$') +plt.show() +``` + +实线是预期通货膨胀率 $x \in \{0, y^N/2, y^N\}$ 对应的菲利普斯曲线;虚线圆是政府的无差异曲线。 + +纳什结果 $(U^*, y^N)$ 位于比拉姆齐结果 $(U^*, 0)$ 更大的圆上(收益更低)。 + +## 最优反应动态 + +最优反应动态通过假设一种自适应机制,将单期模型转化为动态模型,在该机制中,预期通货膨胀率等于上一期的通货膨胀率,即 $x_t = y_{t-1}$。 + +这导致了以下动态: + +$$ +y_t = B(y_{t-1}), \qquad y_0 \text{ given} . +$$ + +由于 $B$ 是一个斜率为 $\theta^2 / (\theta^2 + 1) \in (0, 1)$ 的仿射映射,对其迭代会从任意起始点收敛到不动点 $y^N = \theta U^*$。 + +让我们将最优反应函数与 45 度线一起绘图,并模拟该动态过程。 + +```{code-cell} ipython3 +def best_response_path(cm, y0, T=20): + "Iterate y_{t+1} = B(y_t)." + y = np.empty(T + 1) + y[0] = y0 + for t in range(T): + y[t + 1] = cm.B(y[t]) + return y + +y_path = best_response_path(cm, y0=0.0, T=20) +``` + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(6, 6)) + +x_grid = np.linspace(0, y_N + 1, 100) +ax.plot(x_grid, cm.B(x_grid), 'C0', label='$B(x)$') +ax.plot(x_grid, x_grid, 'k--', lw=1, label='45 degrees') + +# cobweb of the best response dynamics +for t in range(len(y_path) - 1): + ax.plot([y_path[t], y_path[t]], [y_path[t], y_path[t + 1]], 'C1', lw=0.8) + ax.plot([y_path[t], y_path[t + 1]], [y_path[t + 1], y_path[t + 1]], + 'C1', lw=0.8) + +ax.plot(y_N, y_N, 'ko') +ax.annotate('Nash', (y_N, y_N), (y_N - 1.5, y_N + 0.3)) +ax.set_xlabel('$x$') +ax.set_ylabel('$B(x)$') +ax.legend() +plt.show() +``` + +从 $x = 0$(拉姆齐通货膨胀率)开始,政府设定 $y = B(0) > 0$。 + +这促使公众提高其预期,从而导致政府进一步提高通货膨胀率。 + +这一过程的极限是纳什结果 $y = x = y^N$,一种自我确认的状态。 + +因此,最优反应动态收敛于纳什均衡,进一步强化了 $(U^*, y^N)$ 作为无承诺技术模型的预测。 + +## 最小二乘学习收敛于纳什结果 + +最优反应动态的一个变体也可以从最小二乘学习中产生。 + +最小二乘学习在整个这一系列讲座中都起着关键作用,这个简单的例子引入了一些分析要素,这些要素将在后面更复杂的场景中再次出现。 + +按照 {cite}`Bray1982` 的方法,假设预期通货膨胀率 $x_t$ 是过去通货膨胀率的平均值: + +$$ +x_t = \frac{1}{t - 1} \sum_{s=1}^{t-1} y_s , +$$ + +它可以递归地表示为: + +```{math} +:label: pc_expect1 + +x_t = x_{t-1} + \frac{1}{t-1} (y_{t-1} - x_{t-1}), \qquad x_1 = 0 . +``` + +实际通货膨胀率是在 $x_t$ 处评估的最优反应映射的一个扰动版本: + +```{math} +:label: pc_expect2 + +y_t = B(x_t) + \eta_t , +``` + +其中 $\eta_t$ 是一个独立同分布的均值为零的项,代表政府对通货膨胀的不完全控制。 + +将 {eq}`pc_expect2` 代入 {eq}`pc_expect1`,得到随机递归式: + +```{math} +:label: pc_expect3 + +x_t = x_{t-1} + \frac{1}{t-1} \left[ B(x_{t-1}) - x_{t-1} + \eta_t \right] . +``` + +根据随机逼近理论,$x_t$ 的极限行为由相关的常微分方程(ODE)描述: + +```{math} +:label: pc_ode + +\frac{d x}{d t} = B(x) - x . +``` + +这个常微分方程的静止点满足 $x = B(x)$,即纳什均衡通货膨胀率 $x = \theta U^*$。 + +由于映射 $B$ 是仿射的,该常微分方程是线性的,其斜率为: + +$$ +\mathcal{M} = \frac{d}{d x}\left( B(x) - x \right) = B'(x) - 1 = - \frac{1}{\theta^2 + 1} . +$$ + +由于 $\mathcal{M} < 0$,该常微分方程在其静止点附近是稳定的,{cite}`MarcetSargent1989` 的定理给出了 $x_t$ 全局收敛到 $y^N$ 的条件。 + +让我们模拟递归式 {eq}`pc_expect3` 并确认其收敛到纳什结果。 + +```{code-cell} ipython3 +def ls_learning(cm, T=2000, σ_η=1.0, seed=0): + "Simulate least squares learning of expected inflation." + rng = np.random.default_rng(seed) + x = np.empty(T + 1) + y = np.empty(T + 1) + x[0] = 0.0 + y[0] = cm.B(x[0]) + for t in range(1, T + 1): + η = σ_η * rng.standard_normal() + y[t] = cm.B(x[t - 1]) + η + gain = 1.0 / (t + 1) # decreasing gain + x[t] = x[t - 1] + gain * (cm.B(x[t - 1]) - x[t - 1] + η) + return x, y +``` + +```{code-cell} ipython3 +x, y = ls_learning(cm, T=2000, σ_η=1.0) + +fig, ax = plt.subplots(figsize=(9, 5)) +ax.plot(x, 'C0', lw=1, label='expected inflation $x_t$') +ax.axhline(y_N, color='k', ls='--', lw=1, label='Nash $y^N$') +ax.axhline(y_R, color='C2', ls=':', lw=1, label='Ramsey $y^R$') +ax.set_xlabel('$t$') +ax.set_ylabel('inflation') +ax.legend() +plt.show() +``` + +最小二乘动态证实了最优反应动态所展现的悲观结论。 + +给定一个以低通胀、金本位式的 $x$ 值形式出现的初始条件,最优反应或最小二乘动态可以解释通货膨胀的*加速*。 + +但它们无法解释像沃尔克式那样将通货膨胀率重新拉低的*稳定化*过程。 + +后续讲座将以旨在缓和这种悲观情绪的方式重新构建最小二乘学习的各种版本。 + +## 更多的前瞻性 + +最优反应和最小二乘学习是附加在单期经济上的非均衡动态。 + +它们迫使所有的变动都通过预期形成来实现:在选择通货膨胀率时,政府忘记了经济会持续多于一期。 + +如果政府为未来进行规划,可以出现更好的结果。 + +后续讲座描述了三种建模前瞻性的方式,它们赋予不同程度的理性,并预测不同质量的结果: + +1. 一种声誉方法,将理性预期同时赋予政府和公众。许多结果都是可持续的,从拉姆齐结果的重复到比纳什结果重复更差的路径都有可能。 +2. 一种方法,保持政府的理性,但赋予公众原始凯根-弗里德曼意义上的*适应性*预期。这是 {doc}`phillips_adaptive` 的主题。根据贴现因子与适应参数的比较,这种设定可以改善结果,甚至可能维持拉姆齐结果的重复。 +3. 一种将适应性行为同时赋予政府和公众的方法。这是 {doc}`phillips_misspecified` 和 {doc}`phillips_self_confirming` 的主题。 + +## 附录:随机逼近 + +在这里我们简要说明为什么常微分方程 {eq}`pc_ode` 支配着随机差分方程 {eq}`pc_expect3` 的尾部行为。 + +这一论证源自 {cite}`KushnerClark1978`,包含两个关键组成部分:时间尺度的转换和对平均化方法的充分运用。 + +设 $\{a_n\}_{n \geq 0}$ 为满足以下条件的正增益序列: + +$$ +\lim_{n \to \infty} a_n = 0, \qquad \sum_n a_n = +\infty, \qquad \sum_n a_n^2 < +\infty . +$$ + +选择 $a_n = 1 / (n + 1)$ 满足这些假设。 + +将递归式重写为: + +```{math} +:label: pc_sa1 + +x_{n+1} = x_n + a_n \left[ B(x_n) - x_n + \eta_n \right] , +``` + +其中 $\eta_n$ 是独立同分布的,均值为零,方差有限。 + +引入变换后的时间尺度 $t_0 = 0$,$t_n = \sum_{i=0}^{n-1} a_i$,并将离散序列 $\{x_n\}$ 插值为连续时间过程 $x^0(t)$。 + +库什纳和克拉克表明,在这个变换后的时间尺度上,插值过程可以很好地由以下积分方程逼近: + +$$ +x^0(t) = x^0(0) + \int_0^t \left[ B(x^0(s)) - x^0(s) \right] d s + R(t) , +$$ + +其中逼近误差 $R(t)$ 有两个组成部分——一个来自用积分逼近 $B(x) - x$ 中的分布滞后项,另一个来自 $\eta_s$ 中的分布滞后项。 + +通过研究该过程的一系列左移版本,他们证明当 $n \to \infty$ 时,两个误差组成部分都可以被驱动趋于零。 + +噪声成分的关键步骤是注意到相关的部分和构成一个鞅,其方差与 $\sum_i a_i^2$ 成比例,而由于 $\sum_i a_i^2 < \infty$,这个和是收敛的。 + +剩余的误差被送到零,是因为 $a_i \to 0$ 缩小了用于逼近积分的黎曼和的网格尺度。 + +在极限情形下,随机差分方程 {eq}`pc_sa1` 与非随机常微分方程: + +$$ +\frac{d}{d t} \tilde x(t) = B(\tilde x(t)) - \tilde x(t) , +$$ + +共享相同的行为,后者被称为描述原系统的*均值动态*。 + +后续讲座研究了类似 {eq}`pc_sa1` 的系统,其中 $a_i$ *不*随 $i$ 增大而趋于零——即所谓的常增益算法。 + +均值动态 {eq}`pc_ode` 和这些常增益算法成为 {doc}`phillips_learning`、{doc}`phillips_escaping_nash` 和 {doc}`phillips_priors` 中的核心工具,在那里,本讲中所研究的标量预期 $x$ 会扩展为一整套漂移的菲利普斯曲线系数向量。 + +## 练习 + +```{exercise-start} +:label: pc_ex1 +``` + +最小二乘学习的收敛速度取决于相关常微分方程的斜率 $\mathcal{M} = -1/(\theta^2 + 1)$。 + +以通常的 $\sqrt{t}$ 速度收敛的必要条件是 $\mathcal{M} < -1/2$,这要求 $\theta < 1$。 + +针对 $\theta \in \{0.5, 1.0, 2.0\}$(保持 $U^*$ 固定)模拟最小二乘学习,并比较 $x_t$ 在其纳什值 $\theta U^*$ 附近稳定下来的速度。 + +在一张图上绘制 $x_t - \theta U^*$ 的三条路径。 + +```{exercise-end} +``` + +```{solution-start} pc_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(9, 5)) + +for θ in [0.5, 1.0, 2.0]: + cm_θ = CredibilityModel(θ=θ, U_star=5.0) + x, _ = ls_learning(cm_θ, T=3000, σ_η=1.0, seed=1) + ax.plot(x - cm_θ.nash(), lw=1, label=rf'$\theta = {θ}$') + +ax.axhline(0, color='k', lw=0.8) +ax.set_xlabel('$t$') +ax.set_ylabel('$x_t - \\theta U^*$') +ax.legend() +plt.show() +``` + +较小的 $\theta$(更陡峭的 $\mathcal{M}$)会使收敛到纳什通货膨胀率的过程更快、更紧密。 + +较大的 $\theta$ 则使 $x_t$ 在其极限附近更持久地波动。 + +```{solution-end} +``` \ No newline at end of file From 348e91f63249039ff206e933a2525ef42d55e3d5 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:15 +1000 Subject: [PATCH 04/21] Update translation: .translate/state/phillips_credibility.md.yml --- .translate/state/phillips_credibility.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_credibility.md.yml diff --git a/.translate/state/phillips_credibility.md.yml b/.translate/state/phillips_credibility.md.yml new file mode 100644 index 0000000..4e4bbb3 --- /dev/null +++ b/.translate/state/phillips_credibility.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 8 +tool-version: 0.23.0 From d12b04204da56218d3753e0ece2fa1a19d970047 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:16 +1000 Subject: [PATCH 05/21] Update translation: lectures/phillips_drifts_volatilities.md --- lectures/phillips_drifts_volatilities.md | 3090 ++++++++++++++++++++++ 1 file changed, 3090 insertions(+) create mode 100644 lectures/phillips_drifts_volatilities.md diff --git a/lectures/phillips_drifts_volatilities.md b/lectures/phillips_drifts_volatilities.md new file mode 100644 index 0000000..d49fd21 --- /dev/null +++ b/lectures/phillips_drifts_volatilities.md @@ -0,0 +1,3090 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 漂移与波动率 + headings: + Overview: 概览 + Bad policy or bad luck?: 政策不当还是运气不好? + A VAR with drifting coefficients and stochastic volatility: 一个系数漂移且波动率随机变化的 VAR + The data: 数据 + Priors: 先验 + A Metropolis-within-Gibbs sampler: 一个 Metropolis-within-Gibbs 抽样器 + A Metropolis-within-Gibbs sampler::Coefficient path: 系数路径 + A Metropolis-within-Gibbs sampler::Drift covariance: 漂移协方差 + A Metropolis-within-Gibbs sampler::Volatility parameters and paths: 波动率参数与路径 + A Metropolis-within-Gibbs sampler::Complete sampler: 完整的抽样器 + What the data say: 数据揭示了什么 + What the data say::The rate and structure of drift: 漂移的速率与结构 + What the data say::The evolution of volatility: 波动率的演变 + What the data say::Core inflation and the natural rate: 核心通货膨胀与自然失业率 + What the data say::Inflation persistence: 通货膨胀的持续性 + What the data say::Monetary policy activism: 货币政策的积极程度 + Another quarter-century of evidence: 又一个四分之一世纪的证据 + Another quarter-century of evidence::The new observations: 新增的观测数据 + Another quarter-century of evidence::Did coefficient drift continue?: 系数漂移是否持续? + Another quarter-century of evidence::Volatility after the Great Moderation: 大缓和之后的波动率 + Another quarter-century of evidence::Core inflation and the natural rate after 2000: 2000年之后的核心通货膨胀与自然失业率 + Another quarter-century of evidence::Did inflation become persistent again?: 通货膨胀是否再次变得持久? + Another quarter-century of evidence::Can recent policy activism be measured?: 近期的政策积极程度能否被度量? + Another quarter-century of evidence::What the additional observations change: 新增观测数据改变了什么 + Bad policy or bad luck? A verdict: 政策不当还是运气不好?一个结论 + Exercises: 练习 +--- + +(phillips_drifts_volatilities)= +```{raw} jupyter + +``` + +# 漂移与波动率 + +```{contents} Contents +:depth: 2 +``` + +## 概览 + +本节的讲座讲述了一个关于政府对菲利普斯曲线的*模型*、以及由此引发的*政策*如何随时间*漂移*的故事。 + +在 {doc}`phillips_learning` 和 {doc}`phillips_escaping_nash` 中,一个不断拟合并重新拟合近似菲利普斯曲线的政府,沿着一条*逃逸路径*被反复推离一个糟糕的 {doc}`自我实现均衡 `;而 {doc}`phillips_priors` 和 {doc}`phillips_lost_conquest` 则用漂移的信念来解释美国通货膨胀的起落。 + +那些讲座主要讲的是*理论*。 + +本讲座转向*数据*。 + +它研究了 {cite:t}`CogleySargent2005` 一文,该文提出了一个看似简单的问题: + +> 当我们审视美国战后关于通货膨胀、失业和利率的时间序列时,是否能看到动态发生了*漂移*的证据? + +蒂姆·科格利(Tim Cogley)和托马斯·萨金特开始这项工作,是作为《征服》一书 {cite}`Sargent1999` 和逃逸路径论文 {cite}`ChoWilliamsSargent2002` 的实证配套研究。 + +这也是对 {cite:t}`Sims2001comment` 和 {cite:t}`Stock2001comment` 对早期论文 {cite}`CogleySargent2001` 所作的深入评论的回应,并演变成与 {cite:t}`SimsZha2006` 和 {cite:t}`BernankeMihov1998` 之间的一场友好辩论,辩论的主题正是贯穿本节的核心问题: + +*20世纪70年代的大通胀及其在80年代的平息,究竟是政策不当的故事,还是运气不好的故事?* + +要让数据回答这个问题,我们需要一个足够灵活、能同时容纳*两种*答案的统计模型。 + +这个模型是一个*贝叶斯向量自回归模型,其系数按随机游走漂移,其冲击方差按随机波动率演化*。 + +拟合它需要一种马尔可夫链蒙特卡洛算法,该算法结合了 {doc}`卡尔曼滤波 `、{cite:t}`CarterKohn1994` 的前向滤波/后向抽样平滑器,以及 {cite:t}`Jacquier1994` 的随机波动率抽样器。 + +希望了解背景知识的读者可以在 {doc}`var_dmd` 中找到伴随形式的向量自回归,在 {doc}`kalman_2` 中找到卡尔曼平滑器,在 {doc}`ar1_bayes` 和 {doc}`ar1_turningpts` 中找到通过 MCMC 对状态空间模型进行的贝叶斯推断。 + +我们将依次讲解数据变换、先验、抽样器和主要的实证结果。 + +让我们从一些导入语句和数据路径开始。 + +```{code-cell} ipython3 +from pathlib import Path +import time + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +from IPython.display import display, Math +from scipy import linalg +from scipy.special import expit +from scipy.stats import invwishart + + +def locate_data_assets(): + """Find assets from either a MyST build or the repository root.""" + relative = Path('_static/lecture_specific/phillips_drifts_volatilities') + candidates = (relative, Path('lectures') / relative) + for candidate in candidates: + if (candidate / 'NEWQDATA.csv').is_file(): + return candidate + searched = ', '.join(str(path.resolve()) for path in candidates) + raise FileNotFoundError(f'NEWQDATA.csv was not found; searched {searched}') + + +asset_path = locate_data_assets() +data_path = asset_path / 'NEWQDATA.csv' +``` + +## 政策不当还是运气不好? + +有两种颇为可信的观点相互竞争,用以解释美国的大通胀——这与 {doc}`phillips_two_stories` 开篇提出的“胜利”与“昭雪”这两种故事是同一对立面。 + +**政策不当**的观点是本节乃至《征服》一书 {cite}`Sargent1999` 中反复演绎的观点。 + +亚瑟·伯恩斯(Arthur Burns)对经济的某种*模型*、他的*耐心*,或他无法*承诺*一条更好的规则,导致美联储以一种造成美国和平时期历史上最严重通胀的方式来实施货币政策;而一个改进的模型、更多的耐心,或更强的纪律性,则使保罗·沃尔克(Paul Volcker)得以将其平息 {cite}`DeLong1997,Taylor1997comment`。 + +按照这种观点,20世纪70年代到80年代之间发生变化的,是政策的*系统性部分*,即美联储的利率制定对通货膨胀和失业作出反应的方式。 + +**运气不好**的观点则截然不同。 + +区分伯恩斯时代和沃尔克时代的,并非他们的模型或政策,而是*冲击到*经济体上的各种*扰动*。 + +按照这种观点,经济简化形式描述的*系数*基本保持不变,改变的是扰动的*大小*,即*波动率*。 + +{cite:t}`BernankeMihov1998` 和 {cite:t}`SimsZha2006` 为这第二种观点收集了证据,部分办法是应用经典检验,而这些检验*未能拒绝* VAR系数随时间不变的假设。 + +我们该如何加以区分? + +一个系数恒定、波动率恒定的 VAR 可以生成异常大的实现冲击,但它无法表示其方差随时间发生的系统性变化。 + +一个系数漂移但波动率恒定的模型,也可能把波动率的变化误认为系数漂移。 + +因此,科格利和萨金特构建了一个能同时容纳*这两种*渠道的模型,并让贝叶斯后验来判定数据究竟需要多少这两种成分。 + +## 一个系数漂移且波动率随机变化的 VAR + +设变量按名义利率、变换后的失业率、通货膨胀的顺序排列, + +$$ +y_t = \begin{bmatrix} i_t & u_t & \pi_t \end{bmatrix}'. +$$ + +(这里的 $u_t$ 并非原始的失业率,而是其logit变换,我们将在下面的数据部分定义这一变换。) + +量测方程是一个滞后两期、系数随日期变化的 VAR, + +```{math} +:label: csdv_measurement +y_t = X_t'\theta_t + \varepsilon_t, +\qquad +X_t' = I_3 \otimes \begin{bmatrix} 1 & y_{t-1}' & y_{t-2}' \end{bmatrix}. +``` + +每个方程都有一个截距项和六个滞后系数,因此 $\theta_t$ 包含 +$3(1+2\times 3)=21$ 个元素。 + +一个滞后两期的 VAR 可以通过把 $y_t$ 和 +$y_{t-1}$ 堆叠成一个向量,改写为滞后一期的系统;与这个堆叠向量相乘的矩阵称为**伴随矩阵**,改写后的系统称为**伴随形式**的 VAR。 + +下面的函数根据堆叠的系数构造伴随矩阵。 + +```{code-cell} ipython3 +n_variables = 3 +n_lags = 2 +n_regressors = 1 + n_variables * n_lags +n_coefficients = n_variables * n_regressors + + +def companion_matrix(θ): + """Return the intercept and companion matrix for one coefficient vector.""" + equation_rows = np.asarray(θ, dtype=float).reshape( + n_variables, n_regressors + ) + intercept = np.r_[equation_rows[:, 0], np.zeros(n_variables)] + companion = np.zeros((n_variables * n_lags, n_variables * n_lags)) + companion[:n_variables] = equation_rows[:, 1:] + companion[n_variables:, :n_variables] = np.eye(n_variables) + return intercept, companion + + +def design_matrix(regressors): + """Return the observation matrix X_t prime for one date.""" + return np.kron(np.eye(n_variables), np.asarray(regressors, dtype=float)) +``` + +系数向量遵循一个无漂移的随机游走, + +```{math} +:label: csdv_transition +\theta_t = \theta_{t-1} + v_t, +\qquad +v_t \sim N(0,Q). +``` + +关于系数漂移速度的先验,在 {doc}`phillips_priors` 中扮演着一个镜像角色:在那里,是*政府*对漂移中的菲利普斯曲线的先验塑造了它所选择的政策,而在这里,则是*计量经济学家*在关于漂移中的简化形式动态的后验中所持的先验。 + +当伴随矩阵的每一个特征值都严格位于单位圆内时,伴随系统是稳定的。 + +对于 AR(1) 过程而言,这就是 $|\rho|<1$;等价地说,就是 $1-\rho z$ 的零点位于单位圆之外。 + +科格利和萨金特通过只保留每个日期伴随矩阵都稳定的路径来排除爆炸性路径,并使用如下截断先验, + +```{math} +:label: csdv_stability +p(\theta^T,Q) \propto I(\theta^T) f(\theta^T \mid Q) f(Q), +``` + +其中 $I(\theta^T)=1$ 表示一条稳定路径。 + +这一限制体现了这样一种信念,即经济事实上并未走上一条爆炸性的路径。 + +这一限制也使 $Q$ 的边际先验向那些不太可能生成爆炸性系数路径的取值倾斜。 + +下面的代码将稳定性限制应用于一整条轨迹 + +```{code-cell} ipython3 +def companion_roots(θ_path): + """Return all companion roots along a path with shape (21, T).""" + θ_path = np.asarray(θ_path, dtype=float) + if θ_path.ndim == 1: + θ_path = θ_path[:, None] + companions = np.stack( + [ + companion_matrix(θ_path[:, t])[1] + for t in range(θ_path.shape[1]) + ] + ) + return np.linalg.eigvals(companions) + + +def is_stable(θ_path): + """Test whether every companion root is strictly inside the unit circle.""" + return bool(np.max(np.abs(companion_roots(θ_path))) < 1) +``` + +简化形式的创新(新息)协方差按下式随时间变化, + +```{math} +:label: csdv_covariance +\varepsilon_t = R_t^{1/2}\xi_t, +\qquad +\xi_t \sim N(0,I_3), +\qquad +R_t = B^{-1} H_t B^{-1\prime}, +``` + +其中 + +$$ +B = +\begin{bmatrix} +1 & 0 & 0 \\ +\beta_{21} & 1 & 0 \\ +\beta_{31} & \beta_{32} & 1 +\end{bmatrix}, +\qquad +H_t = \operatorname{diag}(h_{1t},h_{2t},h_{3t}). +$$ + +对角元素 $h_{it}$ 使每个正交化冲击的大小能够随时间而消长。 + +接下来的两个函数分别构造三角因子和简化形式的创新协方差。 + +```{code-cell} ipython3 +def b_matrix(β): + """Construct B from β_21, β_31, and β_32.""" + matrix = np.eye(n_variables) + matrix[1, 0], matrix[2, 0], matrix[2, 1] = np.asarray(β, dtype=float) + return matrix + + +def innovation_covariance(h, β): + """Construct R_t from one vector of orthogonalized variances.""" + inverse = np.linalg.inv(b_matrix(β)) + return inverse @ np.diag(h) @ inverse.T +``` + +每个对角波动率都是一个几何随机游走, + +```{math} +:label: csdv_volatility +\log h_{it} = \log h_{i,t-1} + \sigma_i \eta_{it}, +\qquad +\eta_{it} \sim N(0,1). +``` + +标准化的量测创新、系数创新和波动率创新是相互独立的。 + +设定 $Q=0$ 会产生系数恒定、波动率漂移的模型,而固定 $H_t$ 则会产生系数漂移、波动率恒定的模型。 + +后验包含完整路径 $\theta^T$ 和 $H^T$,以及 $Q$、 +$\beta$ 和 $(\sigma_1,\sigma_2,\sigma_3)$。 + +这一后验有数千个维度,因此后续章节将构建一个每次更新一组参数、同时固定其余参数的抽样器。 + +## 数据 + +我们从 {cite:t}`CogleySargent2005` 使用的截至2000年第四季度的美国季度数据集开始。 + +通货膨胀是经季节调整的全体城市消费者 CPI 的对数差分,采样点为每季度的第三个月。 + +失业率是经季节调整的民用失业率的季度平均值,以 $0.01\log[u/(1-u)]$ 的形式进入 VAR,这是一种将有界的比率映射为无约束变量的 logit 变换。 + +名义利率是三个月期国库券利率加一后取对数,在每季度的第一个月对每日观测值取平均,并以季度分数表示。 + +数据始于1948年第二季度,因为其第一个通货膨胀观测值本身已是差分数据,所以两期 VAR 滞后使得1948年第四季度成为第一个可用的回归日期。 + +下面这个代码单元执行了所有变换,并直接从这些序列构造出 VAR(2) 数据。 + +```{code-cell} ipython3 +def prepare_data(source, ordering=('i', 'u', 'pi')): + """Transform a quarterly table and construct the VAR data.""" + if isinstance(source, (str, Path)): + table = pd.read_csv(source) + else: + table = source.copy() + variables = { + 'i': table['y3'].to_numpy(dtype=float), + 'u': 0.01 * np.log( + table['ur'].to_numpy(dtype=float) + / (1 - table['ur'].to_numpy(dtype=float)) + ), + 'pi': table['dp'].to_numpy(dtype=float), + } + if sorted(ordering) != ['i', 'pi', 'u']: + raise ValueError("ordering must be a permutation of ('i', 'u', 'pi')") + raw_y = np.column_stack([variables[name] for name in ordering]) + raw_dates = table['date'].to_numpy(dtype=float) + regressors = np.ones((len(table) - n_lags, n_regressors)) + for lag in range(1, n_lags + 1): + left = 1 + n_variables * (lag - 1) + regressors[:, left:left + n_variables] = raw_y[n_lags-lag:-lag] + targets = raw_y[n_lags:] + dates = raw_dates[n_lags:] + n_training = 4 * 11 - n_lags - 1 + return { + 'raw_dates': raw_dates, + 'raw_y': raw_y, + 'prior_dates': dates[:n_training], + 'prior_y': targets[:n_training], + 'prior_x': regressors[:n_training], + 'dates': dates[n_training:], + 'y': targets[n_training:], + 'x': regressors[n_training:], + } + + +data = prepare_data(data_path) + +data_summary = pd.Series( + { + 'ordering': 'interest, unemployment, inflation', + 'prior sample': '1948Q4--1958Q4', + 'prior observations': len(data['prior_dates']), + 'posterior sample': '1959Q1--2000Q4', + 'posterior observations': len(data['dates']), + 'VAR lags': n_lags, + 'coefficient dimension': n_coefficients, + }, + name='value', +) + +data_summary.to_frame() +``` + +早期的观测数据用于校准先验,其余的观测数据则构成后验样本。 + +让我们用熟悉的经济学单位来查看数据。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Observed $\pi_t$, $u_t$, and $i_t$, 1948Q2--2000Q4 + name: fig-csdv-historical-data +--- +dates_raw = data['raw_dates'] +interest = 400 * np.expm1(data['raw_y'][:, 0]) +unemployment = 100 * expit(100 * data['raw_y'][:, 1]) +inflation = 400 * data['raw_y'][:, 2] + +fig, axes = plt.subplots(3, 1, figsize=(9, 7), sharex=True) +axes[0].plot(dates_raw, inflation, lw=2) +axes[0].set_ylabel('inflation (annual %)') +axes[1].plot(dates_raw, unemployment, lw=2) +axes[1].set_ylabel('unemployment (%)') +axes[2].plot(dates_raw, interest, lw=2) +axes[2].set_ylabel('interest (annual %)') +axes[2].set_xlabel('year') +plt.tight_layout() +plt.show() +``` + +通货膨胀和名义利率在20世纪70年代一同上升,并在1980年前后达到峰值;失业率则在反通胀开始之后才达到峰值;而这三个序列在90年代都变得更为平稳。 + +这些观察结果定位了这一历史事件,但无法说明究竟是系统性动态发生了变化,还是出现了异常大的冲击才导致了这一现象——而这正是本模型所要考察的区别。 + +## 先验 + +各参数的先验彼此独立,且被有意设定得较为宽松,用科格利和萨金特的话说,就是要“让数据自由发声”。 + +它们是根据一个拟合于1948到1958年短训练样本的时不变 VAR 校准得到的。 + +初始系数先验是一个稳定的、截断的高斯分布, + +$$ +p(\theta_0) \propto I(\theta_0)N(\bar\theta,\bar P), +$$ + +其中 $\bar\theta$ 和 $\bar P$ 来自一个拟合于1948—1958训练样本的常系数似不相关回归(SUR)。 + +由于三个方程具有完全相同的回归变量,SUR 系数估计等于逐方程的OLS估计,这使我们能够简洁地实现这一校准。 + +```{code-cell} ipython3 +def sur_prior(y, x): + """Calibrate the Gaussian coefficient prior from a constant VAR.""" + xx_inverse = np.linalg.inv(x.T @ x) + coefficients = xx_inverse @ x.T @ y + residuals = y - x @ coefficients + residual_covariance = np.cov(residuals, rowvar=False, ddof=1) + θ = coefficients.T.reshape(-1) + covariance = np.kron(residual_covariance, xx_inverse) + return θ, covariance, residual_covariance + + +θ_bar, p_bar, r_bar = sur_prior(data['prior_y'], data['prior_x']) + +assert is_stable(θ_bar) +``` + +系数漂移的协方差具有如下逆威沙特先验 + +```{math} +:label: csdv_q_prior +Q \sim IW_{21}\left(T_0,T_0\bar Q\right), +\qquad +T_0 = 22, +\qquad +\bar Q = \gamma^2 \bar P, +\qquad +\gamma^2 = 3.5\times 10^{-4}. +``` + +在 {eq}`csdv_q_prior` 中的约定是先列出自由度,再列出逆威沙特尺度矩阵。 + +由于 $T_0$ 仅比 $\theta_t$ 的维数大一,这个先验虽然合式(proper),但没有有限均值。 + +因此矩阵 $\bar Q$ 是一个保守的尺度校准值,而非 $Q$ 的期望。 + +在后验看到主样本之前,这一校准倾向于支持缓慢的系数漂移。 + +其余的先验分布为 + +$$ +\begin{aligned} +\log h_{i0} &\sim N(\log \bar R_{ii},10), \\ +\beta &\sim N(0,10000I_3), \\ +\sigma_i^2 &\sim IG\left(\frac{1}{2},\frac{0.01^2}{2}\right), +\end{aligned} +$$ + +其中 $\bar R$ 是来自训练样本回归的残差协方差。 + +下面的函数汇总了这些超参数。 + +```{code-cell} ipython3 +def calibrate_prior(model_data, γ_squared=3.5e-4): + """Return every calibrated prior for one variable ordering.""" + θ_mean, θ_covariance, residual_covariance = sur_prior( + model_data['prior_y'], model_data['prior_x'] + ) + degrees_freedom = n_coefficients + 1 + q_center = γ_squared * θ_covariance + return { + 'θ_mean': θ_mean, + 'θ_covariance': θ_covariance, + 'q_center': q_center, + 'q_scale': degrees_freedom * q_center, + 'q_degrees_freedom': degrees_freedom, + 'log_h_mean': np.log(np.diag(residual_covariance)), + 'log_h_variance': 10.0, + 'β_mean': np.zeros(3), + 'β_variance': 10000.0, + 'σ_degrees_freedom': 1.0, + 'σ_scale': 0.01**2, + 'γ_squared': γ_squared, + } + + +prior = calibrate_prior(data) +q_bar = prior['q_center'] + +prior_summary = pd.Series( + { + 'dim(θ)': n_coefficients, + 'T0': prior['q_degrees_freedom'], + 'γ squared': prior['γ_squared'], + 'trace(Q bar)': np.trace(q_bar), + 'log-h prior variance': prior['log_h_variance'], + 'β prior variance': prior['β_variance'], + 'σ-squared IG shape': prior['σ_degrees_freedom'] / 2, + 'σ-squared IG scale': prior['σ_scale'] / 2, + }, + name='value', +) + +prior_summary.to_frame() +``` + +## 一个 Metropolis-within-Gibbs 抽样器 + +我们通过遍历 {cite:t}`CogleySargent2005` 所使用的五个参数模块来模拟后验。 + +遍历全部五个模块一次称为一个扫描(sweep),抽样器要运行多次扫描才能构建出后验样本。 + +科格利和萨金特模拟不受限制的后验,然后每当某次完整的 MCMC 实现出现爆炸性系数路径时,就丢弃该实现。 + +但在本例中,只有稳定的扫描才会为保留的受限后验样本贡献实现值。 + +我们改用 {cite:t}`MurrayAdamsMacKay2010` 的椭圆切片抽样器,在系数路径模块内部施加稳定性限制。 + +这改变了转移核,但没有改变其目标后验。 + +1. 通过 Carter—Kohn 前向滤波/后向抽样步骤抽取一条辅助的高斯系数路径,并用它通过椭圆切片抽样来更新稳定路径。 + +2. 漂移协方差 $Q$ 以系数创新为条件,从一个逆威沙特分布中抽取。 + +3. 波动率创新方差 $\sigma_i^2$ 以波动率增量为条件,从逆伽马分布中抽取。 + +4. 协方差参数 $\beta$ 从关于 VAR 残差的两个变换后的高斯回归中抽取。 + +5. 波动率路径 $H^T$ 通过一个 Jacquier—Polson—Rossi Metropolis 步骤逐日期抽取。 + +这个顺序很重要:一次扫描中的每个模块都要与它实际所依据的条件值配对。 + +### 系数路径 + +以 $R^T$ 和 $Q$ 为条件,一个前向卡尔曼滤波后接 Carter—Kohn 后向模拟器可抽取整条系数路径 {cite}`CarterKohn1994`。 + +前向步骤是一个卡尔曼滤波,而后向步骤则按 $\theta_T,\theta_{T-1},\ldots,\theta_0$ 的相反顺序抽样,每个状态都以其之后抽出的值为条件。 + +对 $\theta_0$ 进行抽样是必不可少的。 + +它为 $Q$ 的共轭更新提供了全部 $T$ 个随机游走增量。 + +```{code-cell} ipython3 +def covariance_root(matrix): + """Return a numerically stable lower covariance factor.""" + matrix = 0.5 * (matrix + matrix.T) + scale = max(1.0, np.max(np.abs(np.diag(matrix)))) + return np.linalg.cholesky(matrix + 1e-12 * scale * np.eye(len(matrix))) + + +def draw_coefficient_path( + y, x, q, h, β, prior, rng, return_mean=False +): + """Draw θ_0,...,θ_T and optionally return its smoothing mean.""" + periods = len(y) + filtered_mean = np.empty((periods + 1, n_coefficients)) + filtered_covariance = np.empty( + (periods + 1, n_coefficients, n_coefficients) + ) + predicted_covariance = np.empty_like(filtered_covariance) + filtered_mean[0] = prior['θ_mean'] + filtered_covariance[0] = prior['θ_covariance'] + predicted_covariance[0] = prior['θ_covariance'] + for t in range(1, periods + 1): + observation = design_matrix(x[t - 1]) + prediction_covariance = filtered_covariance[t - 1] + q + r_t = innovation_covariance(h[t], β) + forecast_covariance = ( + observation @ prediction_covariance @ observation.T + r_t + ) + gain = linalg.solve( + forecast_covariance, + (prediction_covariance @ observation.T).T, + assume_a='pos', + ).T + mean = filtered_mean[t - 1] + mean = mean + gain @ (y[t - 1] - observation @ mean) + covariance = ( + prediction_covariance + - gain @ observation @ prediction_covariance + ) + covariance = 0.5 * (covariance + covariance.T) + filtered_mean[t] = mean + filtered_covariance[t] = covariance + predicted_covariance[t] = prediction_covariance + path = np.empty((n_coefficients, periods + 1)) + if not return_mean: + path[:, -1] = ( + filtered_mean[-1] + + covariance_root(filtered_covariance[-1]) + @ rng.standard_normal(n_coefficients) + ) + for t in range(periods - 1, -1, -1): + smoother = linalg.solve( + predicted_covariance[t + 1], + filtered_covariance[t].T, + assume_a='pos', + ).T + mean = filtered_mean[t] + smoother @ ( + path[:, t + 1] - filtered_mean[t] + ) + covariance = ( + filtered_covariance[t] + - smoother @ predicted_covariance[t + 1] @ smoother.T + ) + path[:, t] = mean + covariance_root(covariance) @ ( + rng.standard_normal(n_coefficients) + ) + return path + + smoothed_mean = np.empty_like(path) + centered_draw = np.empty_like(path) + smoothed_mean[:, -1] = filtered_mean[-1] + centered_draw[:, -1] = covariance_root(filtered_covariance[-1]) @ ( + rng.standard_normal(n_coefficients) + ) + for t in range(periods - 1, -1, -1): + smoother = linalg.solve( + predicted_covariance[t + 1], + filtered_covariance[t].T, + assume_a='pos', + ).T + smoothed_mean[:, t] = filtered_mean[t] + smoother @ ( + smoothed_mean[:, t + 1] - filtered_mean[t] + ) + covariance = ( + filtered_covariance[t] + - smoother @ predicted_covariance[t + 1] @ smoother.T + ) + centered_draw[:, t] = ( + smoother @ centered_draw[:, t + 1] + + covariance_root(covariance) @ rng.standard_normal(n_coefficients) + ) + return smoothed_mean + centered_draw, smoothed_mean + + +def draw_stable_coefficient_path( + current, y, x, q, h, β, prior, rng, max_contractions=100 +): + """Elliptical-slice update of the stability-truncated Gaussian path.""" + if not is_stable(current): + raise ValueError('the elliptical-slice update needs a stable path') + gaussian_draw, mean = draw_coefficient_path( + y, x, q, h, β, prior, rng, return_mean=True + ) + current_centered = current - mean + innovation = gaussian_draw - mean + angle = rng.uniform(0, 2 * np.pi) + lower = angle - 2 * np.pi + upper = angle + for contractions in range(max_contractions + 1): + proposal = ( + mean + + current_centered * np.cos(angle) + + innovation * np.sin(angle) + ) + if is_stable(proposal): + return proposal, contractions + if angle < 0: + lower = angle + else: + upper = angle + angle = rng.uniform(lower, upper) + raise RuntimeError('elliptical-slice stability bracket did not contract') +``` + +### 漂移协方差 + +以系数增量为条件,$Q$ 具有一个逆威沙特的完全条件分布。 + +所保留的模拟从一个由其先验尺度和从 $\theta_0$ 到 $\theta_T$ 的全部 $T$ 个平方增量构成的尺度矩阵中抽取 $Q$。 + +```{code-cell} ipython3 +def draw_q(θ_path, prior, rng): + """Draw Q conditional on the sampled coefficient path.""" + increments = np.diff(θ_path, axis=1) + scale = prior['q_scale'] + increments @ increments.T + degrees_freedom = prior['q_degrees_freedom'] + increments.shape[1] + return invwishart.rvs(df=degrees_freedom, scale=scale, random_state=rng) +``` + +### 波动率参数与路径 + +以波动率增量为条件,每个 $\sigma_i^2$ 具有一个逆伽马完全条件分布。 + +以 VAR 残差和 $H^T$ 为条件,$B$ 中的自由元素通过两个高斯回归抽取。 + +以正交化残差为条件,每个波动率状态都用 {cite:t}`Jacquier1994` 提出的单点 Metropolis 步骤进行更新。 + +随机游走的相邻值决定了对数波动率的高斯提议分布,而对应的正交化残差则决定该提议是否被接受。 + +以下代码实现了这些条件更新,包括不同的端点提议方式。 + +```{code-cell} ipython3 +def var_residuals(y, x, θ_path): + """Return residuals with shape (T, 3).""" + if θ_path.shape[1] == len(y) + 1: + θ_path = θ_path[:, 1:] + if θ_path.shape[1] != len(y): + raise ValueError('θ_path must contain T or T + 1 states') + coefficients = θ_path.T.reshape(len(y), n_variables, n_regressors) + fitted = np.einsum('tk,tnk->tn', x, coefficients) + return y - fitted + + +def draw_σ(h, prior, rng): + """Draw the three log-volatility innovation standard deviations.""" + increments = np.diff(np.log(h), axis=0) + shape = (prior['σ_degrees_freedom'] + increments.shape[0]) / 2 + scales = (prior['σ_scale'] + np.sum(increments**2, axis=0)) / 2 + σ_squared = scales / rng.gamma(shape, 1.0, size=n_variables) + return np.sqrt(σ_squared) + + +def draw_β(residuals, h, prior, rng): + """Draw the free elements of B from transformed Gaussian regressions.""" + β = np.empty(3) + offset = 0 + for equation in range(1, n_variables): + standardized = residuals / np.sqrt(h[1:, equation])[:, None] + dependent = standardized[:, equation] + regressors = -standardized[:, :equation] + prior_precision = np.eye(equation) / prior['β_variance'] + covariance = np.linalg.inv(prior_precision + regressors.T @ regressors) + prior_slice = prior['β_mean'][offset:offset + equation] + mean = covariance @ ( + prior_precision @ prior_slice + regressors.T @ dependent + ) + β[offset:offset + equation] = ( + mean + covariance_root(covariance) @ rng.standard_normal(equation) + ) + offset += equation + return β + + +def accept_volatility(proposal, current, residual, rng): + """Apply the Jacquier--Polson--Rossi likelihood acceptance step.""" + log_ratio = ( + -0.5 * np.log(proposal) + - residual**2 / (2 * proposal) + + 0.5 * np.log(current) + + residual**2 / (2 * current) + ) + return proposal if np.log(rng.random()) <= min(0.0, log_ratio) else current + + +def draw_volatility_path(h, residuals, β, σ, prior, rng): + """Update all stochastic-volatility states one date at a time.""" + periods = len(residuals) + orthogonalized = (b_matrix(β) @ residuals.T).T + updated = np.empty_like(h) + for equation in range(n_variables): + variance = σ[equation]**2 + initial_variance = ( + prior['log_h_variance'] * variance + / (variance + prior['log_h_variance']) + ) + initial_mean = initial_variance * ( + prior['log_h_mean'][equation] / prior['log_h_variance'] + + np.log(h[1, equation]) / variance + ) + updated[0, equation] = np.exp( + initial_mean + np.sqrt(initial_variance) * rng.standard_normal() + ) + for t in range(1, periods): + mean = 0.5 * ( + np.log(updated[t - 1, equation]) + np.log(h[t + 1, equation]) + ) + proposal = np.exp( + mean + np.sqrt(variance / 2) * rng.standard_normal() + ) + updated[t, equation] = accept_volatility( + proposal, + h[t, equation], + orthogonalized[t - 1, equation], + rng, + ) + proposal = np.exp( + np.log(updated[-2, equation]) + + σ[equation] * rng.standard_normal() + ) + updated[-1, equation] = accept_volatility( + proposal, + h[-1, equation], + orthogonalized[-1, equation], + rng, + ) + return updated +``` + +### 完整的抽样器 + +受限后验对在任何日期(包括 $\theta_0$)出现爆炸性的系数路径都赋予零密度。 + +将整条系数路径 $\theta_0,\ldots,\theta_T$ 堆叠成 $z$,并把其余的参数模块收集在 +$\lambda=(Q,H^T,\beta,\sigma)$ 中。 + +以 $\lambda$ 和数据 $Y^T$ 为条件,不受限制的 Carter—Kohn 分布是一个均值为 +$m$、协方差为 $C$ 的高斯分布, + +$$ +z\mid \lambda,Y^T \sim N(m,C). +$$ + +设 $\mathcal A$ 为在每个日期其伴随根都严格位于单位圆内的路径集合,那么受限的完全条件就是这个截断到 $\mathcal A$ 上的高斯分布, + +$$ +\pi_{\mathcal A}(z\mid\lambda,Y^T) += \frac{N(z;m,C)\,\mathbb{1}_{\mathcal A}(z)} + {\Pr(z\in\mathcal A\mid\lambda,Y^T)}. +$$ + +那个归一化概率难以计算,但椭圆转移从不需要对它求值。 + +科格利和萨金特转而模拟不受限制的联合后验,并只有在整条路径都稳定时才保留一个实现值,这是有效的,因为在不受限制的后验上以 $z\in\mathcal A$ 为条件恰好精确地重现了受限后验。 + +如果用 $a$ 表示一条路径不受限制时是稳定的概率,那么这种拒绝方案对每一个保留的抽样大约需要 $1/a$ 次完整的扫描,其中还包括其余四个参数的更新。 + +椭圆切片抽样器通过在稳定区域内部移动而非从任意抽样重新开始,避免了这种浪费。 + +它从当前的稳定路径 $z^{(c)}$ 和一个新抽取的 Carter—Kohn +样本 $\widetilde z\sim N(m,C)$ 出发,其中心化版本 +$\nu=\widetilde z-m$ 与 $z^{(c)}$ 一起描绘出一个椭圆, + +$$ +z(\phi) +=m+(z^{(c)}-m)\cos\phi+\nu\sin\phi, +\qquad 0\leq\phi<2\pi, +$$ + +因此 $z(0)=z^{(c)}$ 且 $z(\pi/2)=\widetilde z$。 + +该算法从整个圆周上均匀地抽取一个角度,每当 $z(\phi)$ 是爆炸性的,就把括号(bracket)收缩到包含已知稳定角度 $\phi=0$ 的那一侧,然后再重新抽取。 + +由于伴随根随系数连续变化,$\phi=0$ 周围总存在一个非零区间是稳定的,因此这一括号搜索总能终止。 + +每一个被拒绝的角度只花费一次线性组合运算和一次伴随根检验的代价,比再执行一次卡尔曼滤波和后向模拟便宜得多。 + +该转移是有效的,因为将配对 $(z^{(c)}-m,\nu)$ 旋转任意角度都不会改变它们的联合高斯密度,因此这一搜索沿着一条固定轨道移动,在这条轨道上每一点在不受限制的密度下都是等可能的。 + +稳定性指示函数在标准椭圆切片更新中扮演着似然函数的角色,并且由于它在当前点处等于一,每一个被接受的角度都自动是稳定的,无需再进行单独的切片高度抽样。 + +将辅助路径边缘化后可以证明,这一转移使截断的高斯分布 +$N(z;m,C)\mathbb{1}_{\mathcal A}(z)$ 保持不变,这正是一个有效转移核所需要具备的性质。 + +其余四个模块不需要这样的调整。 + +以一个稳定的 $z$ 为条件,稳定性指示函数在 +$Q,H^T,\beta$ 和 $\sigma$ 上都是常数,因此它会从它们各自的完全条件中约去,留下的更新与不受限制的抽样器相同。 + +$Q$ 的条件分布在形式上没有变化,但由于每次抽取的 $Q$ 都以一条稳定的系数路径为条件,其边际后验仍然会向不那么爆炸性的漂移倾斜。 + +综合起来,对 $z$ 的椭圆转移,以及对 +$Q,H^T,\beta$ 和 $\sigma$ 不加改变的更新,以远低于科格利和萨金特原始拒绝抽样器的代价,瞄准同一个受稳定性限制的后验。 + +下面这个函数将这五个模块组合在一起,并包含一个随机波动率的预热阶段。 + +```{code-cell} ipython3 +def initial_volatilities(y, prior): + """Construct the sampler's initial volatility path.""" + changes = np.diff(y, axis=0) + centered = changes - changes.mean(axis=0) + log_h = np.empty((len(y) + 1, n_variables)) + log_h[:2] = prior['log_h_mean'] + log_h[2:] = np.log(np.maximum(centered**2, np.finfo(float).tiny)) + return np.exp(log_h) + + +def run_sampler( + y, + x, + prior, + n_sweeps=1_000, + burn=500, + thin=1, + seed=42, + warmup=200, + max_contractions=100, + stable=True, + fixed_q=None, + retain=('S0D', 'SD', 'QD', 'HD', 'CD', 'VD', 'stable_draw'), + progress_every=0, +): + """Run a Gibbs sampler for the unrestricted or stable posterior. + + For the stable posterior, an elliptical-slice transition updates the FFBS + path inside its stability-truncated Gaussian full conditional. Passing + ``fixed_q`` holds Q at that value (for example a matrix of zeros) instead of + drawing it, which nests the constant-coefficient model. + """ + if not (0 <= burn < n_sweeps and thin >= 1): + raise ValueError('require 0 <= burn < n_sweeps and thin >= 1') + if (n_sweeps - burn) % thin: + raise ValueError('(n_sweeps - burn) must be divisible by thin') + valid_retain = {'S0D', 'SD', 'QD', 'HD', 'CD', 'VD', 'stable_draw'} + unknown = set(retain) - valid_retain + if unknown: + raise ValueError(f'unknown retained arrays: {sorted(unknown)}') + + started = time.perf_counter() + rng = np.random.default_rng(seed) + h = initial_volatilities(y, prior) + β = prior['β_mean'].copy() + warm_θ = np.repeat(prior['θ_mean'][:, None], len(y), axis=1) + warm_residuals = var_residuals(y, x, warm_θ) + for _ in range(warmup): + σ = draw_σ(h, prior, rng) + β = draw_β(warm_residuals, h, prior, rng) + h = draw_volatility_path( + h, warm_residuals, β, σ, prior, rng + ) + + q = ( + prior['q_center'].copy() + if fixed_q is None + else np.array(fixed_q, dtype=float) + ) + θ = np.repeat( + prior['θ_mean'][:, None], len(y) + 1, axis=1 + ) + if stable and not is_stable(θ): + raise ValueError('the prior mean does not provide a stable start') + slice_contractions = 0 + maximum_slice_contractions = 0 + + retained = {name: [] for name in retain} + saved_stability = [] + for sweep in range(1, n_sweeps + 1): + if stable: + θ, contractions = draw_stable_coefficient_path( + θ, + y, + x, + q, + h, + β, + prior, + rng, + max_contractions=max_contractions, + ) + else: + θ = draw_coefficient_path(y, x, q, h, β, prior, rng) + contractions = 0 + slice_contractions += contractions + maximum_slice_contractions = max( + maximum_slice_contractions, contractions + ) + if fixed_q is None: + q = draw_q(θ, prior, rng) + residuals = var_residuals(y, x, θ) + σ = draw_σ(h, prior, rng) + β = draw_β(residuals, h, prior, rng) + h = draw_volatility_path( + h, residuals, β, σ, prior, rng + ) + + if sweep > burn and (sweep - burn) % thin == 0: + path_is_stable = is_stable(θ) + saved_stability.append(path_is_stable) + values = { + 'S0D': θ[:, 0], + 'SD': θ[:, 1:], + 'QD': q, + 'HD': h, + 'CD': β, + 'VD': σ, + 'stable_draw': path_is_stable, + } + for name in retained: + retained[name].append(np.asarray(values[name]).copy()) + + if progress_every and sweep % progress_every == 0: + elapsed = time.perf_counter() - started + print( + f'{sweep:,}/{n_sweeps:,} sweeps; ' + f'{slice_contractions:,} slice contractions; ' + f'{elapsed / 60:.1f} minutes', + flush=True, + ) + + stack_axis = { + 'S0D': 1, + 'SD': 2, + 'QD': 2, + 'HD': 2, + 'CD': 1, + 'VD': 1, + 'stable_draw': 0, + } + result = { + name: np.stack(values, axis=stack_axis[name]) + for name, values in retained.items() + } + result['diagnostics'] = { + 'sampler_version': 3, + 'seed': int(seed), + 'stable_restriction': bool(stable), + 'n_sweeps': int(n_sweeps), + 'burn': int(burn), + 'thin': int(thin), + 'warmup': int(warmup), + 'retained_draws': int((n_sweeps - burn) // thin), + 'slice_contractions': int(slice_contractions), + 'mean_slice_contractions': float(slice_contractions / n_sweeps), + 'maximum_slice_contractions': int(maximum_slice_contractions), + 'retained_stability_rate': float(np.mean(saved_stability)), + 'elapsed_seconds': float(time.perf_counter() - started), + } + return result +``` + +下面这个可执行的版本使用1,000次扫描,丢弃前500次,保留其余的500次。 + +它使用了完整的历史样本,采用 $(i,u,\pi)$ 的排序。 + +我们没有运行一次大型的 MCMC 实验,而是有意让抽样器运行规模较小,以便在讲座中能在合理时间内完成。 + +这次简短的运行说明了该方法,但并非一次数值上的复现。 + +不过后验的主要定性特征与科格利和萨金特所报告的结果相近。 + +```{code-cell} ipython3 +posterior = run_sampler( + data['y'], + data['x'], + prior, + n_sweeps=1_000, + burn=500, + thin=1, + seed=42, + warmup=200, + stable=True, + progress_every=0, +) + +def validate_posterior_arrays(result, periods): + """Check posterior shapes, finiteness, positivity, and stability.""" + draws = result['diagnostics']['retained_draws'] + expected = { + 'S0D': (n_coefficients, draws), + 'SD': (n_coefficients, periods, draws), + 'QD': (n_coefficients, n_coefficients, draws), + 'HD': (periods + 1, n_variables, draws), + 'CD': (3, draws), + 'VD': (3, draws), + 'stable_draw': (draws,), + } + assert {name: result[name].shape for name in expected} == expected + assert all(np.all(np.isfinite(result[name])) for name in expected) + assert np.all(result['HD'] > 0) + assert np.all(result['VD'] > 0) + assert np.all(result['stable_draw']) + return expected + + +expected_shapes = validate_posterior_arrays(posterior, len(data['dates'])) +``` + +## 数据揭示了什么 + +我们用后验均值系数路径 $E(\theta_t\mid T)$ 和后验均值协方差路径 +$E(R_t\mid T)$ 来总结后验,然后在我们所提出问题的背景下对其加以解释。 + +### 漂移的速率与结构 + +$Q$ 的迹衡量的是系数漂移的总体速率,$\operatorname{tr}(Q)=0$ 对应于系数恒定不变的情形。 + +直方图展示了保留下来的 $Q$ 抽样以及先验尺度。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Posterior $\operatorname{tr}(Q)$ and prior $\operatorname{tr}(\bar Q)$ + name: fig-csdv-drift-rate +--- +trace_q = np.trace(posterior['QD'], axis1=0, axis2=1) +fig, ax = plt.subplots() +ax.hist(trace_q, bins=30, histtype='step', lw=2) +ax.axvline(np.trace(q_bar), color='C1', lw=2, + label=r'prior $\mathrm{tr}(\bar Q)$') +ax.set_xlabel(r'$\mathrm{tr}(Q)$') +ax.set_ylabel('frequency') +ax.legend() +plt.show() +``` + +后验漂移速率明显高于保守的先验校准值,表明系数变动幅度大于该校准值所预期的水平。 + +这并非与固定系数模型的正式比较,因为连续先验没有在 $Q=0$ 处赋予任何点质量。 + +在已拟合的 TVP-VAR 模型内部,这种变动被归因于系统性关系的变化;它并不能确定政策就是其原因。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Posterior mean VAR coefficients $E(\theta_t\mid T)$ + name: fig-csdv-coefficient-paths +--- +θ_mean = posterior['SD'].mean(axis=2) +mean_path_root_modulus = np.max( + np.abs(companion_roots(θ_mean)), axis=1 +) +assert np.all(mean_path_root_modulus < 1) +coefficient_labels = ( + 'constant', + r'$i_{t-1}$', + r'$u_{t-1}$', + r'$\pi_{t-1}$', + r'$i_{t-2}$', + r'$u_{t-2}$', + r'$\pi_{t-2}$', +) +equation_labels = ( + 'interest equation', + 'unemployment equation', + 'inflation equation', +) + + +def plot_equation_coefficients(axes, dates, θ_path): + """Plot seven labeled coefficients for each VAR equation.""" + first_lines = None + for equation, (ax, label) in enumerate(zip(axes, equation_labels)): + start = equation * len(coefficient_labels) + stop = start + len(coefficient_labels) + lines = ax.plot(dates, θ_path[start:stop].T, lw=2) + for line, coefficient_label in zip(lines, coefficient_labels): + line.set_label(coefficient_label) + if first_lines is None: + first_lines = lines + ax.axhline(0, color='0.65', lw=1) + ax.set_xlabel('year') + ax.set_ylabel(f'{label} coefficient') + return first_lines + + +fig, axes = plt.subplots(1, 3, figsize=(10, 4), sharex=True) +coefficient_lines = plot_equation_coefficients( + axes, + data['dates'], + θ_mean, +) +fig.legend( + coefficient_lines, + coefficient_labels, + loc='lower center', + ncol=4, +) +plt.tight_layout(rect=(0, 0.17, 1, 1)) +plt.show() +``` + +失业方程相对稳定,而通货膨胀方程中的若干系数在整个70年代剧烈波动,并在1980年前后出现转折。 + +因此,漂移主要集中在通货膨胀如何传播这一方面,而非均匀分布在整个 VAR 中,并且不应对单个滞后系数做出结构性解释,因为成对的滞后项可能相互抵消。 + +我们针对排序 $(i,u,\pi)$ 来总结漂移情况,该排序具有最小的稳定后验均值 $\operatorname{tr}(Q)$。 + +```{code-cell} ipython3 +trace_q = np.trace(posterior['QD'], axis1=0, axis2=1) +q_mean = posterior['QD'].mean(axis=2) +drift_summary = { + r'\text{Posterior mean } \operatorname{tr}(Q)': np.trace(q_mean), + r'\text{Posterior mean largest eigenvalue}': ( + np.linalg.eigvalsh(q_mean)[-1] + ), + r'\text{Prior } \operatorname{tr}(\bar Q)': np.trace(q_bar), +} +drift_rows = ' \\\\\n'.join( + f'{label} & {value:.4f}' for label, value in drift_summary.items() +) +display(Math(rf''' +\begin{{array}}{{lr}} +\text{{Quantity}} & \text{{Estimate}} \\ +\hline +{drift_rows} +\end{{array}} +''')) +``` + +科格利和萨金特对每一种排序都做了估计。 + +他们的后验均值表明,排序的改变会影响数值大小,但不会消除漂移: + +| Ordering | Stable $\operatorname{tr}(Q)$ | Stable $\max(\lambda)$ | Unrestricted $\operatorname{tr}(Q)$ | Unrestricted $\max(\lambda)$ | +|---|---:|---:|---:|---:| +| $(i,\pi,u)$ | 0.055 | 0.025 | 0.056 | 0.027 | +| $(i,u,\pi)$ | 0.047 | 0.023 | 0.059 | 0.031 | +| $(\pi,i,u)$ | 0.064 | 0.031 | 0.082 | 0.044 | +| $(\pi,u,i)$ | 0.062 | 0.031 | 0.088 | 0.051 | +| $(u,i,\pi)$ | 0.057 | 0.026 | 0.051 | 0.028 | +| $(u,\pi,i)$ | 0.055 | 0.024 | 0.072 | 0.035 | + +对于使 $Q$ 最小的排序而言,去掉稳定性限制会提高后验均值漂移速率,如上表所示。 + +后文的分析采用 $(i,u,\pi)$ 排序,即将名义利率排在首位、通货膨胀排在末位。 + +对 $Q$ 的后验均值进行对角化后可以发现,漂移是低维的。 + +以下的特征分解总结了 $Q$ 的后验均值。 + +```{code-cell} ipython3 +q_mean = posterior['QD'].mean(axis=2) +q_eigenvalues = np.linalg.eigvalsh(q_mean)[::-1] +q_cumulative = np.cumsum(q_eigenvalues) / q_eigenvalues.sum() + +drift_structure = pd.DataFrame( + { + 'eigenvalue': q_eigenvalues[:3], + 'cumulative share': q_cumulative[:3], + }, + index=pd.Index(range(1, 4), name='principal component'), +) +drift_structure.round(4) +``` + +即使 VAR 包含21个系数,前三个主成分也占据了系数漂移总量中的大多数。 + +### 波动率的演变 + +我们首先要问的是,冲击的*大小*是如何变化的。 + +方程 {eq}`csdv_covariance` 可以在各次抽样之间取平均,而无需构造一个四维的协方差数组。 + +```{code-cell} ipython3 +def mean_innovation_covariance(h_draws, β_draws): + """Compute E(R_t | T) with working memory proportional to T times D.""" + n_draws = h_draws.shape[2] + matrices = np.broadcast_to(np.eye(3), (n_draws, 3, 3)).copy() + matrices[:, 1, 0] = β_draws[0] + matrices[:, 2, 0] = β_draws[1] + matrices[:, 2, 1] = β_draws[2] + inverses = np.linalg.solve( + matrices, + np.broadcast_to(np.eye(3), matrices.shape), + ) + h = h_draws[1:] + mean = np.empty((h.shape[0], 3, 3)) + for row in range(3): + for column in range(row + 1): + value = np.zeros(h.shape[0]) + for shock in range(3): + weights = inverses[:, row, shock] * inverses[:, column, shock] + value += h[:, shock, :] @ weights + mean[:, row, column] = value / n_draws + mean[:, column, row] = mean[:, row, column] + return mean + + +r_mean = mean_innovation_covariance(posterior['HD'], posterior['CD']) +``` + +下图展示了创新标准差和相关系数。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Standard deviations and correlations implied by $E(R_t\mid T)$ + name: fig-csdv-volatility-correlation +--- +variances = ((0, 'Nominal interest'), (2, 'Inflation'), (1, 'Unemployment')) +correlations = ( + (0, 1, 'Interest--unemployment'), + (0, 2, 'Interest--inflation'), + (2, 1, 'Inflation--unemployment'), +) +fig, axes = plt.subplots(3, 2, figsize=(9, 8), sharex=True) +for row, (index, label) in enumerate(variances): + axes[row, 0].plot( + data['dates'], 10000 * np.sqrt(r_mean[:, index, index]), lw=2 + ) + axes[row, 0].set_title(label) +for row, (left, right, label) in enumerate(correlations): + scale = np.sqrt(r_mean[:, left, left] * r_mean[:, right, right]) + axes[row, 1].plot(data['dates'], r_mean[:, left, right] / scale, lw=2) + axes[row, 1].set_title(label) +axes[1, 0].set_ylabel( + r'innovation standard deviation $\times 10^4$' +) +axes[1, 1].set_ylabel('correlation') +axes[-1, 0].set_xlabel('year') +axes[-1, 1].set_xlabel('year') +plt.tight_layout() +plt.show() +``` + +利率和通货膨胀创新标准差在1980年前后急剧达到峰值,而失业创新波动率则在样本末段更为渐进地下降。 + +这三种创新的相关系数也都在1980年前后发生最剧烈的变动,因此简化形式冲击的大小和联合构成都发生了变化。 + +这些变动为“运气变化”即“运气不好”的解释赋予了重要地位,尽管利率创新本身并非结构性货币政策冲击。 + +后验均值协方差矩阵的对数行列式总结了广义单步创新方差 {cite}`Whittle1953`。 + +以下变换总结了广义创新方差。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Generalized innovation variance $\log |E(R_t\mid T)|$ + name: fig-csdv-total-variance +--- +sign, logdet_r = np.linalg.slogdet(r_mean) +assert np.all(sign > 0) +fig, ax = plt.subplots() +ax.plot(data['dates'], logdet_r, lw=2) +ax.set_xlabel('year') +ax.set_ylabel(r'$\log |E(R_t\mid T)|$') +plt.show() +``` + +由于对数行列式越不为负数意味着联合创新方差越大,从两阶段上升到1981年异常峰值、再到随后长期下降,标志着一次大规模冲击事件,随后是由 {cite:t}`KimNelson1999` 和 {cite:t}`McConnellPerezQuiros2000` 记录的“大缓和”(Great Moderation)时期。 + +这是关于运气变化最清晰的总体证据,但它无法解释接下来要考察的、以系数为基础的通货膨胀动态变化。 + +### 核心通货膨胀与自然失业率 + +为了研究系统性动态,我们把 $t$ 期的 VAR 用伴随形式写成 + +$$ +z_t = \mu_{t\mid T} + A_{t\mid T}z_{t-1} + e_t. +$$ + +在日期 $t$,局部均值 $m_t$ 是这样一个不动点:如果伴随形式的 VAR 系数固定在其后验均值处,且未来的创新为零,系统将收敛到该点。 + +```{math} +:label: csdv_local_means +m_t = (I-A_{t\mid T})^{-1}\mu_{t\mid T}, +\qquad +\bar\pi_t = 4s_\pi m_t, +\qquad +\bar u_t = \frac{\exp(100s_u m_t)}{1+\exp(100s_u m_t)}. +``` + +这里 $s_\pi$ 和 $s_u$ 从 $m_t$ 中选取通货膨胀和失业率,因子四对通货膨胀进行年化,逆 logit 变换则将失业率还原为观测到的比率。 + +这些是被冻结的局部系统在特定日期的稳态,而非整体漂移过程的无条件均值。 + +核心通货膨胀是冻结 $t$ 期系数所隐含的长期通货膨胀预测,而自然失业率则是相应的长期失业率锚点,而非自然利率,也不是下一季度失业率的预测值。 + +冻结当前系数并向前推算,恰恰是 {doc}`phillips_learning` 和 {doc}`phillips_escaping_nash` 中学习型政府所采用的*预期效用*(anticipated-utility)手法,这些政府的行为就好像自己当前的信念永远不会被修正一样。 + +以下的实现对核心通货膨胀进行了年化处理,并将存档数据中的失业率变换加以还原。 + +```{code-cell} ipython3 +def local_means(θ_path): + """Compute local core inflation and the natural unemployment rate.""" + θ_path = np.asarray(θ_path, dtype=float) + if θ_path.ndim == 1: + θ_path = θ_path[:, None] + core = np.empty(θ_path.shape[1]) + natural = np.empty(θ_path.shape[1]) + for t in range(θ_path.shape[1]): + intercept, companion = companion_matrix(θ_path[:, t]) + mean = np.linalg.solve(np.eye(6) - companion, intercept) + core[t] = 4 * mean[2] + natural[t] = expit(100 * mean[1]) + return core, natural + + +core_inflation, natural_rate = local_means(θ_mean) +``` + +我们绘制每年第四季度的观测值。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Local means $\bar\pi_t$ and $\bar u_t$ + name: fig-csdv-local-means +--- +def annual_indices(dates, start=1960): + """Return the final observation in each year from a start date.""" + year_values = np.floor(dates + 1e-8).astype(int) + return np.array( + [ + np.flatnonzero(year_values == year)[-1] + for year in np.unique(year_values) + if year >= start + ] + ) + + +years = np.floor(data['dates'] + 1e-8).astype(int) +annual = annual_indices(data['dates']) + +fig, ax = plt.subplots() +ax.plot(data['dates'][annual], 100 * core_inflation[annual], 'o-', lw=2, + markersize=3, label='core inflation') +ax.plot(data['dates'][annual], 100 * natural_rate[annual], '+-', lw=2, + markersize=5, label='natural rate') +ax.set_xlabel('year') +ax.set_ylabel('percent') +ax.legend() +plt.show() +``` + +```{code-cell} ipython3 +core_summary = pd.Series( + { + 'early-1960s mean core inflation (%)': ( + 100 * core_inflation[(years >= 1960) & (years <= 1964)].mean() + ), + 'peak core inflation (%)': 100 * core_inflation[annual].max(), + '1985--2000 mean core inflation (%)': ( + 100 * core_inflation[(years >= 1985) & (years <= 2000)].mean() + ), + }, + name='estimate', +) +core_summary.to_frame().round(2) +``` + +核心通货膨胀从60年代初的低水平攀升到1980年前后的高峰,然后回落;而自然失业率则从约5%更为平缓地上升到6.5%左右,随后又回落到接近4%的水平。 + +由于这两条曲线都由拟合的系数决定,而非由实现的冲击决定,它们的持续性变化指向了一个不断变化的系统性成分。 + +以下计算总结了它们在整个后验样本内的共同变动情况。 + +```{code-cell} ipython3 +core_natural_correlation = np.corrcoef(core_inflation, natural_rate)[0, 1] + +core_natural_correlation +``` + +$\bar\pi_t$ 与 $\bar u_t$ 之间强烈的正季度相关性表明,模型所隐含的长期通货膨胀和失业率锚点共享一个宽泛的周期,而并不意味着当前的通货膨胀与当前的失业率必须同向变动。 + +由于当最大根接近于一时,$(I-A_t)^{-1}$ 会放大微小的系数变化,长期均值本质上比短期预测更为敏感。 + +### 通货膨胀的持续性 + +我们现在要问的是,除了不断变动的波动率之外,系统性动态本身是否也发生了漂移。 + +主要的总结指标是通货膨胀持续性,用零频率处通货膨胀的归一化谱来衡量。 + +日期 $t$ 处通货膨胀的谱密度为 + +```{math} +:label: csdv_spectrum +f_{\pi\pi}(\omega,t) += +\frac{1}{2\pi} +s_\pi +(I-A_{t\mid T}e^{-i\omega})^{-1} +\mathcal R_t +(I-A_{t\mid T}'e^{i\omega})^{-1} +s_\pi', +``` + +其中 $\mathcal R_t$ 将 $E(R_t\mid T)$ 嵌入伴随系统中。 + +低频功率既取决于自回归系数,也取决于创新协方差。 + +下面这个函数计算任意以每季度周期数表示的频率下的通货膨胀功率,并且还返回日期 $t$ 的通货膨胀方差。 + +```{code-cell} ipython3 +def inflation_spectrum(θ, covariance, frequencies): + """Compute inflation power and its variance-normalized counterpart.""" + _, companion = companion_matrix(θ) + innovation = np.zeros((6, 6)) + innovation[:3, :3] = covariance + selector = np.zeros(6) + selector[2] = 1 + stationary = linalg.solve_discrete_lyapunov(companion, innovation) + variance = float(selector @ stationary @ selector) + power = np.empty(len(frequencies)) + for index, frequency in enumerate(frequencies): + phase = np.exp(-2j * np.pi * frequency) + transfer = np.linalg.solve(np.eye(6) - companion * phase, np.eye(6)) + power[index] = np.real( + selector @ transfer @ innovation @ transfer.conj().T @ selector + ) / (2 * np.pi) + return power, power / variance + +``` + +归一化谱除以日期 $t$ 的通货膨胀方差, + +```{math} +:label: csdv_normalized_spectrum +g_{\pi\pi}(\omega,t) += +\frac{f_{\pi\pi}(\omega,t)} +{\int_{-\pi}^{\pi}f_{\pi\pi}(\omega,t)d\omega}, +``` + +因此 $g_{\pi\pi}(0,t)$ 是一个基于自相关的持续性度量。 + +这一归一化去除了 $R_t$ 的一个公共尺度因子,但它仍可能依赖于 $R_t$ 中的相对方差和协方差。 + +第一张图单独展示了零频率处作为一维持续性总结的取值。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Normalized zero-frequency spectrum $g_{\pi\pi}(0,t)$ + name: fig-csdv-inflation-persistence +--- +zero_frequency = np.array([0.0]) +inflation_persistence = np.array([ + inflation_spectrum(θ_mean[:, t], r_mean[t], zero_frequency)[1][0] + for t in range(len(data['dates'])) +]) + +fig, ax = plt.subplots() +ax.plot( + data['dates'][annual], + inflation_persistence[annual], + 'o-', + lw=2, + markersize=3, +) +ax.set_xlabel('year') +ax.set_ylabel(r'$g_{\pi\pi}(0,t)$') +plt.show() +``` + +```{code-cell} ipython3 +persistence_summary = pd.Series( + { + '1960--64 mean': inflation_persistence[ + (years >= 1960) & (years <= 1964) + ].mean(), + '1970--79 mean': inflation_persistence[ + (years >= 1970) & (years <= 1979) + ].mean(), + '1985--2000 mean': inflation_persistence[ + (years >= 1985) & (years <= 2000) + ].mean(), + 'peak': inflation_persistence[annual].max(), + 'peak year': years[annual][np.argmax(inflation_persistence[annual])], + }, + name='estimate', +) +persistence_summary.to_frame().round(3) +``` + +归一化的零频率功率从60年代初的低水平急剧上升,在1980年前后达到高峰,然后在样本剩余的大部分时间里回落到一以下。 + +1980年后的这一崩溃不能用对所有创新进行一次比例缩放来解释,尽管这一归一化统计量仍可能取决于 $R_t$ 的组成。 + +作为比较,一个系数为 $\rho$ 的 $AR(1)$ 过程具有归一化零频率功率 +$(1+\rho)/[2\pi(1-\rho)]$。 + +介于2和10之间的取值对应于 $\rho$ 在约 $0.85$ 到 +$0.97$ 之间。 + +零频率路径省略了频率分布的其余部分。 + +下面的热力图展示了原始和方差归一化的通货膨胀功率如何随时间和频率两个维度变化。 + +```{code-cell} ipython3 +def inflation_spectrum_surface(θ_path, covariance_path, frequencies): + """Evaluate the inflation spectrum at each date on a frequency grid.""" + raw = np.empty((len(frequencies), θ_path.shape[1])) + normalized = np.empty_like(raw) + for date in range(θ_path.shape[1]): + raw[:, date], normalized[:, date] = inflation_spectrum( + θ_path[:, date], + covariance_path[date], + frequencies, + ) + return raw, normalized + + +spectrum_frequencies = np.linspace(0, 0.5, 41) +raw_spectrum, normalized_spectrum = inflation_spectrum_surface( + θ_mean, + r_mean, + spectrum_frequencies, +) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Inflation spectra $f_{\pi\pi}(\omega,t)$ and $g_{\pi\pi}(\omega,t)$ + name: fig-csdv-inflation-spectra +--- +spectrum_start = data['dates'] >= 1960 +fig, axes = plt.subplots(1, 2, figsize=(9, 4), sharey=True) +surfaces = ( + (raw_spectrum, 'raw spectrum', 'log10 power'), + (normalized_spectrum, 'normalized spectrum', 'log10 normalized power'), +) +for ax, (surface, title, color_label) in zip(axes, surfaces): + image = ax.pcolormesh( + data['dates'][spectrum_start], + spectrum_frequencies, + np.log10(surface[:, spectrum_start]), + shading='auto', + ) + ax.set_xlabel('year') + ax.set_ylabel(f'{title}\ncycles per quarter') + fig.colorbar(image, ax=ax, label=color_label) +plt.tight_layout() +plt.show() +``` + +原始谱在1980年前后靠近零频率的区域最为明亮,因为冲击和持续性都被放大了;而归一化谱则在整个70年代保留了一条宽泛的低频“脊”,并在1980年之后消退。 + +这条在归一化后依然存在的“脊”表明,大通胀不仅仅是一个高波动率的事件,因为通货膨胀冲击也以更持久的方式传播开来。 + +点估计并不能揭示数据对这些路径的确定程度有多强。 + +因此我们从每一个保留的抽样中计算相同的年度特征。 + +```{code-cell} ipython3 +def posterior_feature_draws(result, indices): + """Compute selected local means and persistence for retained draws.""" + n_draws = result['SD'].shape[2] + shape = (len(indices), n_draws) + core = np.empty(shape) + natural = np.empty(shape) + persistence = np.empty(shape) + for draw in range(n_draws): + core[:, draw], natural[:, draw] = local_means( + result['SD'][:, indices, draw] + ) + for row, date in enumerate(indices): + covariance = innovation_covariance( + result['HD'][date + 1, :, draw], + result['CD'][:, draw], + ) + persistence[row, draw] = inflation_spectrum( + result['SD'][:, date, draw], + covariance, + zero_frequency, + )[1][0] + return { + 'core': 100 * core, + 'natural': 100 * natural, + 'persistence': persistence, + } + + +historical_feature_draws = posterior_feature_draws(posterior, annual) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Posterior medians and pointwise 90 percent intervals for $\bar\pi_t$, $\bar u_t$, and $g_{\pi\pi}(0,t)$ + name: fig-csdv-feature-uncertainty +--- +fig, axes = plt.subplots(3, 1, figsize=(9, 8), sharex=True) +feature_specs = ( + ('core', 'core inflation (%)'), + ('natural', 'natural rate (%)'), + ('persistence', r'$g_{\pi\pi}(0,t)$'), +) +for ax, (key, ylabel) in zip(axes, feature_specs): + lower, median, upper = np.quantile( + historical_feature_draws[key], + (0.05, 0.5, 0.95), + axis=1, + ) + line, = ax.plot(data['dates'][annual], median, lw=2) + ax.fill_between( + data['dates'][annual], + lower, + upper, + color=line.get_color(), + alpha=0.2, + ) + ax.set_ylabel(ylabel) +axes[-1].set_xlabel('year') +plt.tight_layout() +plt.show() +``` + +实线是后验中位数,阴影区域是逐点的90%区间,而非针对整条路径的联合区间。 + +核心通货膨胀和持续性的中位数路径都保留了先升后于1980年后回落的走势,但它们右偏的区间在整个70年代及1980年前后都明显变宽。 + +自然失业率的中位数走势更为平滑,其在1980年前后以及样本终点处都存在较大的不确定性,因此历史走势的方向要比其确切幅度更为清晰。 + +以下这幅图比较了核心通货膨胀和持续性的时间走势。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: $\bar\pi_t$ and $g_{\pi\pi}(0,t)$ + name: fig-csdv-core-persistence +--- +core_persistence_correlation = np.corrcoef( + core_inflation, inflation_persistence +)[0, 1] + +fig, ax = plt.subplots() +ax.plot(data['dates'][annual], 100 * core_inflation[annual], 'o-', + lw=2, markersize=3, label='core inflation (%)') +ax.plot(data['dates'][annual], inflation_persistence[annual], 'x-', + lw=2, markersize=4, label='normalized spectrum at zero') +ax.set_xlabel('year') +ax.legend() +plt.show() +``` + +核心通货膨胀与归一化持续性在60年代末和70年代同步上升,并在1980年之后几乎同时崩溃,尽管在持续性降至一以下之后,核心通货膨胀仍保持为正值。 + +它们0.909的季度相关系数总结的是时间上的共性,而非因果关系,因为这两个度量单位不同,且都是同一组拟合系数的非线性总结。 + +在已拟合的 TVP-VAR 模型内部,这种共同变动支持了系统传播方式的变化以及冲击波动率变化都发挥了重要作用这一观点。 + +要与固定系数模型进行直接比较,需要拟合受限的 $Q=0$ 模型。 + +沃尔克反通胀期间持续性的下降,与逃逸路径模型的预测相冲突——在那些模型中,在从高通胀向低通胀过渡的过程中,持续性会不断增加 {cite}`Sargent1999,ChoWilliamsSargent2002`。 + +这种张力促使后来出现了一些学习模型,在这些模型中,决策者在70年代不愿实施反通胀措施,随后才改弦更张。 + +### 货币政策的积极程度 + +科格利和萨金特用一个前瞻性的泰勒规则来总结系统性政策, + +```{math} +:label: csdv_policy_rule +i_t = \beta_0 ++ \beta_1 E_t\bar\pi_{t,t+h_\pi} ++ \beta_2 E_t\bar u_{t,t+h_u} ++ \beta_3 i_{t-1} ++ \nu_t. +``` + +他们把积极程度系数定义为 $\mathcal A_t=\beta_1/(1-\beta_3)$,并把 +$\mathcal A_t\geq 1$ 的情形称为“积极”政策。 + +在每个日期,局部 VAR 所隐含的总体两阶段最小二乘投影会给出这些政策规则系数。 + +基准视界为 $h_\pi=4$ 季度和 $h_u=2$ 季度,反映了关于货币政策滞后效应的常规观点。 + +下面这个函数利用每个局部 VAR 的平稳二阶矩,将短期利率投影到模型所隐含的通货膨胀和失业预测上。 + +```{code-cell} ipython3 +def policy_rule_coefficients(θ, covariance, h_pi=4, h_u=2): + """Return the local policy-rule coefficients.""" + _, companion = companion_matrix(θ) + innovation = np.zeros((6, 6)) + innovation[:3, :3] = covariance + stationary_covariance = linalg.solve_discrete_lyapunov( + companion, innovation + ) + selectors = np.eye(6) + companion_power = np.eye(6) + inflation_loading = np.zeros(6) + unemployment_loading = np.zeros(6) + for horizon in range(1, max(h_pi, h_u) + 1): + companion_power = companion_power @ companion + if horizon <= h_pi: + inflation_loading += selectors[2] @ companion_power + if horizon <= h_u: + unemployment_loading += selectors[1] @ companion_power + inflation_loading /= h_pi + unemployment_loading /= h_u + loadings = np.vstack( + (inflation_loading, unemployment_loading, selectors[0]) + ) + regressor_covariance = loadings @ stationary_covariance @ loadings.T + cross_covariance = ( + loadings @ stationary_covariance @ companion.T @ selectors[0] + ) + return np.linalg.solve(regressor_covariance, cross_covariance) + + +policy_coefficients = np.array( + [ + policy_rule_coefficients(θ_mean[:, t], r_mean[t]) + for t in range(len(data['dates'])) + ] +) +inflation_response = policy_coefficients[:, 0] +interest_persistence = policy_coefficients[:, 2] +policy_margin = np.where( + np.abs(interest_persistence) < 1, + inflation_response + interest_persistence - 1, + np.nan, +) +``` + +对于 $|\beta_3|<1$,政策边际 +$\mathcal{M}_t=\beta_{1t}+\beta_{3t}-1$ 恰好在 +$\mathcal A_t\geq1$ 时为非负数,并且避免了除以 $1-\beta_3$。 + +由于 $\beta_3$ 乘以滞后利率,长期反应求和为 +$\beta_1(1+\beta_3+\beta_3^2+\cdots)$,这只有在 +$|\beta_3|<1$ 时才存在。 + +图中其余日期留空,因为 $\mathcal A_t$ 在那些日期没有有限的长期解释。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Policy margin $\mathcal{M}_t=\beta_{1t}+\beta_{3t}-1$ + name: fig-csdv-policy-activism +--- +fig, ax = plt.subplots() +ax.plot(data['dates'], policy_margin, lw=2) +ax.axhline(0, color='0.45', lw=1) +ax.set_xlabel('year') +ax.set_ylabel(r'policy margin $\mathcal{M}_t$') +plt.show() +``` + +政策边际在70年代的大部分时间里都低于零,然后在80年代初之后果断转为正值。 + +这一时间点与政策体制对大通胀有所贡献的观点相吻合。 + +空白区间标记了上述规则忽略了政策边际的那些日期。 + +以下的散点图使用了第四季度的观测值。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: $\mathcal{M}_t$ versus $\bar\pi_t$ and $g_{\pi\pi}(0,t)$ + name: fig-csdv-activism-correlations +--- +displayed_annual = annual[np.isfinite(policy_margin[annual])] + +fig, axes = plt.subplots(1, 2, figsize=(9, 4)) +pairs = ( + (100 * core_inflation, 'core inflation (%)'), + (inflation_persistence, 'normalized spectrum at zero'), +) +for ax, (feature, label) in zip(axes, pairs): + ax.scatter( + policy_margin[displayed_annual], + feature[displayed_annual], + s=18, + ) + ax.axvline(0, color='0.45', lw=1) + ax.set_xlabel(r'policy margin $\mathcal{M}_t$') + ax.set_ylabel(label) +plt.tight_layout() +plt.show() +``` + +核心通货膨胀和持续性数值较高的观测点,聚集在零边际附近或以下,而正的政策边际则聚集在这两个度量都取较低值的区域。 + +所展示的第四季度观测数据表明了一种历史上的关联,而非一种因果性的政策效应。 + +在某些日期,政策规则系数的识别较弱,因此基于后验均值输入的路径会低估不确定性。 + +因此,我们从1975年、1985年和1995年的每一个保留抽样中计算积极程度。 + +```{code-cell} ipython3 +selected_years = (1975, 1985, 1995) +selected_dates = [np.flatnonzero(years == year)[-1] for year in selected_years] + +activism_draws = { + year: np.empty(posterior['SD'].shape[2]) for year in selected_years +} +stable_response_by_year = { + year: np.empty(posterior['SD'].shape[2], dtype=bool) + for year in selected_years +} +for draw in range(posterior['SD'].shape[2]): + for year, date in zip(selected_years, selected_dates): + covariance = innovation_covariance( + posterior['HD'][date + 1, :, draw], + posterior['CD'][:, draw], + ) + rule = policy_rule_coefficients( + posterior['SD'][:, date, draw], covariance + ) + activism_draws[year][draw] = rule[0] / (1 - rule[2]) + stable_response_by_year[year][draw] = np.abs(rule[2]) < 1 +``` + +这些抽样给出了每个日期政策为积极的后验概率,以及在 $|\beta_3|<1$ 的条件下1975年之后积极程度上升的后验概率。 + +```{code-cell} ipython3 +activism_events = ( + activism_draws[1975] > 1, + activism_draws[1985] > 1, + activism_draws[1995] > 1, + activism_draws[1985] > activism_draws[1975], + activism_draws[1995] > activism_draws[1975], +) +activism_conditions = ( + stable_response_by_year[1975], + stable_response_by_year[1985], + stable_response_by_year[1995], + stable_response_by_year[1985] & stable_response_by_year[1975], + stable_response_by_year[1995] & stable_response_by_year[1975], +) +assert all(condition.any() for condition in activism_conditions) +activism_probability_values = np.array( + [ + event[condition].mean() + for event, condition in zip(activism_events, activism_conditions) + ] +) + +activism_probability_index = ( + 'P(A_1975 > 1)', + 'P(A_1985 > 1)', + 'P(A_1995 > 1)', + 'P(A_1985 > A_1975)', + 'P(A_1995 > A_1975)', +) +activism_probabilities = pd.DataFrame( + {'conditional estimate': activism_probability_values}, + index=activism_probability_index, +) +stable_response_shares = pd.Series( + {year: draws.mean() for year, draws in stable_response_by_year.items()}, + name='share with |beta_3| < 1', +) + +display(activism_probabilities.round(3)) +stable_response_shares.to_frame().round(3) +``` + +前三个概率以该日期的 $|\beta_3|<1$ 为条件,而比较则要求两个日期都满足这一条件。 + +中心抽样分布展示了这些概率估计背后的重叠情况和偏斜程度。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Central posterior draws of $\mathcal A_t$ conditional on $|\beta_3|<1$ in 1975, 1985, and 1995 + name: fig-csdv-activism-distributions +--- +stable_activism_draws = { + year: activism_draws[year][stable_response_by_year[year]] + for year in selected_years +} +pooled_activism = np.concatenate(tuple(stable_activism_draws.values())) +activism_limits = np.quantile(pooled_activism, (0.05, 0.95)) +activism_bins = np.linspace(*activism_limits, 31) + +fig, ax = plt.subplots() +for year in selected_years: + central_draws = stable_activism_draws[year] + central_draws = central_draws[ + (central_draws >= activism_limits[0]) + & (central_draws <= activism_limits[1]) + ] + ax.hist( + central_draws, + bins=activism_bins, + histtype='step', + lw=2, + label=str(year), + ) +ax.axvline(1, color='0.45', lw=1) +ax.set_xlabel('activism coefficient') +ax.set_ylabel('retained draws') +ax.legend() +plt.show() +``` + +1975年的分布集中在一附近或以下,而1985年和1995年的分布则大幅右移,但仍然较为分散、有所偏斜且相互重叠。 + +因此后验支持1975年之后从消极政策转为积极政策这一变化,但并不能明确区分1985年与1995年。 + +图中只绘制了满足 $|\beta_3|<1$ 且位于合并样本第5和第95百分位数之间的抽样,而概率计算则使用了所有满足该条件的抽样。 + +(csdv-updated-evidence)= +## 又一个四分之一世纪的证据 + +样本止于2000年第四季度,因此它没有涵盖金融危机、零利率时期、新冠疫情,以及2021至2022年的通货膨胀飙升。 + +问题在于,这些事件是否会改变此前关于漂移、波动率、通货膨胀持续性和系统性政策的证据。 + +### 新增的观测数据 + +为了考察这些事件,我们在2000年第四季度之后附加了最新数据,同时保持2000年第四季度之前的样本不变。 + +这种拼接方式可以防止将对2001年之前的CPI和失业率数据所做的修订,误认为是新增的四分之一世纪所带来的信息。 + +我们从 FRED 下载经季节调整的[CPI][fred-cpi]、经季节调整的[失业率][fred-unemployment],以及[三个月期国库券利率][fred-interest]。 + +[fred-cpi]: https://fred.stlouisfed.org/series/CPIAUCSL +[fred-unemployment]: https://fred.stlouisfed.org/series/UNRATE +[fred-interest]: https://fred.stlouisfed.org/series/TB3MS + +变换方式和季度内的取样时点保持不变:CPI取自第三个月,失业率是三个月的平均值,利率取自第一个月。 + +```{code-cell} ipython3 +fred_url = ( + 'https://fred.stlouisfed.org/graph/fredgraph.csv?' + 'id=CPIAUCSL%2CUNRATE%2CTB3MS' +) +fred_monthly = pd.read_csv( + fred_url, + parse_dates=['observation_date'], +).set_index('observation_date') + +``` + +[美国劳工统计局的说明](https://www.bls.gov/web/empsit/cpsee_e12.pdf)指出,由于联邦政府停摆,2025年10月的失业率观测数据未能采集,导致2025年第四季度没有完整的三个月平均值。 + +因此下面的代码将更新后的样本截止到三个月失业率读数都齐全的最后一个季度,该季度是自动检测出来的,而非硬编码;在撰写本文时,这一季度是2025年第三季度。 + +```{code-cell} ipython3 +def fred_quarterly_table(unemployment_monthly): + """Construct transformed quarterly observations from current FRED data.""" + interest = fred_monthly.loc[ + fred_monthly.index.month.isin((1, 4, 7, 10)), 'TB3MS' + ].copy() + interest.index = interest.index.to_period('Q').start_time + + cpi = fred_monthly.loc[ + fred_monthly.index.month.isin((3, 6, 9, 12)), 'CPIAUCSL' + ].copy() + cpi.index = cpi.index.to_period('Q').start_time + + unemployment = unemployment_monthly.resample('QS').mean() + quarterly = pd.concat( + { + 'interest': interest, + 'unemployment': unemployment, + 'cpi': cpi, + }, + axis=1, + ) + quarterly['y3'] = np.log1p(quarterly['interest'] / 400) + quarterly['ur'] = quarterly['unemployment'] / 100 + quarterly['dp'] = np.log(quarterly['cpi']).diff() + quarterly['date'] = ( + quarterly.index.year + (quarterly.index.quarter - 1) / 4 + ) + columns = ['date', 'y3', 'ur', 'dp'] + return quarterly.loc[:, columns].dropna() + + +unemployment_monthly = fred_monthly['UNRATE'] +unemployment_counts = unemployment_monthly.resample('QS').count() +latest_quarterly = fred_quarterly_table(unemployment_monthly) + +# Extend the archived sample dynamically: append post-2000Q4 quarters only up +# to the first one missing any of its three monthly unemployment readings, so +# no endpoint is hard-coded. An isolated missing month -- for example October +# 2025, which the federal shutdown left uncollected -- caps the sample at the +# preceding complete quarter, and a normally incomplete current quarter caps it +# at the last finished one. +quarterly_unfilled = latest_quarterly.loc['2001-01-01':] +month_counts = unemployment_counts.reindex(quarterly_unfilled.index) +incomplete_quarters = month_counts.index[month_counts < 3] +if len(incomplete_quarters): + first_incomplete_quarter = incomplete_quarters[0] + complete_extension = quarterly_unfilled.loc[ + quarterly_unfilled.index < first_incomplete_quarter + ] +else: + complete_extension = quarterly_unfilled + +cs_sample = pd.read_csv(data_path) +overlap_date = pd.Timestamp('2000-10-01') +cs_sample_overlap = cs_sample.iloc[-1] +latest_overlap = latest_quarterly.loc[overlap_date] + + +def scaled_observation(row): + """Return observable units for a transformed quarterly row.""" + return pd.Series( + { + 'interest rate (annual %)': 400 * np.expm1(row['y3']), + 'unemployment (%)': 100 * row['ur'], + 'inflation (annual %)': 400 * row['dp'], + } + ) + + +cs_sample_scaled = scaled_observation(cs_sample_overlap) +latest_scaled = scaled_observation(latest_overlap) +splice_audit = pd.DataFrame( + { + 'Cogley-Sargent (2005) 2000Q4': cs_sample_scaled, + 'latest revised 2000Q4 data': latest_scaled, + 'current minus Cogley-Sargent (2005)': ( + latest_scaled - cs_sample_scaled + ), + 'first appended 2001Q1': scaled_observation( + complete_extension.iloc[0] + ), + } +) +extended_observations = pd.concat( + (cs_sample, complete_extension.reset_index(drop=True)), + ignore_index=True, +) + + +def quarter_label(timestamp): + """Format a timestamp as year and quarter.""" + return str(timestamp.to_period('Q')) + + +display(splice_audit.round(3)) +``` + +任何缺失值都没有被填补,也没有被当作已观测数据处理。 + +重叠区间表展示了将存档数据与新下载数据拼接时所产生的任何断点。 + +新附加的2001年第一季度通货膨胀率对2000年第四季度和2001年第一季度都使用了最新修订后的CPI水平,因此不会有任何一次对数差分是将两个不同数据发布版本的观测值结合起来计算的。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Observed $\pi_t$, $u_t$, and $i_t$, 1959Q1--2025Q3 + name: fig-csdv-updated-data +--- +fig, axes = plt.subplots(3, 1, figsize=(9, 7), sharex=True) +extended_plot = extended_observations[ + extended_observations['date'] >= 1959 +] +updated_sample_end = complete_extension['date'].iloc[-1] +axes[0].plot( + extended_plot['date'], + 400 * extended_plot['dp'], + lw=2, +) +axes[0].set_ylabel('inflation (annual %)') +axes[1].plot( + extended_plot['date'], + 100 * extended_plot['ur'], + lw=2, +) +axes[1].set_ylabel('unemployment (%)') +axes[2].plot( + extended_plot['date'], + 400 * np.expm1(extended_plot['y3']), + lw=2, +) +axes[2].set_ylabel('interest (annual %)') +axes[2].set_xlabel('year') +for index, ax in enumerate(axes): + cs_sample_label = 'Cogley-Sargent (2005)' if index == 0 else None + sample_end_label = 'updated sample end' if index == 0 else None + ax.axvline( + 2000.75, + color='0.65', + ls='--', + lw=1, + label=cs_sample_label, + ) + ax.axvline( + updated_sample_end, + color='0.45', + ls=':', + lw=1, + label=sample_end_label, + ) +axes[0].legend() +plt.tight_layout() +plt.show() +``` + +```{code-cell} ipython3 +endpoint_observation = complete_extension.iloc[-1] +pd.Series( + { + 'annualized quarterly inflation (%)': ( + 400 * endpoint_observation['dp'] + ), + 'unemployment (%)': 100 * endpoint_observation['ur'], + 'three-month interest rate (%)': ( + 400 * np.expm1(endpoint_observation['y3']) + ), + }, + name=quarter_label(complete_extension.index[-1]), +).to_frame().round(3) +``` + +这次扩展加入了金融危机时期的收缩、疫情期间飙升至13.0%的季度失业率,以及2021—2022年一次短暂的通货膨胀飙升,同时还有两段较长时间的接近零利率时期。 + +由于通货膨胀是由季度变化年化得到的,孤立的波动在这张图中会显得格外醒目,但最近这次飙升在时间跨度上明显比持续了很长时间的70年代通胀上升要短得多。 + +这些观测数据对模型是否会将近期的极端情况归因于冲击波动率还是持续性动态,构成了一次严格的检验,而2008年之后接近于零的利率也削弱了短期利率对政策的度量能力。 + +我们使用上文所述的国库券度量指标,将稳定的 TVP-VAR 模型拟合至2025年第三季度(最后一个完整的季度)。 + +```{code-cell} ipython3 +def append_extension(extension): + """Append a transformed FRED extension to the Cogley-Sargent sample.""" + extension = extension.reset_index(drop=True) + table = pd.concat((cs_sample, extension), ignore_index=True) + assert table['date'].is_unique + assert np.allclose(np.diff(table['date']), 0.25) + return table + + +def fit_updated_model(table): + """Calibrate and fit the stable drifting VAR to one table.""" + model_data = prepare_data(table) + model_prior = calibrate_prior(model_data) + result = run_sampler( + model_data['y'], + model_data['x'], + model_prior, + n_sweeps=5_000, + burn=2_500, + thin=5, + seed=42, + warmup=500, + stable=True, + progress_every=500, + ) + validate_posterior_arrays(result, len(model_data['dates'])) + trace = np.trace(result['QD'], axis1=0, axis2=1) + return { + 'data': model_data, + 'prior': model_prior, + 'posterior': result, + 'trace': trace, + } + + +updated_fit = fit_updated_model(append_extension(complete_extension)) + +latest_data_table = latest_quarterly.loc[ + (latest_quarterly.index >= pd.Timestamp('1948-04-01')) + & (latest_quarterly.index <= complete_extension.index[-1]) +].reset_index(drop=True) +assert np.allclose(np.diff(latest_data_table['date']), 0.25) +latest_data_fit = fit_updated_model(latest_data_table) +``` + +### 系数漂移是否持续? + +```{code-cell} ipython3 +def updated_drift_summary(fit): + """Summarize the updated coefficient-drift distribution.""" + trace = fit['trace'] + q_mean = fit['posterior']['QD'].mean(axis=2) + eigenvalues = np.linalg.eigvalsh(q_mean)[::-1] + return { + 'posterior mean tr(Q)': trace.mean(), + 'share in first three eigen-directions': ( + eigenvalues[:3].sum() / eigenvalues.sum() + ), + } + + +updated_label = quarter_label(complete_extension.index[-1]) +updated_summary = pd.DataFrame( + { + 'Cogley-Sargent (2005) + extension': ( + updated_drift_summary(updated_fit) + ), + 'latest revised data for full sample': updated_drift_summary( + latest_data_fit + ), + } +) +updated_summary.round(3) +``` + +漂移速率分布和系数路径提供了与 {cite:t}`CogleySargent2005` 样本相同的视角。 + +更新后的时间序列图中的竖直虚线标记了 {cite:t}`CogleySargent2005` 样本2000年第四季度的终点,但每一条更新后的路径都来自一次完整的重新估计,而不是把新的点附加到未发生变化的历史估计之上。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Posterior $\operatorname{tr}(Q)$ and prior $\operatorname{tr}(\bar Q)$ through 2025Q3 + name: fig-csdv-updated-drift-rate +--- +fig, ax = plt.subplots() +ax.hist(updated_fit['trace'], bins=30, histtype='step', lw=2) +ax.axvline( + np.trace(updated_fit['prior']['q_center']), + color='C1', + lw=2, + label=r'prior $\mathrm{tr}(\bar Q)$', +) +ax.set_xlabel(r'$\mathrm{tr}(Q)$') +ax.set_ylabel('frequency') +ax.legend() +plt.show() +``` + +在两种数据构造方式下,全样本的后验漂移速率都仍然高于其保守的先验校准值。 + +在 TVP-VAR 模型内部,这表明存在不可忽略的全样本漂移,但这并不是对 $Q=0$ 与 $Q>0$ 的一次正式比较。 + +其大小取决于历史观测值是来自存档数据集,还是来自最新的修订数据。 + +由于 $Q$ 是针对整个1959—2025年路径的单一方差参数,这一直方图本身并不能表明漂移在2000年之后加速了。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Posterior mean VAR coefficients $E(\theta_t\mid T)$ through 2025Q3 + name: fig-csdv-updated-coefficient-paths +--- +fig, axes = plt.subplots(1, 3, figsize=(10, 4), sharex=True) +updated_dates = updated_fit['data']['dates'] +updated_coefficients = updated_fit['posterior']['SD'].mean(axis=2) +coefficient_lines = plot_equation_coefficients( + axes, + updated_dates, + updated_coefficients, +) +for ax in axes: + ax.axvline(2000.75, color='0.65', ls='--', lw=1) +fig.legend( + coefficient_lines, + coefficient_labels, + loc='lower center', + ncol=4, +) +plt.tight_layout(rect=(0, 0.17, 1, 1)) +plt.show() +``` + +若干系数路径在2000年之后仍然在缓慢地移动,其中最大的变化再次集中在通货膨胀方程中,而不是表现为突然的金融危机或疫情式的断点。 + +某些成对滞后系数彼此相反的变动,也说明了为何它们的综合动态含义比任何单条曲线都更具信息量。 + +前三个特征方向占据了后验均值漂移方差的大多数,因此所估计的变动仍然是低维的。 + +如今稳定性限制作用于一条更长的路径,这使得后验漂移速率成为整个1959—2025年样本的一个特性。 + +### 大缓和之后的波动率 + +接下来我们要把创新的大小和相关性变化,与 VAR 动态的变化区分开来。 + +```{code-cell} ipython3 +def model_features(fit): + """Compute features at posterior mean parameters.""" + result = fit['posterior'] + θ = result['SD'].mean(axis=2) + mean_root_modulus = np.max( + np.abs(companion_roots(θ)), axis=1 + ) + if not np.all(mean_root_modulus < 1): + raise ValueError('mean coefficient path is unstable') + covariance = mean_innovation_covariance(result['HD'], result['CD']) + core, natural = local_means(θ) + persistence = np.array([ + inflation_spectrum( + θ[:, t], covariance[t], zero_frequency + )[1][0] + for t in range(len(fit['data']['dates'])) + ]) + sign, logdet = np.linalg.slogdet(covariance) + assert np.all(sign > 0) + policy_coefficients = np.array( + [ + policy_rule_coefficients(θ[:, t], covariance[t]) + for t in range(len(fit['data']['dates'])) + ] + ) + inflation_response = policy_coefficients[:, 0] + interest_persistence = policy_coefficients[:, 2] + policy_margin = np.where( + np.abs(interest_persistence) < 1, + inflation_response + interest_persistence - 1, + np.nan, + ) + return { + 'θ': θ, + 'maximum_companion_root': mean_root_modulus.max(), + 'covariance': covariance, + 'core': core, + 'natural': natural, + 'persistence': persistence, + 'logdet': logdet, + 'policy_margin': policy_margin, + } + + +updated_features = model_features(updated_fit) +latest_data_features = model_features(latest_data_fit) + +pd.Series( + { + 'Cogley-Sargent (2005) + extension': ( + updated_features['maximum_companion_root'] + ), + 'latest revised data for full sample': ( + latest_data_features['maximum_companion_root'] + ), + }, + name='maximum companion-root modulus of mean path', +).to_frame().round(4) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Standard deviations and correlations implied by $E(R_t\mid T)$ through 2025Q3 + name: fig-csdv-updated-volatility-correlation +--- +fig, axes = plt.subplots(3, 2, figsize=(9, 8), sharex=True) +dates = updated_fit['data']['dates'] +covariance = updated_features['covariance'] +for row, (index, _) in enumerate(variances): + axes[row, 0].plot( + dates, + 10000 * np.sqrt(covariance[:, index, index]), + lw=2, + ) +for row, (left, right, _) in enumerate(correlations): + scale = np.sqrt( + covariance[:, left, left] * covariance[:, right, right] + ) + axes[row, 1].plot( + dates, + covariance[:, left, right] / scale, + lw=2, + ) +for row, (_, label) in enumerate(variances): + axes[row, 0].set_title(label) +for row, (_, _, label) in enumerate(correlations): + axes[row, 1].set_title(label) +for ax in axes.flat: + ax.axvline(2000.75, color='0.65', ls='--', lw=1) +axes[1, 0].set_ylabel( + r'innovation standard deviation $\times 10^4$' +) +axes[1, 1].set_ylabel('correlation') +axes[-1, 0].set_xlabel('year') +axes[-1, 1].set_xlabel('year') +plt.tight_layout() +plt.show() +``` + +沃尔克转型时期在利率创新波动率中依然占据主导地位,金融危机导致了最大的通货膨胀波动率峰值,而疫情则在失业创新波动率上独占鳌头。 + +疫情还导致通货膨胀与失业率之间的相关系数急剧下降,因此近期事件既改变了简化形式冲击的构成,也改变了它们的大小。 + +这是关于运气不好这一成分的直接证据,尽管简化形式的创新并不能证明这些潜在扰动在结构上是外生的。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: $\log |E(R_t\mid T)|$ through 2025Q3 + name: fig-csdv-updated-total-variance +--- +fig, ax = plt.subplots() +ax.plot( + updated_fit['data']['dates'], + updated_features['logdet'], + lw=2, +) +ax.axvline(2000.75, color='0.65', ls='--', lw=1) +ax.set_xlabel('year') +ax.set_ylabel(r'$\log |E(R_t\mid T)|$') +plt.show() +``` + +联合创新方差在金融危机期间上升,在2010年代达到大缓和时期的一个深谷,然后在2020年跃升至甚至超过1981年峰值的水平,随后又迅速下降。 + +```{code-cell} ipython3 +def decimal_quarter_label(value): + """Format a decimal quarterly date.""" + year = int(np.floor(value + 1e-8)) + quarter = int(round(4 * (value - year))) + 1 + return f'{year}Q{quarter}' + + +def volatility_summary(fit, features): + """Summarize innovation-volatility peaks and endpoints.""" + dates = fit['data']['dates'] + standard_deviation = 10000 * np.sqrt( + np.diagonal(features['covariance'], axis1=1, axis2=2) + ) + names = ('interest', 'unemployment', 'inflation') + return pd.DataFrame( + { + 'peak quarter': [ + decimal_quarter_label( + dates[np.argmax(standard_deviation[:, index])] + ) + for index in range(n_variables) + ], + }, + index=names, + ) + + +updated_volatility = volatility_summary(updated_fit, updated_features) +updated_volatility +``` + +在2025年第三季度这一终点,三种创新标准差都远低于各自的峰值,这在该模型内部支持了疫情冲击是一个大而短暂的事件这一解释。 + +### 2000年之后的核心通货膨胀与自然失业率 + +同样的局部均值计算能够区分暂时性的通货膨胀与模型长期预测的转变。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Local means $\bar\pi_t$ and $\bar u_t$ through 2025Q3 + name: fig-csdv-updated-local-means +--- +updated_dates = updated_fit['data']['dates'] +updated_annual = annual_indices(updated_dates) +fig, ax = plt.subplots() +ax.plot( + updated_dates[updated_annual], + 100 * updated_features['core'][updated_annual], + 'o-', + lw=2, + markersize=3, + label='core inflation', +) +ax.plot( + updated_dates[updated_annual], + 100 * updated_features['natural'][updated_annual], + '+-', + lw=2, + markersize=5, + label='natural rate', +) +ax.axvline(2000.75, color='0.65', ls='--', lw=1) +ax.set_xlabel('year') +ax.set_ylabel('percent') +ax.legend() +plt.show() +``` + +这里70年代核心通货膨胀的峰值低于 {cite:t}`CogleySargent2005` 图中所显示的水平,因为后来的观测数据修正了平滑后的历史值,所以竖直虚线两侧的数值都属于同一次更新后的拟合结果。 + +2000年之后,核心通货膨胀率大多维持在约2%到3%之间,即使2020年之后观测到的通货膨胀率大幅上升,核心通货膨胀率也只是温和上升。 + +自然失业率曲线是模型局部隐含的长期失业率锚点,这正是为何2020年季度失业率能跳升至13.0%,而这条曲线却依然保持在接近5%的水平的原因。 + +月度峰值为14.8%。 + +由于样本在第四季度之前结束,最后一个年度点代表的是2025年第三季度。 + +```{code-cell} ipython3 +def endpoint_features(features): + """Return economically scaled endpoint features.""" + return pd.Series( + { + 'core inflation (%)': 100 * features['core'][-1], + 'natural rate (%)': 100 * features['natural'][-1], + 'normalized persistence': features['persistence'][-1], + 'log generalized innovation variance': features['logdet'][-1], + } + ) + + +updated_endpoints = endpoint_features(updated_features).to_frame( + name=updated_label +).T +latest_data_endpoints = endpoint_features( + latest_data_features +).to_frame(name=updated_label).T +data_revision_sensitivity = pd.concat( + { + 'Cogley-Sargent (2005) + extension': updated_endpoints, + 'latest revised data for full sample': latest_data_endpoints, + } +) +data_revision_sensitivity.round(3) +``` + +终点处的核心通货膨胀、自然失业率和持续性总结在这两种数据构造方式下都相似。 + +按抽样计算的年度路径展示了不确定性在更新后的拟合结果内部是如何演变的。 + +```{code-cell} ipython3 +updated_feature_draws = posterior_feature_draws( + updated_fit['posterior'], + updated_annual, +) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Posterior medians and pointwise 90 percent intervals for $\bar\pi_t$, $\bar u_t$, and $g_{\pi\pi}(0,t)$ through 2025Q3 + name: fig-csdv-updated-feature-uncertainty +--- +fig, axes = plt.subplots(3, 1, figsize=(9, 8), sharex=True) +for ax, (key, ylabel) in zip(axes, feature_specs): + lower, median, upper = np.quantile( + updated_feature_draws[key], + (0.05, 0.5, 0.95), + axis=1, + ) + line, = ax.plot(updated_dates[updated_annual], median, lw=2) + ax.fill_between( + updated_dates[updated_annual], + lower, + upper, + color=line.get_color(), + alpha=0.2, + ) + ax.axvline(2000.75, color='0.65', ls='--', lw=1) + ax.set_ylabel(ylabel) +axes[-1].set_xlabel('year') +plt.tight_layout() +plt.show() +``` + +实线是后验中位数,阴影区域是逐点的90%区间,而非针对整条路径的联合区间。 + +2000年之后,核心通货膨胀中位数相对平坦,持续性中位数也保持在较低水平,而自然失业率区间较宽,并在终点处再次变宽。 + +终点处的行总结了这三个非线性特征的不确定性。 + +```{code-cell} ipython3 +def endpoint_feature_intervals(draws): + """Summarize draw-wise uncertainty in endpoint model features.""" + labels = { + 'core': 'core inflation (%)', + 'natural': 'natural rate (%)', + 'persistence': 'normalized persistence', + } + rows = {} + for key, label in labels.items(): + values = draws[key][-1] + rows[label] = { + 'median': np.median(values), + '5th percentile': np.quantile(values, 0.05), + '95th percentile': np.quantile(values, 0.95), + } + return pd.DataFrame.from_dict(rows, orient='index') + + +updated_endpoint_intervals = endpoint_feature_intervals( + updated_feature_draws +) +updated_endpoint_intervals.round(3) +``` + +正如上表所示,在2025年第三季度,核心通货膨胀和自然失业率的中位数都仍处于历史上较为温和的水平。 + +它们的区间依然较宽,归一化持续性也仍保留着相当大的上尾,因此将近期的通货膨胀归类为暂时性现象这一结论并非确定无疑。 + +### 通货膨胀是否再次变得持久? + +这里的持续性指的是通货膨胀创新向未来通货膨胀的传播程度,而不是观测到的通货膨胀保持高位的季度数量。 + +归一化谱降低了对冲击规模共同变化的敏感度,尽管它仍然依赖于 $R_t$ 中的相对方差和协方差。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: $g_{\pi\pi}(0,t)$ through 2025Q3 + name: fig-csdv-updated-persistence +--- +fig, ax = plt.subplots() +ax.plot( + updated_dates[updated_annual], + updated_features['persistence'][updated_annual], + 'o-', + lw=2, + markersize=3, +) +ax.axvline(2000.75, color='0.65', ls='--', lw=1) +ax.set_xlabel('year') +ax.set_ylabel(r'$g_{\pi\pi}(0,t)$') +plt.show() +``` + +估计出的 $g_{\pi\pi}(0,t)$ 路径重现了上升到1980年峰值再随后崩溃的走势,但2000年之后它一直停留在约0.2到0.5之间,且在2020年之后只是略有上升。 + +一连串较大的简化形式创新可以使观测到的通货膨胀在数个季度内保持高位,而不必产生70年代所估计出的那种强烈传播效应。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: $\bar\pi_t$ and $g_{\pi\pi}(0,t)$ through 2025Q3 + name: fig-csdv-updated-core-persistence +--- +fig, axes = plt.subplots( + 2, + 1, + figsize=(9, 6), + sharex=True, +) +axes[0].plot( + updated_dates[updated_annual], + 100 * updated_features['core'][updated_annual], + 'o-', + lw=2, + markersize=3, +) +axes[1].plot( + updated_dates[updated_annual], + updated_features['persistence'][updated_annual], + 'x-', + lw=2, + markersize=4, +) +for ax in axes: + ax.axvline(2000.75, color='0.65', ls='--', lw=1) +axes[0].set_ylabel('core inflation (%)') +axes[1].set_ylabel('normalized spectrum at zero') +axes[1].set_xlabel('year') +plt.tight_layout() +plt.show() +``` + +核心通货膨胀从2010年代中期的低点恢复至接近其早前水平,而持续性则仍停留在1980年后的低位区间,并未随之上升。 + +这种分歧将模型长期通货膨胀率的温和上升,与向70年代式传播模式的回归区分开来。 + +完整的谱图展示了这种差异的来源。 + +```{code-cell} ipython3 +updated_raw_spectrum, updated_normalized_spectrum = ( + inflation_spectrum_surface( + updated_features['θ'], + updated_features['covariance'], + spectrum_frequencies, + ) +) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: $f_{\pi\pi}(\omega,t)$ and $g_{\pi\pi}(\omega,t)$ through 2025Q3 + name: fig-csdv-updated-spectra +--- +fig, axes = plt.subplots( + 1, + 2, + figsize=(9, 4), + sharey=True, + constrained_layout=True, +) +updated_surfaces = ( + (updated_raw_spectrum, 'raw spectrum', 'log10 power'), + ( + updated_normalized_spectrum, + 'normalized spectrum', + 'log10 normalized power', + ), +) +for ax, (surface, title, color_label) in zip(axes, updated_surfaces): + image = ax.pcolormesh( + updated_dates, + spectrum_frequencies, + np.log10(surface), + shading='auto', + ) + ax.axvline(2000.75, color='0.85', ls='--', lw=1) + ax.set_xlabel('year') + ax.set_ylabel(f'{title}\ncycles per quarter') + fig.colorbar(image, ax=ax, label=color_label) +plt.show() +``` + +金融危机和疫情在 $f_{\pi\pi}(\omega,t)$ 中表现为明亮而宽阔的条带,因为简化形式的创新方差增大了。 + +归一化谱 $g_{\pi\pi}(\omega,t)$ 在2000年之后并不存在与70年代相当的低频“脊”。 + +综合来看,这些图不支持出现向70年代式持续性回归的观点,同时也没有使这一归一化统计量脱离对 $R_t$ 的依赖。 + +```{code-cell} ipython3 +def episode_summary(fit, features): + """Average selected features over economically distinct episodes.""" + years = np.floor(fit['data']['dates'] + 1e-8).astype(int) + periods = { + '1970--1979': (years >= 1970) & (years <= 1979), + '1985--2000': (years >= 1985) & (years <= 2000), + '2001--2019': (years >= 2001) & (years <= 2019), + '2020--2022': (years >= 2020) & (years <= 2022), + '2023--2025Q3': years >= 2023, + } + rows = {} + for label, mask in periods.items(): + rows[label] = { + 'core inflation (%)': 100 * features['core'][mask].mean(), + 'normalized persistence': features['persistence'][mask].mean(), + 'log generalized innovation variance': ( + features['logdet'][mask].mean() + ), + } + return pd.DataFrame.from_dict(rows, orient='index') + + +updated_episodes = episode_summary(updated_fit, updated_features) +updated_episodes.round(3) +``` + +各阶段的平均值对比了2020—2022年的高波动率与2000年之后各十年间较低的归一化持续性。 + +### 近期的政策积极程度能否被度量? + +当 $|\beta_3|<1$ 时,政策边际给出了与2000年之后相同的积极政策分类,而无需除以 $1-\beta_3$。 + +在以下图中,灰色线标记了积极政策的阈值 $\mathcal{M}_t=0$。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Policy margin $\mathcal{M}_t$ through 2025Q3 + name: fig-csdv-updated-activism +--- +fig, ax = plt.subplots() +updated_policy_margin = updated_features['policy_margin'] +ax.plot(updated_dates, updated_policy_margin, lw=2) +ax.axhline(0, color='0.45', lw=1) +ax.axvline(2000.75, color='0.65', ls='--', lw=1) +ax.set_xlabel('year') +ax.set_ylabel(r'policy margin $\mathcal{M}_t$') +plt.show() +``` + +在所展示的2000年之后的日期中,政策边际大多为正,并在2010年代中期以及2020年前后移向零。 + +空白区间省略了拟合出的利率反应无法稳定收敛的那些日期。 + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Post-2000 $\mathcal{M}_t$ versus $\bar\pi_t$ and $g_{\pi\pi}(0,t)$ + name: fig-csdv-updated-activism-correlations +--- +fig, axes = plt.subplots(1, 2, figsize=(9, 4)) +recent_annual = annual_indices(updated_dates, start=2001) +displayed_recent = recent_annual[ + np.isfinite(updated_policy_margin[recent_annual]) +] +axes[0].scatter( + updated_policy_margin[displayed_recent], + 100 * updated_features['core'][displayed_recent], + s=18, +) +axes[1].scatter( + updated_policy_margin[displayed_recent], + updated_features['persistence'][displayed_recent], + s=18, +) +for ax in axes: + ax.axvline(0, color='0.45', lw=1) + ax.set_xlabel(r'policy margin $\mathcal{M}_t$') +axes[0].set_ylabel('core inflation (%)') +axes[1].set_ylabel('normalized spectrum at zero') +plt.tight_layout() +plt.show() +``` + +其余2000年之后的观测数据并不能在政策边际、核心通货膨胀和持续性之间确立一种稳定的因果关系。 + +我们还考察了2025年第三季度终点处的中心抽样分布。 + +```{code-cell} ipython3 +def endpoint_policy_margin_draws(fit): + """Return endpoint margins and stability indicators.""" + result = fit['posterior'] + margins = np.empty(result['SD'].shape[2]) + stable_response = np.empty(result['SD'].shape[2], dtype=bool) + for draw in range(len(margins)): + covariance = innovation_covariance( + result['HD'][-1, :, draw], + result['CD'][:, draw], + ) + rule = policy_rule_coefficients( + result['SD'][:, -1, draw], covariance + ) + margins[draw] = rule[0] + rule[2] - 1 + stable_response[draw] = np.abs(rule[2]) < 1 + return margins, stable_response + + +updated_margin_draws, stable_response_draws = ( + endpoint_policy_margin_draws(updated_fit) +) +assert np.any(stable_response_draws) +stable_margin_draws = updated_margin_draws[stable_response_draws] +updated_margin_summary = pd.Series( + { + 'median M': np.median(stable_margin_draws), + '5th percentile of M': np.quantile(stable_margin_draws, 0.05), + '95th percentile of M': np.quantile(stable_margin_draws, 0.95), + 'P(M >= 0 | |beta_3| < 1)': np.mean(stable_margin_draws >= 0), + 'share with |beta_3| < 1': stable_response_draws.mean(), + }, + name=updated_label, +).to_frame().T +updated_margin_summary.round(3) +``` + +```{code-cell} ipython3 +--- +mystnb: + figure: + caption: Central 90 percent of posterior draws for $\mathcal{M}_t$ conditional on $|\beta_3|<1$ at 2025Q3 + name: fig-csdv-updated-activism-distributions +--- +updated_margin_limits = np.quantile( + stable_margin_draws, + (0.05, 0.95), +) +updated_margin_bins = np.linspace(*updated_margin_limits, 31) + +fig, ax = plt.subplots() +central_draws = stable_margin_draws[ + (stable_margin_draws >= updated_margin_limits[0]) + & (stable_margin_draws <= updated_margin_limits[1]) +] +ax.hist( + central_draws, + bins=updated_margin_bins, + histtype='step', + lw=2, +) +ax.axvline(0, color='0.45', lw=1) +ax.set_xlabel(r'policy margin $\mathcal{M}_t$') +ax.set_ylabel('draw count') +plt.show() +``` + +表中报告了具有稳定利率反应的抽样比例,以及在这些抽样中积极政策的概率。 + +若某一区间跨越零点,则表明终点处的分类仍存在不确定性。 + +图中只显示了处于第5和第95百分位数之间的抽样,而零利率下限和非常规政策进一步削弱了2008年之后这一短期利率投影的解释力。 + +### 新增观测数据改变了什么 + +这额外的四分之一世纪增加了一次戏剧性的波动率事件,但没有出现与70年代相当的2000年后低频“脊”。 + +疫情是主导性的总体不确定性事件,但近期的通货膨胀飙升并未重现70年代那种低频持续性“脊”。 + +在更新后的 TVP-VAR 模型内部,全样本漂移速率的后验分布依然高于其保守的先验校准值;要进行固定系数比较,需要一个单独的 $Q=0$ 模型。 + +2025年第三季度的自然失业率和政策边际估计仍不够精确,尤其是因为并非每一次后验抽样都满足 $|\beta_3|<1$。 + +## 政策不当还是运气不好?一个结论 + +贝叶斯 VAR 模型对本讲座开篇提出的问题给出了一个细致入微的答案。 + +- *波动率发生了漂移:* 冲击的大小发生了巨大的变化,出现了沃尔克时期的一次飙升以及随后的大缓和,因此运气不好的说法确实抓住了某些真实的东西。 + +- *已拟合的 TVP-VAR 也将变动归因于系数:* 通货膨胀持续性和核心通货膨胀在整个70年代上升,并在80年代下降,尽管一个正式的固定系数与漂移系数模型的比较需要一个单独的 $Q=0$ 模型。 + +- *新增的观测数据并未推翻这一区分:* 疫情产生了一次极端的波动率事件,而近期的通货膨胀飙升并未重现70年代的持续性。 + +简化形式的 VAR 本身无法证明是美联储信念的变化导致了系数漂移,因为私人部门行为和其他未被纳入模型的机制同样能够改变简化形式的动态。 + +还有一个转折,它把我们带回到本节的理论。 + +{doc}`phillips_learning` 和 +{doc}`phillips_escaping_nash` 中的逃逸路径模型预测,随着一个学习型政府愈发不愿放弃一个高通胀的自我实现均衡,通货膨胀持续性应当在反通胀过程中*上升*。 + +数据却显示出相反的情况,因为1980年之后随着通货膨胀下降,持续性也随之下降。 + +这促成了后来的一些学习模型,包括 {cite:t}`CogleySargentConquest2005` 和 {cite:t}`Primiceri2006`,在这些模型中,决策者在70年代不愿实施反通胀措施、以及他们最终的转变,共同产生了一种先上升后下降的持续性。 + +与西姆斯、扎、伯南克和米霍夫的这场友好辩论,因此所做的远不止裁决一个历史问题。 + +它使贯穿本节的学习与漂移理论模型更为精细——从《征服》一书中的 {doc}`自我实现均衡 `,到用于解读后来通货膨胀的 {doc}`漂移的美联储信念 `。 + +## 练习 + +```{exercise} +:label: csdv_ex1 + +对于一个 $AR(1)$ 过程,归一化的零频率功率为 + +$$ +g(0)=\frac{1+\rho}{2\pi(1-\rho)}. +$$ + +计算 $\rho=0$、$0.85$ 和 $0.97$ 时的 $g(0)$,并使用上文的持续性路径,解释1980年前后通货膨胀动态是如何变化的。 +``` + +```{solution-start} csdv_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +ρ = np.array([0.0, 0.85, 0.97]) +g0 = (1 + ρ) / (2 * np.pi * (1 - ρ)) +pd.Series(g0, index=ρ, name='normalized power at zero').to_frame() +``` + +白噪声的 $g(0)=1/(2\pi)$,而大约在2到10之间的取值,则对应于系数在约 +$0.85$ 到 $0.97$ 之间的高度持续性自回归过程。 + +因此,大通胀期间零频率功率的上升以及1980年之后的下降,代表着持续性发生了巨大变化。 + +```{solution-end} +``` + +```{exercise} +:label: csdv_ex2 + +在本讲座中,我们始终强调,要对漂移系数与恒定系数进行正式的比较,需要用 $Q=0$(即纯粹的“运气不好”的特殊情形,其中 VAR 系数被冻结,只有随机波动率 $H_t$ 变动)重新拟合模型。 + +该抽样器已经支持这一点:向 `run_sampler` 传入 +`fixed_q=np.zeros((n_coefficients, n_coefficients))`,即可将 $Q$ 固定为零,而不是对其进行抽样。 + +将这个恒定系数模型拟合到科格利—萨金特样本,并将其归一化零频率谱 +$g_{\pi\pi}(0,t)$ 与 {numref}`fig-csdv-inflation-persistence` 中的漂移系数路径进行对比。 + +在所度量的持续性中,70年代的上升与1980年后的下降会发生什么变化?这告诉了你什么关于仅靠漂移*波动率*是否能够解释持续性动态的信息? +``` + +```{solution-start} csdv_ex2 +:class: dropdown +``` + +在 $Q=0$ 的情形下,椭圆切片更新所返回的系数路径在整个时间上保持恒定,因此 $A_{t\mid T}$ 不再变动,而 +$g_{\pi\pi}(0,t)$ 中随时间变化的唯一剩余来源,就是漂移中的协方差 $R_t$。 + +```{code-cell} ipython3 +constant_posterior = run_sampler( + data['y'], + data['x'], + prior, + n_sweeps=1_000, + burn=500, + thin=1, + seed=42, + warmup=200, + stable=True, + fixed_q=np.zeros((n_coefficients, n_coefficients)), +) + +constant_θ = constant_posterior['SD'].mean(axis=2) +constant_R = mean_innovation_covariance( + constant_posterior['HD'], constant_posterior['CD'] +) +constant_persistence = np.array([ + inflation_spectrum(constant_θ[:, t], constant_R[t], zero_frequency)[1][0] + for t in range(len(data['dates'])) +]) + +fig, ax = plt.subplots() +ax.plot(data['dates'][annual], inflation_persistence[annual], 'o-', + lw=2, markersize=3, label='drifting coefficients') +ax.plot(data['dates'][annual], constant_persistence[annual], 's-', + lw=2, markersize=3, label=r'constant coefficients ($Q=0$)') +ax.set_xlabel('year') +ax.set_ylabel(r'$g_{\pi\pi}(0,t)$') +ax.legend() +plt.show() +``` + +即使 $A$ 固定不变,持续性度量仍会变动,因为 $R_t$ 的*构成*——即三个正交冲击的相对大小——即便在其总体尺度被归一化去除之后,依然会发生变化。 + +事实上,恒定系数路径同样在1980年前后攀升至一个峰值,因为通货膨胀创新相对于其他创新变得更大,因此单凭运气不好这一渠道,就能够制造出*上升*阶段的大部分现象。 + +它无法重现的是*下降*阶段:1980年之后,恒定系数模型下的持续性在样本剩余时间里一直维持在2到3左右的高位,而漂移系数路径则崩溃回落到一以下。 + +将 $A$ 冻结在其全样本平均值上,会使得通货膨胀在90年代的传播强度几乎与70年代相当。 + +因此,仅靠漂移的波动率能够解释一部分上升过程,但完全不能解释沃尔克时期持续性的反通胀式下降——1980年之后的这次崩溃,正是关于*系统性*动态的证据,这也正是为何要回答政策不当还是运气不好这个问题,需要同时考虑这两个渠道。 + +```{solution-end} +``` \ No newline at end of file From 25a09a71739ffa5735f9120cf5b2cd98b6a34a0f Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:17 +1000 Subject: [PATCH 06/21] Update translation: .translate/state/phillips_drifts_volatilities.md.yml --- .translate/state/phillips_drifts_volatilities.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_drifts_volatilities.md.yml diff --git a/.translate/state/phillips_drifts_volatilities.md.yml b/.translate/state/phillips_drifts_volatilities.md.yml new file mode 100644 index 0000000..e9254c1 --- /dev/null +++ b/.translate/state/phillips_drifts_volatilities.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 10 +tool-version: 0.23.0 From c656a90bd28823ffe6d08ba1b59c8133d283305d Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:18 +1000 Subject: [PATCH 07/21] Update translation: lectures/phillips_escaping_nash.md --- lectures/phillips_escaping_nash.md | 580 +++++++++++++++++++++++++++++ 1 file changed, 580 insertions(+) create mode 100644 lectures/phillips_escaping_nash.md diff --git a/lectures/phillips_escaping_nash.md b/lectures/phillips_escaping_nash.md new file mode 100644 index 0000000..38e1d2a --- /dev/null +++ b/lectures/phillips_escaping_nash.md @@ -0,0 +1,580 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 逃离纳什通胀 + headings: + Overview: 概览 + The model: 模型 + The self-confirming equilibrium: 自我确认均衡 + Adaptation and the mean dynamics: 适应性与均值动态 + Escape dynamics as a control problem: 作为控制问题的逃逸动态 + The dominant escape path: 主导逃逸路径 + The race of four ODEs: 四条常微分方程的竞速 + Mean dynamics reinforce the escape: 均值动态强化逃逸 + The experimentation trap: 试验陷阱 + Escape frequency and model richness: 逃逸频率与模型丰富度 + Escaping volatile inflation: 逃离高波动通货膨胀 + Exercises: 练习 +--- + +(phillips_escaping_nash)= +```{raw} jupyter + +``` + +# 逃离纳什通胀 + +```{contents} Contents +:depth: 2 +``` + +## 概览 + +> 如果一个不太可能发生的事件发生了,它极有可能是以最可能的方式发生的。 +> +> —— 迈克尔·哈里森 + +本讲座是 {doc}`phillips_learning` 的分析性完成篇。 + +它遵循 {cite}`ChoWilliamsSargent2002`(CWS),该文将 {cite}`Sargent1999` 第 8 章中*模拟*出的逃逸动态转化为一种*确定性刻画*。 + +在 {doc}`phillips_learning` 中,我们观察到一个恒定增益的政府反复地逃离纳什自我确认均衡,并在拉姆齐结果附近长时间停留——但我们只是通过模拟对这些逃逸做了非正式的描述。 + +CWS 表明,这些逃逸受它们自身的常微分方程支配,该方程由**大偏差理论**得出。 + +由此出现的图景包含两个确定性部分: + +* **均值动态**:一个把政府信念拉*向*自我确认均衡的常微分方程;以及 +* **逃逸动态**:第二个常微分方程——由一个"最可能的不太可能"的冲击序列驱动——将信念推*离*自我确认均衡,朝支持拉姆齐结果的信念方向移动。 + +一个引人注目的发现是,逃逸存在一条*主导路径*:在发生逃逸的条件下,政府的信念会沿着一条几乎确定的路线演变,沿途它暂时习得了自然率假说的某个版本,并削减了通货膨胀。 + +本讲座是 {doc}`phillips_learning` 的技术延伸;下一讲 {doc}`phillips_priors` 在此基础上,探讨政府关于参数漂移的*先验*如何重塑均值动态与这些逃逸动态。 + +我们使用便于分析处理的**静态**模型。 + +让我们从导入相关模块开始: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +from scipy.integrate import solve_ivp +``` + +## 模型 + +真实经济是 {cite}`KydlandPrescott1977` 的自然率模型, + +```{math} +:label: en_truth + +U_n = u - \theta(\pi_n - \hat x_n) + \sigma_1 W_{1n}, +\qquad +\pi_n = x_n + \sigma_2 W_{2n}, +\qquad +\hat x_n = x_n, +``` + +其中 $\theta, u > 0$,且 $W_n = (W_{1n}, W_{2n})'$ 为独立同分布的标准高斯变量。 + +政府并不知道 {eq}`en_truth`。 + +在静态模型中,它通过将失业率对通货膨胀和一个常数项做回归,拟合一条非预期性菲利普斯曲线, + +```{math} +:label: en_belief + +U_n = \gamma_1 \pi_n + \gamma_{-1} + \eta_n , +``` + +信念为 $\gamma = (\gamma_1, \gamma_{-1})$(斜率与截距),并将 $\eta_n$ 视为外生的。 + +在相信 {eq}`en_belief` 的前提下,政府求解 {doc}`菲尔普斯问题 `,其静态最优反应将通货膨胀设定为常数 + +```{math} +:label: en_bestresp + +x(\gamma) = -\frac{\gamma_{-1}\, \gamma_1}{1 + \gamma_1^2} . +``` + +按照 CWS 的说法,三种信念值得单独命名: + +* **信念 1(纳什):** $\gamma_1 = -\theta$,截距使 $x = \theta u$ —— 这正是 {cite}`KydlandPrescott1977` 的时间一致结果。 +* **信念 2(拉姆齐):** $\gamma_1 = 0$,此时政府认为不存在权衡取舍,设定 $x = 0$。 +* **信念 3(归纳):** 通货膨胀系数之和为零,对于一个有耐心的政府,这同样会使通货膨胀趋于 $0$。 + +```{code-cell} ipython3 +class EscapeModel: + "CWS 2002 static model. γ = (γ₁ slope, γ₋₁ intercept), regressors Φ = (π, 1)." + + def __init__(self, θ=1.0, u=5.0, σ1=0.3, σ2=0.3): + self.θ, self.u, self.σ1, self.σ2 = θ, u, σ1, σ2 + + def x(self, γ): + γ1, γm1 = γ + return -γm1 * γ1 / (1 + γ1**2) + + def M(self, γ): + "E[ΦΦ'] with Φ = (π, 1)." + x = self.x(γ) + return np.array([[x**2 + self.σ2**2, x], [x, 1.0]]) + + def g_bar(self, γ): + "Mean-dynamics forcing E[Φ(U − Φ'γ)] = M(T(γ) − γ)." + x = self.x(γ) + E_ΦU = np.array([x * self.u - self.θ * self.σ2**2, self.u]) + return E_ΦU - self.M(γ) @ γ +``` + +## 自我确认均衡 + +自我确认均衡是一种能够自我复制的信念:政府依据 $\gamma$ 采取行动所生成的数据上,{eq}`en_belief` 的总体回归系数等于 $\gamma$ 本身。 + +将这些总体系数记为 $T(\gamma)$,CWS 证明 + +$$ +\bar g(\gamma) \equiv E\left[\Phi(U - \Phi'\gamma)\right] = \bar M \left(T(\gamma) - \gamma\right), +$$ + +因此自我确认均衡解出 $\bar g(\gamma) = 0$。 + +对于静态模型,均衡是直线 $\gamma_1 = -\theta$ 与抛物线 $\gamma_{-1} = u(1 + \gamma_1^2)$ 的交点——一个唯一点,它支持 {doc}`phillips_credibility` 中的纳什结果。 + +它与 {doc}`phillips_self_confirming` 中构造的自我确认均衡相同,此处以静态(常数加斜率)特例的形式给出,{doc}`phillips_priors` 中同样使用这一形式。 + +```{code-cell} ipython3 +model = EscapeModel(θ=1.0, u=5.0, σ1=0.3, σ2=0.3) +γ_sce = np.array([-model.θ, model.u * (1 + model.θ**2)]) + +print(f"self-confirming beliefs γ = {γ_sce} (slope -θ, intercept u(1+θ²))") +print(f"self-confirming inflation x = {model.x(γ_sce):.2f} (= Nash = θu)") +print(f"check g_bar = {model.g_bar(γ_sce)}") +``` + +```{code-cell} ipython3 +γ1_grid = np.linspace(-2, 1, 200) +fig, ax = plt.subplots(figsize=(7, 6)) +ax.plot(γ1_grid, model.u * (1 + γ1_grid**2), label=r'$\gamma_{-1} = u(1+\gamma_1^2)$') +ax.axvline(-model.θ, color='C1', ls='--', label=r'$\gamma_1 = -\theta$') +ax.plot(γ_sce[0], γ_sce[1], 'ko', ms=8) +ax.annotate('SCE (Nash)', γ_sce, (γ_sce[0] + 0.1, γ_sce[1] + 1)) +ax.set_xlabel(r'slope $\gamma_1$') +ax.set_ylabel(r'intercept $\gamma_{-1}$') +ax.set_ylim(0, 25) +ax.legend() +ax.set_title('The unique self-confirming equilibrium') +plt.show() +``` + +## 适应性与均值动态 + +我们令政府具有适应性:每期它都通过恒定增益递归最小二乘法更新 $\gamma$,并依据当前的估计值采取行动——这是 {cite}`Kreps1998` 意义上的**预期效用**模型。 + +关于最小二乘学习的文献({cite}`MarcetSargent1989`、{cite}`Woodford1990`、{cite}`EvansHonkapohja2001`)表明,当增益 $\varepsilon \to 0$ 时,信念可以由**均值动态**常微分方程近似: + +```{math} +:label: en_mean + +\dot\gamma = R^{-1} \bar g(\gamma), +\qquad +\dot R = \bar M(\gamma) - R . +``` + +{eq}`en_mean` 的一个静止点即为一个自我确认均衡,CWS 证明该常微分方程围绕它是*全局稳定*的。 + +因此,仅在均值动态作用下,适应性政府会被吸引到纳什通货膨胀水平。 + +```{code-cell} ipython3 +def mean_ode(t, z, model): + γ, R = z[:2], z[2:].reshape(2, 2) + return np.concatenate([np.linalg.inv(R) @ model.g_bar(γ), + (model.M(γ) - R).ravel()]) + +z0 = np.concatenate([γ_sce + np.array([0.4, -3.0]), model.M(γ_sce).ravel()]) +sol = solve_ivp(lambda t, z: mean_ode(t, z, model), [0, 60], z0, + max_step=0.1, rtol=1e-9, atol=1e-11) + +fig, ax = plt.subplots(figsize=(8, 4.5)) +ax.plot(sol.t, -sol.y[1] * sol.y[0] / (1 + sol.y[0]**2)) +ax.axhline(model.θ * model.u, color='k', ls='--', lw=1, label='Nash') +ax.set_xlabel('time') +ax.set_ylabel('inflation $x$') +ax.set_title('Mean dynamics: from a perturbed start, beliefs return to Nash') +ax.legend() +plt.show() +``` + +均值动态本身无法解释 {doc}`phillips_learning` 中模拟所显示的反复出现的低通胀访问现象。 + +要解释这一点,我们需要第二种力量。 + +## 作为控制问题的逃逸动态 + +尽管当 $\varepsilon \to 0$ 时噪声的影响会消失,但对于固定的正增益,*罕见*的冲击序列可以将信念推离自我确认均衡很远。 + +大偏差理论刻画了这种罕见事件*最可能*的形式。 + +对于一条候选信念路径 $\gamma(\cdot)$,可以定义最小二乘创新的对数矩生成(H-)泛函,其勒让德变换 $L$,以及一个**行动泛函** $S(T, \gamma) = \int_0^T L\,ds$,用以衡量该路径的"代价"——即它有多不可能。 + +**主导逃逸路径**在离开 $\bar\gamma$ 的一个邻域 $G$ 的约束下最小化行动值。 + +借鉴 {cite}`Williams2019`,CWS 将其归纳为一个简洁的控制问题:H-泛函变为具有归一化矩阵 $Q$(由李雅普诺夫方程得到的四阶矩矩阵)的二次形式,逃逸路径求解 + +```{math} +:label: en_control + +\bar S = \inf_{v(\cdot),\, T} \; \frac12 \int_0^T v(s)' Q(\gamma(s), R(s))^{-1} v(s)\, ds +``` + +约束条件为*受扰动的*均值动态 + +```{math} +:label: en_perturbed + +\dot\gamma = R^{-1}\bar g(\gamma) + v, +\qquad +\dot R = \bar M(\gamma) - R, +\qquad +\gamma(0) = \bar\gamma, \; \gamma(T) \notin G . +``` + +可以将 {eq}`en_control` 理解为一个最小二乘问题:$v$ 是均值动态要实现逃逸所需的额外"强制项",$Q$ 起协方差矩阵的作用,代价最低的强制项即是最可能出现的异常冲击序列。 + +其两个推论(他们的定理 5.3)将该控制问题与随机模型联系起来: + +* 在一个有界区间上发生逃逸的概率约为 $\exp(-\bar S/\varepsilon)$,因此**逃逸之间的平均时间**约为 $\exp(\bar S/\varepsilon)$;且 +* 在发生逃逸的条件下,信念以趋近于一的概率沿主导逃逸路径演变。 + +逃逸动态与均值动态一样,都是*确定性*的。 + +## 主导逃逸路径 + +对于具有二项冲击的静态模型,CWS 以封闭形式求解了该控制问题(其第 7 节)。 + +逃逸强制项异常简单: + +```{math} +:label: en_force + +v = R^{-1} \begin{bmatrix} \sigma_1 \sigma_2 \\ 0 \end{bmatrix} , +``` + +因此主导逃逸路径求解 + +```{math} +:label: en_escape + +\dot\gamma = R^{-1}\left( \bar g(\gamma) + \begin{bmatrix} \sigma_1 \sigma_2 \\ 0 \end{bmatrix} \right), +\qquad +\dot R = \bar M(\gamma) - R . +``` + +让我们从自我确认均衡出发对 {eq}`en_escape` 进行积分,直到信念离开一个半径为 5 的圆。 + +```{code-cell} ipython3 +def escape_ode(t, z, model): + γ, R = z[:2], z[2:].reshape(2, 2) + force = np.array([model.σ1 * model.σ2, 0.0]) + return np.concatenate([np.linalg.inv(R) @ (model.g_bar(γ) + force), + (model.M(γ) - R).ravel()]) + +def left_circle(t, z): + "Terminal event: beliefs leave the radius-5 circle around the SCE." + return 5.0 - np.linalg.norm(z[:2] - γ_sce) +left_circle.terminal = True +left_circle.direction = -1 + +z0 = np.concatenate([γ_sce, model.M(γ_sce).ravel()]) +esc = solve_ivp(lambda t, z: escape_ode(t, z, model), [0, 200], z0, + events=left_circle, max_step=0.02, rtol=1e-9, atol=1e-11) + +slope, intercept = esc.y[0], esc.y[1] +infl = -intercept * slope / (1 + slope**2) +``` + +```{code-cell} ipython3 +fig, axes = plt.subplots(1, 2, figsize=(12, 5)) + +axes[0].plot(esc.t, intercept, label='intercept $\\gamma_{-1}$') +axes[0].plot(esc.t, slope, label='slope $\\gamma_1$') +axes[0].axhline(0, color='C3', ls=':', lw=1, label='induction ($\\gamma_1 = 0$)') +axes[0].set_xlabel('time') +axes[0].set_ylabel('coefficient') +axes[0].set_title('Dominant escape path (cf. CWS Figure 4)') +axes[0].legend() + +axes[1].plot(esc.t, infl) +axes[1].axhline(model.θ * model.u, color='k', ls='--', lw=1, label='Nash') +axes[1].axhline(0, color='C2', ls=':', lw=1, label='Ramsey') +axes[1].set_xlabel('time') +axes[1].set_ylabel('inflation $x$') +axes[1].set_title('Inflation along the escape') +axes[1].legend() + +plt.tight_layout() +plt.show() +``` + +```{code-cell} ipython3 +print(f"slope : {slope[0]:.2f} → {slope[-1]:.3f} (induction hypothesis at 0)") +print(f"intercept : {intercept[0]:.1f} → {intercept[-1]:.1f}") +print(f"inflation : {infl[0]:.2f} → {infl[-1]:.2f} (Nash {model.θ*model.u:.0f} → Ramsey 0)") +``` + +沿着主导逃逸路径,斜率从其自我确认值 $-1$ 上升到接近零——即**归纳假说**——通货膨胀则从纳什水平下降到接近拉姆齐水平。 + +这正是我们在 {doc}`phillips_learning` 中通过模拟看到的那种暂时性稳定化,现在被推导为一条确定性路径:政府偶然生成了足够多的通货膨胀*实验*,从而发现了自然率假说的一个足够好的版本,并据此采取行动。 + +## 四条常微分方程的竞速 + +逃逸强制项 {eq}`en_force` 从何而来? + +对于二项冲击 $W_{in} \in \{-1, +1\}$,任意一期实现的冲击组合都落在四组之一。 + +CWS 证明,最可能的逃逸会*反复*使用相同的异常组合,因此存在四条候选逃逸常微分方程——每种组合对应一条——而主导逃逸即为最快到达边界的那一条。 + +让我们计算每个候选路径在自我确认均衡处的瞬时速度。 + +```{code-cell} ipython3 +R0 = model.M(γ_sce) +R0_inv = np.linalg.inv(R0) +σ1σ2 = model.σ1 * model.σ2 + +candidates = { + "{(1,1),(-1,-1)} → Ramsey": np.array([σ1σ2, 0.0]), + "{(1,-1),(-1,1)} → higher π": np.array([-σ1σ2, 0.0]), + "{(1,1),(1,-1)}": R0 @ (R0_inv @ np.array([model.x(γ_sce) * model.σ1, model.σ1])), + "{(-1,1),(-1,-1)}": R0 @ (R0_inv @ np.array([-model.x(γ_sce) * model.σ1, -model.σ1])), +} + +for name, force in candidates.items(): + v = R0_inv @ force + print(f" {name:28s} |velocity| = {np.linalg.norm(v):.3f}") +``` + +组合 $\{(1,1), (-1,-1)\}$ 产生的速度远大于最后两个组合,且其方向指*向*拉姆齐(斜率上升、截距下降)。 + +其镜像组合 $\{(1,-1),(-1,1)\}$ 具有相同的速率,但方向错误——指向*更高*的通货膨胀——而在那个方向上均值动态会与之对抗,很快将其拉回。 + +因此这场竞速的胜者是朝向拉姆齐方向的路径,它所诱导出的逃逸强制项正是 {eq}`en_force` 中的 $R^{-1}(\sigma_1\sigma_2, 0)'$。 + +## 均值动态强化逃逸 + +为什么朝向拉姆齐的逃逸能够成功,而其镜像却失败了? + +在自我确认均衡附近,均值动态指*向*该均衡,对抗任何逃逸。 + +但 CWS(其图 8-9)表明,一旦信念沿朝向拉姆齐的方向移动了一小段距离,均值动态本身就开始指*向*拉姆齐,从而强化了逃逸。 + +我们可以通过绘制信念空间中的均值动态向量场来观察这一点。 + +```{code-cell} ipython3 +gs = np.linspace(-1.2, 0.1, 16) # slope +gi = np.linspace(4.5, 10.5, 16) # intercept +GS, GI = np.meshgrid(gs, gi) +DS, DI = np.zeros_like(GS), np.zeros_like(GI) + +for i in range(GS.shape[0]): + for j in range(GS.shape[1]): + γ = np.array([GS[i, j], GI[i, j]]) + d = np.linalg.inv(model.M(γ)) @ model.g_bar(γ) + DS[i, j], DI[i, j] = d + +fig, ax = plt.subplots(figsize=(8, 6)) +ax.quiver(GS, GI, DS, DI, angles='xy', alpha=0.7) +ax.plot(*γ_sce, 'ko', ms=8, label='SCE (Nash)') +ax.plot(0, model.u, 'C2s', ms=8, label='Ramsey belief') +ax.plot(slope, intercept, 'C3', lw=2, label='escape path') +ax.set_xlabel(r'slope $\gamma_1$') +ax.set_ylabel(r'intercept $\gamma_{-1}$') +ax.set_title('Mean dynamics (arrows) and the escape path') +ax.legend() +plt.show() +``` + +在自我确认均衡附近,箭头将信念推回纳什水平,但离开该均衡后——沿着逃逸路径——箭头则朝拉姆齐信念方向扫动。 + +逃逸动态只需要*启动*这一背离过程;均值动态负责完成剩余的工作。 + +正是在这个意义上,均值动态描绘出一条*迂回*的路线:被逃逸路径推离均衡后,系统会在拉姆齐附近停留一段时间,然后残留的短期菲利普斯曲线才被重新发现,均值动态最终将信念带回纳什水平。 + +## 试验陷阱 + +这种逃逸具有一种令人信服的行为解释。 + +在其近似模型内部,政府只有当通货膨胀存在足够的*离散度*时,才能检测到自然率假说。 + +但在自我确认均衡内,政府设定了一个恒定的系统性通货膨胀率,因此不会产生这种离散度——它被困在一个**试验陷阱**中。 + +只有一段异常的冲击序列,才会使政府充分改变通货膨胀,从而使其估计的菲利普斯曲线变得更陡;一条更陡峭的感知曲线(通过最优反应)会引导它削减通货膨胀,这又会产生进一步的有影响力的观测值,使曲线进一步变陡。 + +这种自我强化的过程会在感知的菲利普斯曲线变得垂直时——即归纳假说——停止,通货膨胀接近拉姆齐水平。 + +系统无法永远停留在那里:事实上*确实*存在一条短期菲利普斯曲线,政府最终会重新发现它,从而重新点燃将其带回纳什水平的均值动态。 + +## 逃逸频率与模型丰富度 + +被最小化的行动值 $\bar S$ 决定了逃逸发生的频繁程度:平均逃逸时间以 $\exp(\bar S/\varepsilon)$ 的速度增长。 + +CWS 的一个引人注目的发现是,当政府的模型更加丰富时,逃逸会*更加频繁*。 + +{doc}`phillips_learning` 中带有滞后失业率与滞后通货膨胀的完整动态模型,其 $\bar S$ 远小于静态模型,尽管两者具有相同的自我确认均衡。 + +一个更丰富的模型使政府能够检测到自然率假说更为微妙的分布滞后("归纳假说")版本,因此它更容易朝拉姆齐方向逃逸。 + +```{note} +逃逸动态继承了使均值动态如此有用的同一种"近似确定性":对于较小的增益,{doc}`phillips_learning` 中的随机模拟会紧贴此处推导出的确定性逃逸路径。下一讲 {doc}`phillips_priors` 表明,政府关于其系数如何漂移的*先验*会重塑这两种动态——甚至可能使逃逸变成一个确定性的*循环*。 +``` + +## 逃离高波动通货膨胀 + +逃逸带来的是通货膨胀*水平*的下降。 + +{cite}`EllisonYates2007` 扩展了该模型,以解释战后的第二个事实:通货膨胀*波动性*与通货膨胀水平同升同降。 + +他们的方法是给政府一个稳定化的动机。 + +沿用 {cite}`PhelpsTaylor1977` 的思路,他们加入了一个失业冲击 $W_3$,政府(而非制定价格的私人部门)可以对其做出反应。 + +现在,一个相信存在可利用的菲利普斯曲线的政府,倾向于通过改变通货膨胀来*对抗* $W_3$,因此政策的感知有效性 $|\gamma_1|$ 不仅驱动通货膨胀的水平,也驱动其波动性。 + +在他们的模型中,私人主体所面临的预期通货膨胀波动性为 + +```{math} +:label: en_vol + +E(\sigma_\pi \mid \gamma) = \left[ \sigma_2^2 + \left(\frac{\gamma_1}{1 + \gamma_1^2}\right)^2 \sigma_3^2 \right]^{1/2} . +``` + +在自我确认均衡 $\gamma_1 = -\theta$ 处,政府相信政策是有效的,并积极对抗 $W_3$,因此通货膨胀是*波动的*。 + +沿着逃逸路径,$\gamma_1 \to 0$:政府不再相信自己能够利用菲利普斯曲线,放弃了稳定化操作,波动性项收缩为控制误差 $\sigma_2$。 + +将 {eq}`en_vol` 应用于我们已经计算出的信念路径,可以看出通货膨胀的水平与波动性*同步*逃逸。 + +```{code-cell} ipython3 +σ3 = 0.9 # size of the stabilizable shock +infl_vol = np.sqrt(model.σ2**2 + (slope / (1 + slope**2))**2 * σ3**2) + +fig, axes = plt.subplots(1, 2, figsize=(12, 4.5)) +axes[0].plot(esc.t, infl) +axes[0].axhline(model.θ * model.u, color='k', ls='--', lw=1, label='Nash') +axes[0].axhline(0, color='C2', ls=':', lw=1, label='Ramsey') +axes[0].set_xlabel('time'); axes[0].set_ylabel('inflation level') +axes[0].set_title('level escapes'); axes[0].legend() + +axes[1].plot(esc.t, infl_vol, 'C1') +axes[1].axhline(model.σ2, color='k', ls='--', lw=1, label=r'control error $\sigma_2$') +axes[1].set_xlabel('time'); axes[1].set_ylabel('inflation volatility') +axes[1].set_title('volatility escapes too'); axes[1].legend() + +plt.tight_layout() +plt.show() +``` + +随着信念的逃逸,二者都会下降,因为它们都源自同一个根源:政府对存在可利用权衡取舍的信念。 + +{cite}`EllisonYates2007` 还就逃逸的*时机*得出了一个更为微妙的进一步结论。 + +一个更大的可稳定冲击 $\sigma_3$ 会使逃逸*更难触发*:为了制造出通货膨胀在变动而失业率保持不变的假象,一段异常的冲击序列现在不仅要抵消控制误差,还必须抵消政府自身针对 $W_3$ 的稳定化反应。 + +政府能够抵消的冲击越多,触发逃逸所需的序列就越复杂,等待时间也就越长。 + +如果按字面理解,这意味着一个经济体恰恰在需要稳定化的冲击*较少*时,才更有可能逃向低通胀——这为二十世纪八十年代中期出现的经济平静与伴随而来的反通胀之间提供了一种颇具启发性的联系。 + +## 练习 + +```{exercise-start} +:label: en_ex1 +``` + +逃逸强制项 {eq}`en_force` 与 $\sigma_1 \sigma_2$——两个冲击标准差的乘积——成比例。 + +对一组 $\sigma_1 = \sigma_2 = \sigma \in \{0.2, 0.3, 0.4, 0.5\}$ 分别积分主导逃逸常微分方程 {eq}`en_escape`,并报告每种情形下从半径为 5 的圆中*退出的时间*。 + +一个噪声更大的经济体,会如何影响信念沿逃逸路线移动的速度? + +```{exercise-end} +``` + +```{solution-start} en_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +for σ in [0.2, 0.3, 0.4, 0.5]: + m = EscapeModel(θ=1.0, u=5.0, σ1=σ, σ2=σ) + γ0 = np.array([-m.θ, m.u * (1 + m.θ**2)]) + + def leave(t, z, m=m, γ0=γ0): + return 5.0 - np.linalg.norm(z[:2] - γ0) + leave.terminal = True + leave.direction = -1 + + z0 = np.concatenate([γ0, m.M(γ0).ravel()]) + s = solve_ivp(lambda t, z: escape_ode(t, z, m), [0, 500], z0, + events=leave, max_step=0.02, rtol=1e-9, atol=1e-11) + print(f"σ = {σ}: exit time along the escape path = {s.t[-1]:.2f}") +``` + +更大的 $\sigma$ 会使逃逸强制项 $R^{-1}(\sigma_1\sigma_2, 0)'$ 变得更强,因此信念沿逃逸路线移动得更快(沿确定性路径的退出*时间*更短)。 + +请注意,这与逃逸的*频率*不同,后者由行动值 $\bar S$ 与增益 $\varepsilon$ 支配;一个噪声更大的经济体,一旦逃逸开始,会更快地走完某条既定的逃逸路线。 + +```{solution-end} +``` + +```{exercise-start} +:label: en_ex2 +``` + +将向量场图中的强化效应量化。 + +在逃逸路径*沿途*的若干点上,计算均值动态漂移 $R^{-1}\bar g(\gamma)$,并测量它与当前信念指向拉姆齐信念 $(0, u)$ 方向之间的余弦对齐度。 + +余弦值接近 $+1$ 意味着均值动态正将信念推*向*拉姆齐——强化了逃逸。 + +```{exercise-end} +``` + +```{solution-start} en_ex2 +:class: dropdown +``` + +```{code-cell} ipython3 +γ_ramsey = np.array([0.0, model.u]) # Belief 2 + +def cosine_toward_ramsey(γ, R): + drift = np.linalg.inv(R) @ model.g_bar(γ) + to_ramsey = γ_ramsey - γ + denom = np.linalg.norm(drift) * np.linalg.norm(to_ramsey) + return np.nan if denom < 1e-9 else drift @ to_ramsey / denom + +for frac in [0.0, 0.25, 0.5, 0.75, 0.95]: + k = min(int(frac * len(esc.t)), len(esc.t) - 1) + γ, R = esc.y[:2, k], esc.y[2:, k].reshape(2, 2) + print(f"frac {frac:.2f}: γ = ({γ[0]:+.2f}, {γ[1]:.1f}), " + f"cos(drift, →Ramsey) = {cosine_toward_ramsey(γ, R):+.2f}") +``` + +正处于自我确认均衡时,漂移为零(余弦值未定义),因此均值动态既不助力也不阻碍逃逸。 + +但一旦信念沿逃逸路线移动了哪怕一点点,均值动态的漂移方向就几乎精确地指向拉姆齐信念(余弦值 $\approx +1$):均值动态一路强化逃逸,直至到达拉姆齐水平。 + +CWS 所强调的对抗力量,仅局限于均衡附近的一个*极小*邻域——逃逸动态只需要将信念推出这个邻域,之后均值动态便会完成剩余的工作。 + +```{solution-end} +``` \ No newline at end of file From 99f981e845de6226e2fc11aee03793999a766498 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:18 +1000 Subject: [PATCH 08/21] Update translation: .translate/state/phillips_escaping_nash.md.yml --- .translate/state/phillips_escaping_nash.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_escaping_nash.md.yml diff --git a/.translate/state/phillips_escaping_nash.md.yml b/.translate/state/phillips_escaping_nash.md.yml new file mode 100644 index 0000000..5d42b93 --- /dev/null +++ b/.translate/state/phillips_escaping_nash.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 12 +tool-version: 0.23.0 From e0981b648e07b9a6e72723907c0c7307b7745398 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:19 +1000 Subject: [PATCH 09/21] Update translation: lectures/phillips_learning.md --- lectures/phillips_learning.md | 799 ++++++++++++++++++++++++++++++++++ 1 file changed, 799 insertions(+) create mode 100644 lectures/phillips_learning.md diff --git a/lectures/phillips_learning.md b/lectures/phillips_learning.md new file mode 100644 index 0000000..5ff650d --- /dev/null +++ b/lectures/phillips_learning.md @@ -0,0 +1,799 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 适应性学习与逃逸动态 + headings: + Overview: 概述 + A primer on recursive algorithms: 递归算法入门 + A primer on recursive algorithms::Beliefs, moment conditions, and self-confirming equilibria: 信念、矩条件与自我确认均衡 + A primer on recursive algorithms::Iteration: 迭代法 + A primer on recursive algorithms::Stochastic approximation: 随机逼近 + A primer on recursive algorithms::Mean dynamics: 均值动态 + A primer on recursive algorithms::Constant gain and convergence in distribution: 常数增益与依分布收敛 + A primer on recursive algorithms::Escape routes and the theory of large deviations: 逃逸路径与大偏差理论 + A primer on recursive algorithms::A tractable action functional: 一个可处理的行动泛函 + A primer on recursive algorithms::From computation to adaptation: 从计算到适应 + The adaptive model: 适应性模型 + The adaptive model::Government beliefs and behavior: 政府的信念与行为 + The adaptive model::The Phelps problem with lags: 带滞后项的菲尔普斯问题 + Least squares learning converges: 最小二乘法学习收敛 + Constant gain and escape dynamics: 常数增益与逃逸动态 + The escape route and the induction hypothesis: 逃逸路径与归纳假设 + Relation to equilibria under forecast misspecification: 与预测误设均衡的关系 + Role of the discount factor: 折扣因子的作用 + Anticipated utility: 预期效用 + Conclusions: 结论 + Exercises: 练习 +--- + +(phillips_learning)= +```{raw} jupyter + +``` + +# 适应性学习与逃逸动态 + +```{contents} Contents +:depth: 2 +``` + +## 概述 + +本讲座是*菲利普斯曲线权衡*系列讲座的集大成之作。 + +它遵循 {cite}`Sargent1999` 的第 8 章,这是该书最具野心的一章。 + +在 {doc}`phillips_self_confirming` 中,政府对菲利普斯曲线持有*固定*的信念——这些信念被由它们本身所生成的数据所证实。 + +在这里,我们把政府变成一个实时经济计量学家。 + +每一期它都: + +* 根据到目前为止观测到的数据,通过递归最小二乘法重新估计其菲利普斯曲线;并且 +* 根据其*当前*的估计值,设定通货膨胀率为 {doc}`phelps 问题 ` 第一期建议的水平。 + +我们要问的是:这样一个适应性的政府是否会收敛到自我确认均衡。 + +答案取决于一个单一的参数——支配旧数据被折扣速度的**增益**(gain): + +* 若采用实现最小二乘法的*递减*增益,均值动态会将经济拉向自我确认均衡,我们不会得到什么新结果:系统被困在纳什结果附近。 +* 若采用*常数*增益,主体会对过去数据打折扣,收敛被阻止,**新的结果便会涌现**。系统会反复地从自我确认均衡*逃逸*向拉姆齐(零通胀)结果——这种自发的稳定化现象,颇似沃尔克时代的到来。 + +这些逃逸正是 {doc}`phillips_two_stories` 中"econometric 政策评估的证明"故事的核心:一个学习索洛-托宾分布滞后版本自然率假说的适应性政府,会因偶然的观察结果而稳定住通货膨胀。 + +本讲座复现、分析并重新诠释了类似克里斯托弗·西姆斯(Christopher Sims)和郑喜泰(Heetaik Chung)的模拟结果 {cite}`Sims1988,Chung1990`。 + +在这里,我们通过*模拟*来研究这些逃逸;{doc}`phillips_escaping_nash` 随后将其解析地刻画为第二个确定性 ODE,而 {doc}`phillips_priors` 则探讨政府关于系数漂移的先验如何重塑这两种力量。 + +让我们导入所需的库: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +from scipy.linalg import solve_discrete_are +``` + +## 递归算法入门 + +本节是一个独立完整的入门介绍。 + +它构建了贯穿后文全部内容的两个分析对象——**均值动态**(mean dynamics)与**逃逸路径**(escape routes)——并解释了同一个递归公式既可以被视为计算自我确认均衡的*算法*,也可以被视为政府实时适应的*模型*的意义所在。 + +这部分内容较为技术性,只想了解结论的读者可以直接跳到下面的模拟部分,需要时再回来查阅。 + +### 信念、矩条件与自我确认均衡 + +在经典识别方案下,自我确认均衡由政府关于某些总体矩及其所隐含的回归系数的信念所确定。 + +在经典识别方案下,这些信念由三元组 $(\gamma, \, E X_{C} X_{C}', \, E U X_{C})$ 度量,其中 $\gamma$ 是菲利普斯曲线系数向量。 + +在本讲座的适应性模型中,这些对象的*时间 $t$ 的取值*是经济的状态变量之一;它们只有在自我确认均衡中才不再作为状态变量存在,因为在那里它们是常数。 + +经典识别方案下的自我确认均衡满足以下矩条件: + +```{math} +:label: pl_scemoments + +\begin{aligned} +E\, R_{XC}^{-1}(\gamma)\left[ U_t X_{Ct}' - \left(X_{Ct} X_{Ct}'\right)\gamma \right] &= 0, \\ +E\, X_{Ct} X_{Ct}' - R_{XC}(\gamma) &= 0, +\end{aligned} +``` + +其中数学期望是关于 $(U_t, X_{Ct})$ 的分布计算的,而该分布通过菲尔普斯问题的解 $h(\gamma)$ 依赖于 $\gamma$。 + +自我指涉正是通过分布对 $\gamma$ 的这种依赖性而浮现出来的:政府的信念塑造其政策,而政策塑造了随后用来检验信念的数据。 + +{eq}`pl_scemoments` 的第一行是 $\gamma$ 的最小二乘正规方程,两边预先乘以二阶矩矩阵的逆;第二行将 $R_{XC}$ 定义为回归量的二阶矩矩阵。 + +将所有未知量组合成一个向量会比较方便: + +```{math} +:label: pl_phivec + +\phi = \begin{bmatrix} \gamma \\ \operatorname{col}(R_{XC}) \end{bmatrix}, +``` + +其中 $\operatorname{col}(R_{XC})$ 将 $R_{XC}$ 的各列堆叠起来。 + +矩条件 {eq}`pl_scemoments` 随即可以写成紧凑形式: + +```{math} +:label: pl_bdef + +E\left[F(\phi, \zeta)\right] = 0, +\qquad +b(\phi) \equiv E\left[F(\phi, \zeta)\right], +``` + +其中 $\zeta$ 是一个随机向量,期望是关于其分布计算的(同样,该分布依赖于 $\phi$)。 + +自我确认均衡是 $b$ 的一个零点,即一组信念 $\phi_f$,满足: + +```{math} +:label: pl_scezero + +b(\phi_f) = 0 . +``` + +本节余下的部分描述了寻找这样一个零点的递归算法,以及一种将每个计算算法转化为实时适应模型的视角转换。 + +### 迭代法 + +最简单的算法通过以下公式计算估计值序列 $\{\phi_k\}$: + +```{math} +:label: pl_iterate + +\phi_{k+1} = \phi_k + a\, b(\phi_k), +``` + +其中,用来计算 {eq}`pl_bdef` 中定义 $b(\phi_k)$ 的期望所用的分布,本身是在当前估计值 $\phi_k$ 处计算的,而 $a > 0$ 是步长。 + +这正是 {doc}`phillips_self_confirming` 中用来计算自我确认均衡的松弛算法。 + +每一步都需要计算数学期望 $b(\phi) = E[F(\phi, \zeta)]$——这正是我们在那里需要矩(李雅普诺夫)公式的原因。 + +### 随机逼近 + +将 {eq}`pl_iterate` 中的均值 $b(\phi_n)$ 替换为单次随机抽样 $F(\phi_n, \zeta_n)$,并让*步长*来完成平均,就得到了 {eq}`pl_iterate` 的一个随机版本: + +```{math} +:label: pl_sa + +\phi_{n+1} = \phi_n + a_n F(\phi_n, \zeta_n), +\qquad +a_n > 0, \quad \sum_{n=0}^\infty a_n = +\infty . +``` + +要研究 {eq}`pl_sa` 的极限行为,我们定义**人为时间**(artificial time): + +```{math} +:label: pl_artificial + +t_n = \sum_{k=0}^n a_k , +``` + +构造抽样过程 $\phi(t_n) = \phi_n$,并对其进行插值(通常是分段线性插值),得到一个连续时间过程 $\phi^o(t)$。 + +随后,随着 $n \to \infty$,用一个连续时间过程来逼近 $\phi^o(t)$,并利用它来刻画原始序列的尾部行为。 + +增益序列 $\{a_n\}$ 不同的递减速率会产生不同的逼近过程,因为它们改变了从实际时间 $n$ 到人为时间 $t_n$ 的映射 {eq}`pl_artificial`。 + +```{note} +递归随机逼近起源于 {cite}`RobbinsMonro1951`,他设计了 {eq}`pl_sa` 用于在噪声观测下寻找回归函数的根;以及 {cite}`KieferWolfowitz1952`,他将其改造用于寻找回归函数的最大值(下文提到的"K-W"算法)。用于分析此类递归的"ODE 方法"——即用微分方程的解来逼近插值过程——归功于 {cite}`Ljung1977`;书籍级的详尽处理见 {cite}`BenvenisteMetivierPriouret1990` 和 {cite}`KushnerYin2003`。将其用于研究自我指涉宏观经济模型中的学习问题,由 {cite}`MarcetSargent1989` 开创,并被 {cite}`EvansHonkapohja2001` 全面发展。 +``` + +### 均值动态 + +{cite}`KushnerClark1978` 和 {cite}`Ljung1977` 的经典随机逼近算法将增益设定为按 $a_n \sim 1/n$ 的速度递减(至少对某个 $N > 0$ 满足 $t \geq N$)。 + +这使得我们能够对 {eq}`pl_sa` 几乎必然收敛到 $b(\phi)$ 的零点这一结论做出强有力的论断。 + +当 $a_n \sim 1/n$ 时,随着 $n \to \infty$,插值过程 $\phi^o(t)$ 逼近以下常微分方程的解: + +```{math} +:label: pl_ode + +\frac{d \phi^o(t)}{dt} = b\left(\phi^o(t)\right), +``` + +我们称之为**均值动态**——这是 {doc}`phillips_credibility` 附录中推导的标量最小二乘学习 ODE 的向量化推广。 + +大数定律使连续时间逼近中的随机项以足够快的速度消失,从而使均值动态 {eq}`pl_ode` 刻画了随机过程 {eq}`pl_sa` 的*尾部*行为。 + +因此: + +* 如果算法收敛(几乎必然地),它就收敛到均值动态的零点 $b(\phi) = 0$——即一个自我确认均衡;并且 +* ODE {eq}`pl_ode` 携带着关于算法局部与全局稳定性的信息。 + +局部稳定性由 $b$ 在静止点处雅可比矩阵的特征值支配:如果所有特征值的实部都为负,该静止点就是局部稳定的;而在关于增益的一定条件下,实部最大的特征值支配着收敛的*速率*(通常的 $\sqrt{T}$ 速率要求该特征值低于 $-\tfrac12$)。 + +我们将在下面看到,在我们所用参数下,经典模型的这个特征值恰好位于 $-\tfrac12$ 的边界上,因此收敛是边际性的——事实证明,这一点对系统能否轻易逃逸至关重要。 + +```{note} +{cite}`BrockHommes1997` 构建的模型,其全局行为由远离理性预期均衡的稳定均值动态,以及在均衡附近适应的局部不稳定性共同驱动——这是一种从学习中产生内生波动的互补机制。 +``` + +### 常数增益与依分布收敛 + +我们同样关注 {eq}`pl_sa` 的另一版本,其中对所有 $n$ 都采用*常数*增益 $a_n = \epsilon > 0$。 + +常数增益算法的极限定理使用了一种弱于 $a_n \sim 1/n$ 时可用的几乎必然收敛的收敛概念——即依分布收敛。 + +它们关注的是当 $\epsilon \to 0$ 同时 $n\epsilon \to +\infty$ 时的小噪声极限。 + +同样使用人为时间 {eq}`pl_artificial`,构造过程族: + +```{math} +:label: pl_cgain + +\phi_{n+1}^\epsilon = \phi_n^\epsilon + \epsilon\, F(\phi_n^\epsilon, \zeta_n), +``` + +对其插值以得到 $\phi^\epsilon(t)$,并研究其小 $\epsilon$ 极限。 + +杜皮伊(Dupuis)与库什纳(Kushner),见 {cite}`KushnerYin2003`,以及其他学者验证了在何种条件下,当 $\epsilon \to 0$ 且 $\epsilon n \to \infty$ 时,过程 $\phi_n^\epsilon$ *依分布*收敛到同一均值动态 {eq}`pl_ode` 的零点;均值动态所需满足的限制条件与经典 $a_n \sim 1/n$ 理论中的要求相同。 + +与递减增益算法不同,常数增益算法不会稳定下来:$(\gamma, R_{XC})$ 会收敛到一个*平稳随机过程*,围绕自我确认均衡永久地波动——并偶尔远离它。 + +### 逃逸路径与大偏差理论 + +对本讲座而言,常数增益机制中最重要的特征不是向 $\phi_f$ 的收敛,而是*远离它的偏离*。 + +我们对远离自我确认均衡的运动与趋向它的运动同样感兴趣,因为模拟中反复出现的稳定化现象恰恰就是这样的偏离。 + +**大偏差理论**通过三个对象来刻画这些偏离。 + +首先是(创新过程 $F(\phi_n, \zeta_n)$ 某种平均化版本的)对数矩生成函数:对于与 $F$ 维数一致的向量 $\theta$, + +```{math} +:label: pl_mgf + +H(\theta, \phi) = \log E \exp\left(\theta' F(\phi, \zeta)\right), +``` + +其中期望是关于 $\zeta$ 的分布计算的。 + +```{note} +方程 {eq}`pl_mgf` 是一个启发性的简写。实际进入理论的对象是一个*时间平均*极限;{cite}`DupuisKushner1987` 和 {cite}`KushnerYin2003` 假设对每个 $\delta > 0$,以下极限在任意紧集上关于 $\phi_i, \alpha_i$ 一致存在: +$$ +\sum_{i=0}^{T/\delta - 1} \delta\, H(\alpha_i, \phi_i) += \lim_{N \to \infty} \frac{\delta}{N} + \log E \exp \sum_{i=0}^{T/\delta - 1} \alpha_i' + \sum_{j=iN}^{iN+N-1} F(\phi_i, \zeta_j) . +$$ +内部的求和对长度为 $N$ 的一个区块内的创新项做平均;双重极限使我们能够处理序列相关的创新项。 +``` + +其次是 $H$ 的**勒让德变换**(Legendre transform),它扮演速率函数的角色: + +```{math} +:label: pl_legendre + +L(\beta, \phi) = \sup_\theta \left[ \theta'\beta - H(\theta, \phi) \right] . +``` + +第三是**行动泛函**(action functional),它衡量候选逃逸路径 $\phi(\cdot)$ 的"代价": + +```{math} +:label: pl_action + +S(T, \phi) = +\begin{cases} +\displaystyle \int_0^T L\!\left(\tfrac{d}{ds}\phi(s),\, \phi(s)\right) ds + & \text{如果 } \phi(s) \text{ 绝对连续且 } \phi(0) = \phi_f, \\[2mm] +\infty & \text{否则。} +\end{cases} +``` + +杜皮伊和库什纳将寻找最可能逃逸路径的问题转化为一个*确定性控制问题*。 + +设 $D$ 是包含 $\phi_f$ 的一个紧集,其边界为 $\partial D$,设 $C[0,T]$ 是 $[0,T]$ 上的连续函数集合。 + +逃逸路径是求解以下问题的路径 $\tilde\phi(\cdot)$: + +```{math} +:label: pl_escapeproblem + +\inf_{T > 0} \; \inf_{\phi \in A} S(T, \phi), +\qquad +A = \left\{ \phi(\cdot) \in C[0,T] : \phi(T) \in \partial D \right\} . +``` + +假设最小化路径 $\tilde\phi(\cdot)$ 是唯一的,并设 $t_D^\epsilon$ 为常数增益过程 $\phi^\epsilon(t)$ 离开 $D$ 的首个时刻,{cite}`DupuisKushner1987` 证明了对每个 $\delta > 0$ 都有: + +```{math} +:label: pl_escapelim + +\lim_{\epsilon \to 0} \operatorname{Prob}\left( +\left| \phi^\epsilon(t_D^\epsilon) - \tilde\phi(T) \right| > \delta +\right) = 0 . +``` + +换句话说:*在系统逃离集合 $D$ 的条件下,它离开该集合的位置会接近最小行动路径的终点*——因此逃逸具有确定的方向和形态,尽管它是由偶然性触发的。 + +正是在这个意义上,下文中的逃逸虽然不需要任何巨大的冲击触发,却"看起来有目的性":它们遵循 {eq}`pl_escapeproblem` 所规定的最小行动路径。 + +一个关键的对比:均值动态 {eq}`pl_ode` *不*依赖于其周围的噪声,而逃逸路径*却*依赖于噪声——噪声不仅在 {eq}`pl_ode` 周围添加随机波动,它还开辟出了这第二类路径。 + +```{note} +其数学基础是 {cite}`FreidlinWentzell1998`(特别是其第 4 章)关于随机扰动动态系统的大偏差理论,被 {cite}`DupuisKushner1987` 和 {cite}`DupuisKushner1989` 专门用于随机逼近;一种弱收敛处理见 {cite}`DupuisEllis1997`。 +``` + +### 一个可处理的行动泛函 + +逃逸路径的计算承诺提供关于算法中心趋势的低成本信息,但行动泛函 {eq}`pl_action` 通常难以计算。 + +一个重要的特例极大地简化了它。 + +假设创新项是加性的且服从高斯分布: + +$$ +F(\phi, \zeta) = b(\phi) + \sigma(\phi)\, \zeta, +$$ + +其中 $\zeta_n$ 是平稳的且服从高斯分布,但不一定是序列不相关的,并定义 $R = \sum_j E\, \zeta_t \zeta_{t-j}'$。 + +那么行动泛函取如下二次形式: + +```{math} +:label: pl_action2 + +S(T, \phi) = \frac{1}{2} \int_0^T +\left(\tfrac{d}{ds}\phi - b(\phi)\right)' +\left[\sigma(\phi)\, R\, \sigma(\phi)'\right]^{+} +\left(\tfrac{d}{ds}\phi - b(\phi)\right) +h(s)\, ds , +``` + +其中 $(\cdot)^{+}$ 是摩尔-彭若斯广义逆(用于处理 $\sigma R \sigma'$ 可能出现的随机奇异性)。 + +权重 $h(s)$ 依赖于增益:当 $a_n = a_0 / n^\gamma$ 中的 $\gamma = 1$ 时,$h(s) = \exp(s)$;当 $\gamma < 1$ 时,$h(s) = 1$。 + +将 {eq}`pl_action2` 理解为一种代价,它惩罚*实际漂移* $\tfrac{d}{ds}\phi$ 与*均值漂移* $b(\phi)$ 之间的偏离,并按局部噪声协方差 $\sigma R \sigma'$ 的逆对每个方向加权。 + +因此最小行动逃逸路径会穿过均值动态较弱而噪声信息量较大的区域——而在我们的模型中,这恰恰是*归纳假设*所指的方向。 + +```{note} +这个二次行动泛函正是 {cite}`ChoWilliamsSargent2002` 中所最小化的对象,该文是本讲座模型的正式发表版本。他们求解了纳什自我确认均衡的控制问题 {eq}`pl_escapeproblem`,并从解析上证明了最小行动逃逸会将通货膨胀权重之和推向激活归纳假设的值——也就是趋向拉姆齐结果。{cite}`SargentWilliams2005` 研究了政府先验(等价地,即增益算法的协方差结构,我们的 $P_0$ 与遗忘因子)如何重塑逃逸,而 {cite}`Kasa2004` 将同样的大偏差机制应用于反复出现的货币危机。 +``` + +### 从计算到适应 + +前述递归公式是作为逼近自我确认均衡的*算法*被引入的。 + +同样的数学也告诉我们,当我们将自我确认均衡模型*改造*为纳入实时适应时会发生什么——只需将 $\phi_n$ 理解为政府在时间 $n$ 的信念,而非某个求解器的第 $n$ 次迭代结果。 + +以下两个事实统领了后文的一切: + +1. 实现最小二乘法的增益序列(按 $1/t$ 递减)使均值动态将经济拉*向*自我确认均衡;而 +2. 递减速度更慢的增益序列——极限情形下即为对过去打折扣的常数增益——则*阻止*了这种拉力,并增加了逃逸动态影响结果的频率。 + +```{note} +一段简短的思想史。{cite}`Lucas_Prescott_1971` 曾摒弃对矩条件 {eq}`pl_scezero` 进行迭代这一计算策略,但 {cite}`Townsend1983` 却使用了它。{cite}`Woodford1990` 和 {cite}`MarcetSargent1989` 用均值动态 {eq}`pl_ode` 建立了含有自我指涉的模型中最小二乘学习收敛于理性预期的条件,两者都要求 $b(\phi)$ 的连续性。曹寅坤(In-Koo Cho)研究了带有*不连续* $b(\phi)$ 的问题,这种不连续性源自可信度和搜索问题中不连续的决策规则(触发策略);为了使最小二乘学习逼近理性预期,他使用了满足 $\tfrac{1}{\log n} < a_n < \tfrac{1}{\sqrt n}$ 的增益,这为 {eq}`pl_sa` 产生了一个*扩散*逼近,促进了足够的试探以发现均衡。{cite}`KandoriMailathRob1993` 运用相关数学方法,通过突变在博弈中选择长期均衡,而罗杰·迈尔森(Roger Myerson)将逃逸路径的计算应用于一个投票问题。这些学习方法的现代综合体现在 {cite}`EvansHonkapohja2001` 中。 +``` + +## 适应性模型 + +现在我们来构建经典的适应性模型。 + +### 政府的信念与行为 + +政府相信存在一个分布滞后的菲利普斯曲线: + +```{math} +:label: pl_belief + +U_t = \gamma' X_{C,t} + \varepsilon_{C,t}, +\qquad +X_{C,t} = \begin{bmatrix} y_t & U_{t-1} & U_{t-2} & y_{t-1} & y_{t-2} & 1 \end{bmatrix}' . +``` + +在时间 $t$ 到达时,凭借估计值 $\gamma_{t-1}$,政府通过求解菲尔普斯问题来设定通货膨胀的系统性部分,*就好像* $\gamma_{t-1}$ 将永远支配菲利普斯曲线一样: + +```{math} +:label: pl_rule + +y_t = h(\gamma_{t-1}) X_{t-1} + v_{2t}, +\qquad +X_{t-1} = \begin{bmatrix} U_{t-1} & U_{t-2} & y_{t-1} & y_{t-2} & 1 \end{bmatrix}' . +``` + +随后它通过**递归最小二乘法**(RLS)更新其信念: + +```{math} +:label: pl_rls + +\begin{aligned} +\gamma_t &= \gamma_{t-1} + g_t R_{XC,t}^{-1} X_{C,t}\left(U_t - \gamma_{t-1}' X_{C,t}\right), \\ +R_{XC,t} &= R_{XC,t-1} + g_t\left(X_{C,t} X_{C,t}' - R_{XC,t-1}\right), +\end{aligned} +``` + +其中 $\{g_t\}$ 是增益序列。 + +最小二乘法设定 $g_t = 1/t$;常数增益算法设定 $g_t = g_0 > 0$,并对过去的观测打折扣,如果政府怀疑菲利普斯曲线会随时间漂移,这样做是合理的。 + +假设公众知道政府的规则,因此其通货膨胀预测为 $x_t = h(\gamma_{t-1}) X_{t-1}$,即 {eq}`pl_rule` 中的系统性部分。 + +失业率是由 {doc}`phillips_self_confirming` 中实际的菲利普斯曲线在 $\rho_1 = \rho_2 = 0$ 时生成的: + +$$ +U_t = U^* - \theta(y_t - x_t) + v_{1t} = U^* - \theta v_{2t} + v_{1t} . +$$ + +### 带滞后项的菲尔普斯问题 + +给定一个信念 $\gamma$,决策规则 $h(\gamma)$ 求解一个 LQ 控制问题。 + +将所信奉的菲利普斯曲线写为 $U_t = \gamma_0 y_t + c' s_t$,其中 $\gamma_0$ 是当期通货膨胀的系数,$c$ 收集了状态 $s_t = X_{t-1}$ 上的系数。 + +政府最小化 $E\sum_t \delta^t (U_t^2 + y_t^2)$,因此每期损失为 $s_t' (cc') s_t + (\gamma_0^2 + 1) y_t^2 + 2\gamma_0\, y_t\, c' s_t$,状态按 $s_{t+1} = A s_t + B y_t$ 演化,其中: + +$$ +s_{t+1} = \begin{bmatrix} U_t \\ U_{t-1} \\ y_t \\ y_{t-1} \\ 1 \end{bmatrix}, +\qquad +U_t = c' s_t + \gamma_0 y_t . +$$ + +我们使用 `scipy` 的离散代数李卡提方程求解器来求解这个折扣 LQ 问题。 + +```{code-cell} ipython3 +class AdaptivePhillips: + """ + Classical adaptive Phillips curve model: the government re-estimates a + distributed-lag Phillips curve by recursive least squares and each period + acts on the first-period recommendation of the Phelps problem. + """ + + def __init__(self, θ=1.0, U_star=5.0, σ1=0.3, σ2=0.3, δ=0.98): + self.θ, self.U_star, self.σ1, self.σ2, self.δ = θ, U_star, σ1, σ2, δ + + # classical self-confirming belief: U = -θ y + (θ²+1)U* + self.γ_sce = np.array([-θ, 0.0, 0.0, 0.0, 0.0, (θ**2 + 1) * U_star]) + + # self-confirming moment matrix M = E[X_C X_C'] and residual variance + self.M = self._sce_moments() + self.σC2 = σ1**2 # var(U | X_C) at the SCE + + def _sce_moments(self): + "E[X_C X_C'] at the serially-uncorrelated classical SCE." + θ, σ1, σ2 = self.θ, self.σ1, self.σ2 + μU, μy = self.U_star, self.θ * self.U_star + Σ = {('U', 'U'): θ**2 * σ2**2 + σ1**2, ('y', 'y'): σ2**2, + ('U', 'y'): -θ * σ2**2, ('y', 'U'): -θ * σ2**2} + # regressors: (time, type) for [y_t, U_{t-1}, U_{t-2}, y_{t-1}, y_{t-2}, 1] + regs = [(0, 'y'), (1, 'U'), (2, 'U'), (1, 'y'), (2, 'y'), (None, 'c')] + mean = {'U': μU, 'y': μy, 'c': 1.0} + M = np.zeros((6, 6)) + for i, (ti, tyi) in enumerate(regs): + for j, (tj, tyj) in enumerate(regs): + if tyi == 'c' or tyj == 'c' or ti != tj: + M[i, j] = mean[tyi] * mean[tyj] + else: + M[i, j] = Σ[(tyi, tyj)] + mean[tyi] * mean[tyj] + return M + + def phelps_h(self, γ): + "Government decision rule ŷ_t = h(γ)·X_{t-1} for belief γ." + δ, γ0, c = self.δ, γ[0], γ[1:] + R = np.outer(c, c) + Q = np.array([[γ0**2 + 1.0]]) + N = (γ0 * c).reshape(1, -1) + A = np.zeros((5, 5)); B = np.zeros((5, 1)) + A[0, :] = c; B[0, 0] = γ0 # U_t + A[1, 0] = 1.0 # U_{t-1} + B[2, 0] = 1.0 # y_t + A[3, 2] = 1.0 # y_{t-1} + A[4, 4] = 1.0 # constant + sb = np.sqrt(δ) + Ad, Bd = sb * A, sb * B + P = solve_discrete_are(Ad, Bd, R, Q, s=sb * N.T) + F = np.linalg.solve(Q + Bd.T @ P @ Bd, Bd.T @ P @ Ad + N) + return -F.ravel() +``` + +我们使用 {cite}`Sargent1999` 附录 A 中递归最小二乘法的卡尔曼滤波实现。 + +遗忘因子 $\lambda \in (0, 1]$ 映射到增益:$\lambda = 1$ 给出最小二乘法($g_t \to 1/t$),而 $\lambda < 1$ 给出常数增益 $g_0 = 1 - \lambda$。 + +先验被初始化,就好像政府已经观测到 $T$ 期的自我确认均衡数据一样,通过 $P_0 = (\sigma_C^2 / T)\, M^{-1}$;$T$ 越大意味着先验越紧。 + +```{code-cell} ipython3 +def simulate(model, λ, T_prior, n=1000, seed=0): + "Simulate the adaptive system. λ=1 is least squares; λ<1 is constant gain." + rng = np.random.default_rng(seed) + θ, U_star, σ1, σ2 = model.θ, model.U_star, model.σ1, model.σ2 + + γ = model.γ_sce.copy() + P = (model.σC2 / T_prior) * np.linalg.inv(model.M) + R2 = model.σC2 + g0 = 1 - λ + + U1 = U2 = U_star + y1 = y2 = θ * U_star + y_path, U_path, sumweights, constant = (np.empty(n) for _ in range(4)) + + for t in range(n): + h = model.phelps_h(γ) + X_lag = np.array([U1, U2, y1, y2, 1.0]) + yhat = h @ X_lag + + v2, v1 = σ2 * rng.standard_normal(), σ1 * rng.standard_normal() + y = yhat + v2 + U = U_star - θ * (y - yhat) + v1 + + φ = np.array([y, U1, U2, y1, y2, 1.0]) # X_C,t + denom = R2 + φ @ P @ φ + gain = P @ φ / denom + γ = γ + gain * (U - γ @ φ) + R1 = (g0 / (1 - g0)) * P if λ < 1 else 0.0 # constant vs decreasing + P = P - np.outer(P @ φ, φ @ P) / denom + R1 + + y_path[t], U_path[t] = y, U + sumweights[t] = γ[0] + γ[3] + γ[4] # weights on current+lagged y + constant[t] = γ[5] + U2, U1 = U1, U + y2, y1 = y1, y + + return dict(y=y_path, U=U_path, sumweights=sumweights, constant=constant) +``` + +```{code-cell} ipython3 +model = AdaptivePhillips() +h_sce = model.phelps_h(model.γ_sce) +print("decision rule at the self-confirming belief:") +print(f" h(γ_sce) = {np.round(h_sce, 3)} (a constant rule of " + f"{h_sce[-1]:.1f} = Nash inflation)") +``` + +在自我确认信念处,菲尔普斯规则是一个等于纳什通货膨胀率的常数,信念自我复制——适应性系统的静止点正是 {doc}`phillips_self_confirming` 中的自我确认均衡。 + +## 最小二乘法学习收敛 + +我们遵循 {cite}`Sargent1999` 的做法,将真实的数据生成参数设定为 {doc}`phillips_self_confirming` 结尾处的经典示例:$U^* = 5$、$\theta = 1$、$\sigma_1 = \sigma_2 = 0.3$、$\rho_1 = \rho_2 = 0$、$\delta = 0.98$。 + +经典自我确认均衡具有序列不相关的 $(U, y)$,围绕均值 $(5, 5)$ 波动。 + +首先,采用最小二乘法(递减增益)。 + +```{code-cell} ipython3 +ls = simulate(model, λ=1.0, T_prior=5000, n=1000, seed=1) + +fig, ax = plt.subplots(figsize=(9, 4.5)) +ax.plot(ls['y'], lw=0.8) +ax.axhline(5, color='k', ls='--', lw=1, label='self-confirming (Nash)') +ax.axhline(0, color='C2', ls=':', lw=1, label='Ramsey') +ax.set_xlabel('$t$') +ax.set_ylabel('inflation $y_t$') +ax.set_title('Figure 8.1: classical adaptive model, least squares') +ax.legend() +plt.show() +``` + +在最小二乘法下,均值动态占据主导:通货膨胀紧贴着自我确认值 5,模拟结果看起来就像是从自我确认均衡本身抽取出来的一样。 + +我们没有得到什么新结果——政府被困在纳什结果附近。 + +## 常数增益与逃逸动态 + +现在赋予政府一个*常数*增益 $\lambda = 0.975$,使其对过去数据打折扣。 + +```{code-cell} ipython3 +cg = simulate(model, λ=0.975, T_prior=300, n=1000, seed=1) + +fig, ax = plt.subplots(figsize=(9, 4.5)) +ax.plot(cg['y'], lw=0.8) +ax.axhline(5, color='k', ls='--', lw=1, label='self-confirming (Nash)') +ax.axhline(0, color='C2', ls=':', lw=1, label='Ramsey') +ax.set_xlabel('$t$') +ax.set_ylabel('inflation $y_t$') +ax.set_title('Figure 8.2: classical adaptive model, constant gain ' + r'($\lambda = 0.975$)') +ax.legend() +plt.show() +``` + +图景完全不同了。 + +通货膨胀最初接近自我确认值 5,随后几乎跌落至零并停留在那里很长一段时间,然后缓慢地朝 5 迈进,却又再一次被推向零。 + +将系统拉向自我确认均衡的均值动态,遭到了一种反复出现的力量的对抗,这种力量将通货膨胀推向接近拉姆齐结果的水平。 + +关键在于,没有大的冲击触发这些稳定化:它们是常数增益学习动态的一个*内生*特征。 + +```{code-cell} ipython3 +print(f"constant-gain inflation: mean {cg['y'].mean():.2f}, " + f"fraction of periods near Ramsey (y<2): {(cg['y'] < 2).mean():.0%}") +``` + +## 逃逸路径与归纳假设 + +为什么系统会朝拉姆齐方向逃逸,而不是朝其他方向? + +答案是 {doc}`phillips_adaptive` 中的**归纳假设**:当估计出的菲利普斯曲线中当期与滞后通货膨胀的权重之和趋近于零时,菲尔普斯问题会建议政府*降低*通货膨胀。 + +让我们将通货膨胀与这一权重之和一起绘图。 + +```{code-cell} ipython3 +fig, axes = plt.subplots(2, 1, figsize=(9, 7), sharex=True) + +axes[0].plot(cg['y'], lw=0.8) +axes[0].axhline(0, color='C2', ls=':', lw=1) +axes[0].set_ylabel('inflation $y_t$') + +axes[1].plot(cg['sumweights'], lw=0.8, color='C1') +axes[1].axhline(-1, color='k', ls='--', lw=1, label='self-confirming value') +axes[1].axhline(0, color='C3', ls=':', lw=1, label='induction hypothesis') +axes[1].set_xlabel('$t$') +axes[1].set_ylabel('sum of weights on $y$') +axes[1].legend() + +fig.suptitle('Escape route: stabilizations coincide with the sum of ' + 'weights rising toward zero') +plt.tight_layout() +plt.show() +``` + +每一次稳定化都恰好对应着权重之和从其自我确认值 $-1$ 跳向零。 + +当它达到零时,归纳假设(暂时)得到满足,菲尔普斯问题要求近乎拉姆齐水平的通货膨胀,而由此产生的数据短暂地*强化*了归纳假设——从技术意义上说这不是自我确认的,但却是自我强化的。 + +我们可以通过绘制估计出的菲利普斯曲线中常数项与权重之和的联合路径,直接看出这条逃逸路径。 + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(8, 6)) +sc = ax.scatter(cg['constant'], cg['sumweights'], c=np.arange(len(cg['y'])), + cmap='viridis', s=6) +ax.axhline(0, color='C3', ls=':', lw=1.5, label='induction hypothesis') +ax.axhline(-1, color='k', ls='--', lw=1, label='self-confirming value') +ax.set_xlabel('constant in estimated Phillips curve') +ax.set_ylabel('sum of weights on $y$') +ax.legend() +plt.colorbar(sc, label='time $t$') +plt.show() +``` + +信念大部分时间都停留在自我确认值附近(权重之和 $\approx -1$),但反复地朝归纳线(权重之和 $= 0$)猛冲——这正是逃逸路径,沿着这条路径,政府学会了一个索洛-托宾版本的自然率假说并稳定住了通货膨胀。 + +## 与预测误设均衡的关系 + +近乎拉姆齐的这些插曲,让人想起 {doc}`phillips_misspecified` 和 {doc}`phillips_self_confirming` 中带有最优误设预测的均衡。 + +在那里,一个*不含常数项但含单位根*的预测模型能够很好地逼近一个*含有*常数项的真实模型。 + +在这里,一种类似风味的逼近在近乎拉姆齐的插曲中发挥作用:政府估计出的菲利普斯曲线,通过将权重之和推向零,利用归纳假设来逼近一个常数项——只不过被逼近的模型并非固定不变,而是随着政府自身的信念通过菲尔普斯问题反馈回来而不断变化。 + +## 折扣因子的作用 + +朝拉姆齐方向反复出现的稳定化,取决于折扣因子 $\delta$ 是否接近于 1。 + +降低 $\delta$ 会提高低通货膨胀插曲期间观测到的通货膨胀率,这与归纳假设下菲尔普斯问题的运作机制是一致的。 + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(9, 4.5)) +for δ in [0.90, 0.95, 0.98]: + m = AdaptivePhillips(δ=δ) + sim = simulate(m, λ=0.975, T_prior=300, n=1000, seed=1) + ax.plot(sim['y'], lw=0.7, label=rf'$\delta = {δ}$') +ax.axhline(0, color='k', lw=0.5) +ax.set_xlabel('$t$') +ax.set_ylabel('inflation $y_t$') +ax.legend() +ax.set_title('Escapes toward Ramsey deepen as the government becomes patient') +plt.show() +``` + +## 预期效用 + +这个适应性模型是大卫·克雷普斯(David Kreps)所称的**预期效用**(anticipated utility)模型的一个例子 {cite}`Kreps1998`。 + +政府对一个临时误设的模型——一个系数固定的菲利普斯曲线——加以调整,纳入最新的观测数据,并沿途重新优化。 + +在 $t$ 时刻做决策时,它的行为就好像其当前的估计值 $\gamma_{t-1}$ 将永远支配菲利普斯曲线一样,使用的是若 $\gamma$ 真的是时间不变的话本应是最优的同一政策函数 $h(\cdot)$。 + +这是对理性预期的一个微小偏离:日历时间只通过漂移的信念 $\gamma_t$ 进入。 + +与贝叶斯或稳健型决策者不同,一个预期效用型政府忽视了自身逐期模型误设的问题——它并不考虑自己的系数会漂移,即便它们确实在漂移。 + +然而,正如模拟所示,这种对理性的适度偏离已足以对美国通货膨胀的兴衰给出一个丰富的解释,并为"econometric 政策评估的证明"提供支撑。 + +## 结论 + +在很长的时间段内,一个适应性政府学会了产生*优于纳什*的结果。 + +这些结果来自适应性的反复动态:在最小二乘法下将系统拉向自我确认均衡的均值动态继续发挥作用,但在常数增益下,噪声使系统能够反复地逃逸向拉姆齐结果。 + +从一个自我确认均衡出发,适应性算法逐渐使政府将足够的权重放在归纳假设上,以至于偶然的观测结果最终促成了一次稳定化。 + +适应性使得政府的信念成为一种隐藏状态,它给通货膨胀和失业率注入了序列相关性——因此,一个外部预测者若使用随机系数模型,或者进行卢卡斯在其批判 {cite}`lucas1976econometric` 中所指出的那种不断调整,会做得更好。 + +在这个意义上,适应性模型包含了证明 econometric 政策评估的基础——这正是 {doc}`phillips_two_stories` 中两个故事的第二个。 + +## 练习 + +```{exercise-start} +:label: pl_ex1 +``` + +构建**凯恩斯主义**适应性模型,其中政府沿相反方向拟合菲利普斯曲线,将通货膨胀对失业率做回归。 + +回归量是 $X_{K,t} = \begin{bmatrix} U_t & U_{t-1} & U_{t-2} & y_{t-1} & y_{t-2} & 1 \end{bmatrix}'$,政府在 $y_t = \beta' X_{K,t} + \varepsilon_{K,t}$ 中估计 $\beta$,然后在求解菲尔普斯问题之前将其反转为 $\gamma$。 + +不必重新推导所有内容,而是探索*经典*模型对常数增益的敏感性:用 $\lambda \in \{0.99, 0.975, 0.95\}$ 进行模拟,比较通货膨胀朝拉姆齐逃逸的频率。 + +更大的增益(更小的 $\lambda$,对过去更快地打折扣)如何影响逃逸的频率? + +```{exercise-end} +``` + +```{solution-start} pl_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(9, 4.5)) +for λ in [0.99, 0.975, 0.95]: + sim = simulate(model, λ=λ, T_prior=300, n=1000, seed=1) + frac = (sim['y'] < 2).mean() + ax.plot(sim['y'], lw=0.6, + label=rf'$\lambda = {λ}$ (near-Ramsey {frac:.0%})') +ax.axhline(0, color='k', lw=0.5) +ax.set_xlabel('$t$') +ax.set_ylabel('inflation $y_t$') +ax.legend() +plt.show() +``` + +更大的常数增益(更小的 $\lambda$)对过去的数据打折扣更重,从而更有力地阻止了向自我确认均衡的收敛,产生了更频繁——尽管也更嘈杂——的朝拉姆齐结果的逃逸。 + +```{solution-end} +``` + +```{exercise-start} +:label: pl_ex2 +``` + +图 8.1 与图 8.2 的对比取决于增益,但最小二乘法的结果同样取决于先验的紧密程度。 + +对先验紧密度 $T \in \{500, 2000, 5000\}$,模拟最小二乘系统($\lambda = 1$),并报告多个随机种子下的平均通货膨胀率。 + +解释为什么更松的先验(更小的 $T$)会使即便是最小二乘系统也容易发生逃逸。 + +```{exercise-end} +``` + +```{solution-start} pl_ex2 +:class: dropdown +``` + +```{code-cell} ipython3 +for T in [500, 2000, 5000]: + means = [simulate(model, λ=1.0, T_prior=T, n=1000, seed=s)['y'].mean() + for s in range(6)] + print(f"T = {T:>4}: mean inflation across seeds = " + f"{np.round(means, 1)}") +``` + +在更松的先验下,有效增益 $1/(T + t)$ 一开始就更大,因此早期的更新足够大,能够将信念从自我确认均衡上踢出去。 + +由于该均衡只是边际稳定的——均值动态的一个特征值恰好位于快速收敛区域的边界上——系统随后可能朝归纳假设漂移,并被困在接近拉姆齐的水平附近,模拟出常数增益下的逃逸现象。 + +更紧的先验则会使增益始终保持较小,因此最小二乘法能可靠地紧贴自我确认均衡。 + +```{solution-end} +``` \ No newline at end of file From ea231f654ee20cff02607b8e7951c32d39490d52 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:20 +1000 Subject: [PATCH 10/21] Update translation: .translate/state/phillips_learning.md.yml --- .translate/state/phillips_learning.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_learning.md.yml diff --git a/.translate/state/phillips_learning.md.yml b/.translate/state/phillips_learning.md.yml new file mode 100644 index 0000000..e9b1834 --- /dev/null +++ b/.translate/state/phillips_learning.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 11 +tool-version: 0.23.0 From 04223e08e1c5c7876aa2298b6c0975e287487a06 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:21 +1000 Subject: [PATCH 11/21] Update translation: lectures/phillips_misspecified.md --- lectures/phillips_misspecified.md | 419 ++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 lectures/phillips_misspecified.md diff --git a/lectures/phillips_misspecified.md b/lectures/phillips_misspecified.md new file mode 100644 index 0000000..cafacd8 --- /dev/null +++ b/lectures/phillips_misspecified.md @@ -0,0 +1,419 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 最优错误设定信念 + headings: + Overview: 概述 + An experiment in Bray's lab: 布雷实验室中的一个实验 + An experiment in Bray's lab::Constant-gain adaptive expectations: 常增益适应性预期 + An experiment in Bray's lab::The actual law of motion: 实际运动规律 + Optimal misspecification: 最优错误设定 + Comparing the true and forecasting models: 比较真实模型与预测模型 + Comparing the true and forecasting models::Impulse responses: 脉冲响应 + Lessons: 结论 + Exercises: 练习 +--- + +(phillips_misspecified)= +```{raw} jupyter + +``` + +# 最优错误设定信念 + +```{contents} Contents +:depth: 2 +``` + +## 概述 + +本讲座继续研究菲利普斯曲线的权衡关系。 + +内容遵循 {cite}`Sargent1999` 的第 6 章。 + +我们描述了贯穿本系列讲座的三个概念性问题: + +1. 如何构建这样一种均衡——其中代理人共享一个共同的*错误设定的*最小二乘预测模型, +2. 预期如何能够在均衡中贡献出独立的动态,以及 +3. 经典的适应性预期方案如何利用二阶矩来近似一阶矩。 + +为了揭示这些问题,我们暂时搁置菲利普斯曲线,转而使用 {cite}`Bray1982` 关于单一商品价格的简单模型——这是研究有限理性的一个常用工具。 + +我们对布雷的模型加以修改,以说明一种以新的方式融合了理性预期与适应性预期两方面特征的均衡概念,并将在 {doc}`phillips_self_confirming` 中把它应用于菲利普斯曲线。 + +本讲座的重点是**具有最优但错误设定预测的市场均衡**。 + +* *最优*意味着预测方案的自由参数是通过(非线性)最小二乘法选择的。 +* *错误设定*意味着预测模型在函数形式上是错误的。 + +一个显著的特征是:真实模型*取决于*代理人的模型是如何被错误设定的——代理人的信念会影响其行为,而这种行为又塑造了他们随后用于拟合的数据。 + +我们将在频域中展开分析,因此让我们先导入所需的库: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +from scipy.optimize import minimize_scalar +``` + +## 布雷实验室中的一个实验 + +遵循 {cite}`Bray1982`,假设 + +```{math} +:label: pm_bray + +p_t = a + b \, p_{t+1}^e + u_t , +``` + +其中 $u_t$ 是独立同分布的,均值为零,方差为 $\sigma_u^2$,$a > 0$,$b \in (0, 1)$,$p_t$ 是市场价格,$p_{t+1}^e$ 是市场对下一期价格的预期。 + +理性预期均衡满足 $p_{t+1}^e = \frac{a}{1-b}$ 且 $p_t = \frac{a}{1-b} + u_t$。 + +布雷假设 $p_{t+1}^e$ 是过去价格的经验平均值,并证明了当 $0 < b < 1$ 时,这种递减增益方案几乎必然收敛到理性预期值 $\frac{a}{1-b}$。 + +在过渡期间,状态变量 $p_t^e$ 贡献了动态性,使价格呈现序列相关性,但这些动态是暂时性的:在理性预期均衡处,$p_t$ 是一个常数加上一个序列不相关的冲击。 + +### 常增益适应性预期 + +为了让预期能够赋予*持续性*的序列相关性,我们偏离布雷的设定,假设市场具有**常增益**适应性预期: + +```{math} +:label: pm_bray2 + +p_{t+1}^e = C p_t + (1 - C) p_t^e, \qquad |C| < 1 . +``` + +布雷的方案用 $\frac{1}{t}$ 代替 $C$,从而使 $p_{t+1}^e$ 成为一个样本平均值。 + +而固定 $C$ 则会对过去的观测值进行*贴现*,这会阻止收敛到理性预期,也会阻止 $p_{t+1}^e$ 收敛到某个常数。 + +写成分布滞后形式: + +```{math} +:label: pm_bray3 + +p_{t+1}^e = \frac{C}{1 - (1 - C) L} p_t , +``` + +其中 $L$ 是滞后算子。 + +如果价格遵循如下的整合移动平均过程,那么方程 {eq}`pm_bray2` 就是线性最小二乘预测: + +```{math} +:label: pm_brayper + +p_t = p_{t-1} + \epsilon_t - (1 - C)\epsilon_{t-1} , +``` + +因此市场将价格感知为由纯粹的永久性成分和暂时性成分构成。 + +### 实际运动规律 + +将信念 {eq}`pm_bray3` 代入 {eq}`pm_bray`,可以看出:当市场以这种方式进行预测时,其行动使价格的*实际*运动规律变为 + +```{math} +:label: pm_bray4 + +p_t = \frac{a}{1 - b} + \frac{1}{1 - bC} + \left[ \frac{1 - (1 - C)L}{1 - \frac{1 - C}{1 - bC} L} \right] u_t + = \nu + f(L) u_t , +``` + +其中 $\nu = \frac{a}{1-b}$,$f(L)$ 的定义与之匹配。 + +该价格的均值为 $\nu$,谱密度为 + +$$ +F(\omega) = f(e^{i\omega}) f(e^{-i\omega}) \, \sigma_u^2, \qquad \omega \in [-\pi, \pi] . +$$ + +注意 $F$ 通过 $f$ 依赖于 $C$。 + +让我们对真实过程进行编码。 + +```{code-cell} ipython3 +class BrayModel: + """ + Bray's price model with constant-gain adaptive expectations. + + The perceived law of motion is an IMA(1,1) with unit root; to keep its + spectral density well defined we approximate the unit root by a root ρ + slightly below one, following Sargent (1999). + """ + + def __init__(self, a=1.0, b=0.5, σ_u=1.0, ρ=0.995, N=1024): + self.a, self.b, self.σ_u, self.ρ, self.N = a, b, σ_u, ρ, N + self.ν = a / (1 - b) + ω = 2 * np.pi * np.arange(N) / N + self.ω = ω + self.z = np.exp(1j * ω) + + def true_spectrum(self, C): + "Spectral density F(ω) of the actual price process, given belief C." + b, z = self.b, self.z + φ = (1 - C) / (1 - b * C) + scale = 1 / (1 - b * C) + f = scale * (1 - (1 - C) * z) / (1 - φ * z) + return np.abs(f)**2 * self.σ_u**2 + + def approx_spectrum(self, c, σ_ε2=1.0): + "Spectral density G(ω) of the agent's approximating IMA model." + g = (1 - (1 - c) * self.z) / (1 - self.ρ * self.z) + return np.abs(g)**2 * σ_ε2 +``` + +## 最优错误设定 + +关于实际运动规律 {eq}`pm_bray4` 的两个事实促使我们对 $C$ 施加均衡约束: + +1. 假设价格遵循 {eq}`pm_bray4`,真正的线性最小二乘单步预测规则*并不是*像 {eq}`pm_bray2` 那样的几何分布滞后形式。 +2. 即使将预测限定为 {eq}`pm_bray2` 的形式,*最佳的*这类规则也应使 $C$ 求解一个预测误差最小化问题,因此 $C$ 应当是一个结果,而非自由参数。 + +理性预期均衡本可以修正这两个特征。 + +我们遵循 {cite}`Bray1982` 的做法,弱化均衡概念:保留特征 1 不变(代理人保留错误的函数形式),同时修正特征 2(他们在该形式下选择最优参数)。 + +设想将单个个体置于一个市场中,市场中所有其他人("代表性代理人")都使用 $C$,因此价格遵循 {eq}`pm_bray4`。 + +该个体选择 $c$ 以拟合以下形式的最佳模型: + +```{math} +:label: pm_bray6 + +p_t = \frac{1 - (1 - c) L}{1 - L}\epsilon_t = g(L)\epsilon_t , +``` + +方法是最小化单步预测误差方差。 + +由于 $g(L)$ 具有单位根,其直流增益是无穷大的;这正是感知模型如何利用单位根来*拟合常数均值* $\nu$ 的方式。 + +在数值计算中,我们用一个略小于一的根 $\rho$ 来替代单位根。 + +```{prf:definition} 最优估计映射 +:label: pm_bmap + +给定 $C$ 及其导致的价格过程 {eq}`pm_bray4`,个体的最优预测参数 $c = B(C)$ 是 {eq}`pm_bray6` 中 $c$ 的非线性最小二乘估计量,其中数据由 {eq}`pm_bray4` 生成。 +``` + +按照汉森和萨金特 {cite}`HansenSargent1993` 的频域方法,最佳近似 $(c, \sigma_\epsilon^2)$ 使以下式子最小化: + +```{math} +:label: pm_criterion + +A(c, \sigma_\epsilon^2) = \frac{1}{N}\sum_{j=0}^{N-1} +\left\{ \log G(\omega_j, c) + \frac{F(\omega_j)}{G(\omega_j, c)} \right\} ++ \frac{\nu^2}{G(0)} , +``` + +其中 $\omega_j = \frac{2\pi j}{N}$,项 $\frac{\nu^2}{G(0)}$ 使得近似模型利用其接近单位根的特性来拟合均值。 + +将 $\sigma_\epsilon^2$ 集中消去后,剩下一个关于 $c$ 的一维最小化问题。 + +```{prf:definition} 预测错误设定下的均衡 +:label: pm_equilibrium + +预测错误设定下的均衡是一个不动点 $C = B(C)$。 +``` + +在这样一个不动点处,代表性代理人是名副其实的:"代表性"——单个个体的最优参数与所有人都使用的参数相等。 + +```{code-cell} ipython3 +def best_estimate(model, C): + "The best-estimate map c = B(C)." + F = model.true_spectrum(C) + z, ν, N = model.z, model.ν, model.N + + def neg_profile(c): + H = np.abs((1 - (1 - c) * z) / (1 - model.ρ * z))**2 # |g|^2 + σ_ε2 = np.mean(F / H) + ν**2 / H[0] # concentrated + return np.log(σ_ε2) + np.mean(np.log(H)) # profiled criterion + + res = minimize_scalar(neg_profile, bounds=(1e-4, 0.99), method='bounded') + return res.x + +def solve_equilibrium(model, C0=0.3, tol=1e-10, maxit=500): + "Iterate the best-estimate map to a fixed point." + C = C0 + for _ in range(maxit): + C_new = best_estimate(model, C) + if abs(C_new - C) < tol: + break + C = C_new + return C_new +``` + +```{code-cell} ipython3 +bray = BrayModel(a=1.0, b=0.5, σ_u=1.0) +C_star = solve_equilibrium(bray) +print(f"equilibrium belief C = {C_star:.4f}") +``` + +对于这些参数,均衡信念约为 $C \approx 0.08$,这再现了 {cite}`Sargent1999` 第 6 章中报告的数值。 + +我们还来报告一下代理人使用其错误设定模型所导致的*实际*单步预测误差标准差。 + +```{code-cell} ipython3 +def fitted_sigma2(model, C, c): + "Concentrated innovation variance σ_ε^2 of the approximating model." + F = model.true_spectrum(C) + H = np.abs((1 - (1 - c) * model.z) / (1 - model.ρ * model.z))**2 + return np.mean(F / H) + model.ν**2 / H[0] + +c_star = best_estimate(bray, C_star) +σ_bar = np.sqrt(fitted_sigma2(bray, C_star, c_star)) +print(f"actual one-step forecast error std σ̄_ε = {σ_bar:.4f}") +``` + +## 比较真实模型与预测模型 + +对于均衡 $C$,我们绘制真实模型与近似模型的均衡谱密度。 + +```{code-cell} ipython3 +F = bray.true_spectrum(C_star) +σ_ε2 = fitted_sigma2(bray, C_star, c_star) +G = bray.approx_spectrum(c_star, σ_ε2) + +half = bray.N // 2 +fig, ax = plt.subplots(figsize=(8, 5)) +ax.plot(bray.ω[:half], np.log(F[:half]), 'C0', label='true model') +ax.plot(bray.ω[:half], np.log(G[:half]), 'C1--', label='forecasting model') +ax.set_xlabel(r'angular frequency $\omega$') +ax.set_ylabel('log spectral density') +ax.legend() +plt.show() +``` + +在最小化 {eq}`pm_criterion` 的过程中,近似模型利用其接近单位根的特性来拟合均值。 + +低频处两个谱密度之间的巨大差距,反映了近似模型是如何用*二阶*矩的特征(零频率处谱密度的一个尖峰)来拟合*一阶*矩(均值 $\nu$)的。 + +真实谱密度随频率急剧下降——这正是格兰杰所说的"典型谱形状"({cite}`Granger1966`)——这揭示了价格中存在相当大的正序列相关性,因为代理人认为价格受永久性冲击影响的信念,使得冲击具有持续性。 + +### 脉冲响应 + +我们通过向每个移动平均表示输入一个单位冲击,来比较两个模型的脉冲响应函数。 + +```{code-cell} ipython3 +def impulse_response(num_roots, den_roots, T=25): + "IRF of (1 - num L)/(1 - den L): coefficients of the ratio of lag polys." + h = np.empty(T) + h[0] = 1.0 + for k in range(1, T): + h[k] = den_roots * h[k - 1] + h[1:] -= num_roots * h[:-1] # apply the numerator (1 - num L) + return h + +φ = (1 - C_star) / (1 - bray.b * C_star) +scale = 1 / (1 - bray.b * C_star) +irf_true = scale * impulse_response(1 - C_star, φ) # f(L) +irf_approx = impulse_response(1 - c_star, bray.ρ) # g(L) + +fig, ax = plt.subplots(figsize=(8, 5)) +ax.plot(irf_true, 'C0o-', ms=4, label='true model') +ax.plot(irf_approx, 'C1s--', ms=4, label='approximating model') +ax.set_xlabel('lag') +ax.set_ylabel('response') +ax.legend() +plt.show() +``` + +真实模型的脉冲响应确认了价格中的序列相关性。 + +近似模型往往会低估冲击的短期影响,而高估其长期影响:其接近单位根的特性导致了一种不会消退的响应。 + +## 结论 + +这个模型中的代理人具有**有限理性**:*理性*描述的是他们使用最小二乘法这一事实,而*有限*描述的则是他们的模型错误设定。 + +在理性预期下,只有一个模型在起作用。 + +而在有限理性下,则必须至少有两个模型:有限理性代理人所使用的模型,以及真实的模型。 + +这两者相互影响——有限理性代理人利用自己的模型去近似真实模型,而真实模型又反映了代理人的决策——并且两者都不同于理性预期模型。 + +适应性预期模型利用单位根来模仿常数这一独特方式,预示了在 {doc}`phillips_self_confirming` 中发展的菲利普斯曲线模型的一个版本,该版本有助于为计量经济学政策评估正名。 + +这个技巧——用单位根来近似常数——同样是 {doc}`phillips_learning` 和 {doc}`phillips_escaping_nash` 中*逃逸动态*的引擎,其中一个正在学习的政府所估计的菲利普斯曲线会逐渐趋向归纳假设,并在相信该假设后,将通货膨胀率下调至拉姆齐水平。 + +## 练习 + +```{exercise-start} +:label: pmis_ex1 +``` + +均衡信念 $C$ 取决于 {eq}`pm_bray` 中的反馈参数 $b$。 + +在保持 $a = 1$ 和 $\sigma_u = 1$ 固定的情况下,计算并绘制均衡 $C$ 作为 $b$ 的函数,其中 $b$ 取自网格 $b \in \{0.1, 0.2, \ldots, 0.8\}$。 + +更强的预期反馈(更大的 $b$)如何影响对过去数据进行贴现的均衡程度? + +```{exercise-end} +``` + +```{solution-start} pmis_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +b_grid = np.arange(0.1, 0.85, 0.1) +C_of_b = [solve_equilibrium(BrayModel(a=1.0, b=b, σ_u=1.0)) for b in b_grid] + +fig, ax = plt.subplots(figsize=(8, 4.5)) +ax.plot(b_grid, C_of_b, 'o-') +ax.set_xlabel('feedback parameter $b$') +ax.set_ylabel('equilibrium belief $C$') +plt.show() +``` + +更强的反馈会提高均衡增益 $C$:代理人会对近期观测值赋予更大的权重,因此他们所产生的价格过程比原本会呈现的持续性更弱。 + +```{solution-end} +``` + +```{exercise-start} +:label: pmis_ex2 +``` + +通过将最优估计映射 $c = B(C)$ 与 45 度线一起绘图,并标出不动点,来验证该均衡确实是一个真正的不动点。 + +```{exercise-end} +``` + +```{solution-start} pmis_ex2 +:class: dropdown +``` + +```{code-cell} ipython3 +C_grid = np.linspace(0.02, 0.4, 25) +B_vals = [best_estimate(bray, C) for C in C_grid] + +fig, ax = plt.subplots(figsize=(6, 6)) +ax.plot(C_grid, B_vals, 'C0', label='$B(C)$') +ax.plot(C_grid, C_grid, 'k--', lw=1, label='45 degrees') +ax.plot(C_star, C_star, 'ko') +ax.annotate('equilibrium', (C_star, C_star), + (C_star + 0.05, C_star - 0.03)) +ax.set_xlabel('$C$') +ax.set_ylabel('$B(C)$') +ax.legend() +plt.show() +``` + +最优估计映射在均衡信念处与 45 度线相交,证实了 $C = B(C)$。 + +```{solution-end} +``` \ No newline at end of file From 07f8b38e6d7fdfa8f0d610c5964e20168e655654 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:21 +1000 Subject: [PATCH 12/21] Update translation: .translate/state/phillips_misspecified.md.yml --- .translate/state/phillips_misspecified.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_misspecified.md.yml diff --git a/.translate/state/phillips_misspecified.md.yml b/.translate/state/phillips_misspecified.md.yml new file mode 100644 index 0000000..54c8555 --- /dev/null +++ b/.translate/state/phillips_misspecified.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 6 +tool-version: 0.23.0 From 5108feee0f97defb91174ee79c8195546cbec7c3 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:22 +1000 Subject: [PATCH 13/21] Update translation: lectures/phillips_priors.md --- lectures/phillips_priors.md | 617 ++++++++++++++++++++++++++++++++++++ 1 file changed, 617 insertions(+) create mode 100644 lectures/phillips_priors.md diff --git a/lectures/phillips_priors.md b/lectures/phillips_priors.md new file mode 100644 index 0000000..109d460 --- /dev/null +++ b/lectures/phillips_priors.md @@ -0,0 +1,617 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 先验、逃逸与学习循环 + headings: + Overview: 概述 + The static model: 静态模型 + The self-confirming equilibrium: 自证均衡 + Drifting beliefs and the Kalman filter: 漂移信念与卡尔曼滤波 + Mean dynamics and E-stability: 均值动态与 E-稳定性 + Learning cycles: 学习循环 + Escape dynamics and the direction of escape: 逃逸动态与逃逸方向 + Sims's nonconvergence: 西姆斯的不收敛现象 + Conclusion: 结论 + Conclusion::Are the estimated beliefs realistic?: 估计出的信念是否现实? + Exercises: 练习 +--- + +(phillips_priors)= +```{raw} jupyter + +``` + +# 先验、逃逸与学习循环 + +```{contents} Contents +:depth: 2 +``` + +## 概述 + +> 波旁家族什么都记得,却什么也没学到。 +> +> —— 夏尔·莫里斯·德·塔列朗 + +本讲座是 {doc}`phillips_learning` 的续篇。 + +它遵循 {cite}`SargentWilliams2005` 的方法,该文献推广了 {cite}`Sargent1999` 第 8 章以及 {cite}`ChoWilliamsSargent2002`(CWS)的适应性模型,我们在 {doc}`phillips_escaping_nash` 中推导过后者的逃逸动态。 + +在 {doc}`phillips_learning` 中,政府通过递归最小二乘法估计其菲利普斯曲线。 + +那是一种非常特定的学习方式。 + +最小二乘学习者的行为就好像它相信其模型的系数遵循一个特定的随机游走——具有特定新息协方差矩阵的随机游走。 + +在这里,我们让政府对其系数如何漂移持有*任意*先验信念,用协方差矩阵 $V$ 来编码,并考察这种先验的形状如何影响驱动模型的两种力量: + +* **均值动态**,它将政府的信念拉向自证(纳什)均衡;以及 +* **逃逸动态**,它偶尔将信念推离自证均衡,转向低通胀的拉姆齐结果。 + +我们将发现三件事。 + +1. 某些先验会使自证均衡变得*不稳定*,从而使均值动态本身产生反复出现的反通胀——这是一种由霍普夫分岔产生的**学习循环**,而非罕见的随机逃逸。 +2. 先验决定了逃逸的*方向*和*速度*;但在每种情况下,逃逸的目的地都是拉姆齐结果。 +3. 先验解释了一个由来已久的谜题:为什么西姆斯和钟的模拟会逃离纳什通胀并*永远*停留在拉姆齐附近,而 {cite}`Sargent1999` 和 CWS 的模拟却只是逃逸后又被拉回。 + +在整个讲座中,我们使用 {doc}`phillips_escaping_nash` 中可解析处理的**静态**模型,在该模型中政府对失业率关于通胀和常数进行简单回归。 + +让我们从导入开始: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +from scipy.linalg import sqrtm +from scipy.integrate import solve_ivp +``` + +## 静态模型 + +真实经济是 {cite}`KydlandPrescott1977` 自然率模型的一个版本: + +```{math} +:label: pp_truth + +\begin{aligned} +U_n &= u - (\pi_n - \hat x_n) + \sigma_1 W_{1n}, \qquad u > 0, \\ +\pi_n &= x_n + \sigma_2 W_{2n}, \\ +\hat x_n &= x_n, +\end{aligned} +``` + +其中 $U_n$ 是失业率,$\pi_n$ 是通货膨胀率,$x_n$ 是政府设定的通胀的系统性部分,$\hat x_n$ 是公众的(理性)预测,$W_n = (W_{1n}, W_{2n})'$ 是独立同分布的标准高斯噪声。 + +由于 $\pi_n - \hat x_n = \sigma_2 W_{2n}$,真实的失业率是 $U_n = u - \sigma_2 W_{2n} + \sigma_1 W_{1n}$——无论系统性政策如何,它都围绕自然率 $u$ 波动。 + +政府并不知道这一点。 + +在**静态模型**中,政府通过对失业率关于当前通胀和常数进行回归来拟合一个非预期性的菲利普斯曲线, + +```{math} +:label: pp_belief + +U_n = a + b\, \pi_n + \eta_n , +``` + +信念向量为 $\gamma = (a, b)$(截距和斜率),并将 $\eta_n$ 视为外生冲击。 + +在相信 {eq}`pp_belief` 的前提下,政府求解菲尔普斯问题——最小化 $\hat E \sum_n \delta^n (U_n^2 + \pi_n^2)$——其静态最优反应将通胀设定为常数 + +```{math} +:label: pp_bestresp + +x(\gamma) = -\frac{a\, b}{1 + b^2} . +``` + +```{code-cell} ipython3 +class StaticPhillips: + "The static Sargent-Williams model: government regresses U on (1, π)." + + def __init__(self, u=5.0, σ1=0.3, σ2=0.3): + self.u, self.σ1, self.σ2 = u, σ1, σ2 + self.σ = σ1 # govt regression error std = σ1 + + def x(self, γ): + "Government best response (systematic inflation) given beliefs γ." + a, b = γ + return -a * b / (1 + b**2) + + def M(self, γ): + "Second moment matrix E[ΦΦ'] of regressors Φ = (1, π), given γ." + x = self.x(γ) + return np.array([[1.0, x], [x, x**2 + self.σ2**2]]) + + def g_bar(self, γ): + "Least squares moment E[Φ(U - Φ'γ)] under the data γ generates." + u, σ2 = self.u, self.σ2 + x = self.x(γ) + E_ΦU = np.array([u, x * u - σ2**2]) + return E_ΦU - self.M(γ) @ γ +``` + +有三个信念向量值得命名。 + +* **信念 1(纳什):** $b = -1$,截距使政府设定 $x = u$。这是 {cite}`KydlandPrescott1977` 的时间一致性结果。 +* **信念 2(拉姆齐):** $b = 0$,因此政府认为*不存在*权衡,设定 $x = 0$。 +* **信念 3(归纳):** 在动态版本中,当前和滞后通胀的系数之和为零,这对于一个有耐心的政府来说也会使通胀趋向 $0$。 + +## 自证均衡 + +自证均衡是一个能自我再生的信念 $\bar\gamma$:当政府依据 $\bar\gamma$ 行事时所产生的数据,使得总体回归系数恰好等于 $\bar\gamma$,即 $\bar g(\bar\gamma) = 0$。 + +对于静态模型,这可以手工轻松求解。 + +斜率为 $b = \operatorname{cov}(U, \pi)/\operatorname{var}(\pi) = -\sigma_2^2/\sigma_2^2 = -1$,均值匹配给出截距 $a = u + x(\bar\gamma)$。 + +将最优反应 {eq}`pp_bestresp`($b = -1$)代入,得到 $x = a/2$,因此 $a = u + a/2$,即 $a = 2u$。 + +```{code-cell} ipython3 +model = StaticPhillips(u=5.0, σ1=0.3, σ2=0.3) +γ_sce = np.array([2 * model.u, -1.0]) + +print(f"self-confirming beliefs γ = {γ_sce} (intercept 2u, slope -1)") +print(f"self-confirming inflation x = {model.x(γ_sce):.2f} (= Nash = u)") +print(f"check g_bar(γ_sce) = {model.g_bar(γ_sce)}") +``` + +自证均衡的通胀率等于纳什(时间一致性)结果 $u = 5$,即使政府的模型是设定错误的。 + +政府的非预期性菲利普斯曲线在均衡路径*上*与真实模型在观测上等价,但在均衡路径*之外*是错误的——而这正是它的适应性行为反复试探的地方。 + +## 漂移信念与卡尔曼滤波 + +现在我们让政府变得具有适应性。 + +依照 {cite}`SargentWilliams2005`,政府相信其菲利普斯曲线的系数以随机游走的形式*漂移*, + +```{math} +:label: pp_drift + +\alpha_n = \alpha_{n-1} + \Lambda_n, +\qquad +\operatorname{cov}(\Lambda_n) = V , +``` + +它通过卡尔曼滤波形成其估计值 $\gamma_n = \hat\alpha_{n \mid n-1}$。 + +协方差矩阵 $V$ 是政府对**参数漂移的先验信念**——这是我们要放开的对象。 + +对于回归量 $\Phi_n = (1, \pi_n)'$,卡尔曼滤波的大样本近似(见 {cite}`BenvenisteMetivierPriouret1990`)为 + +```{math} +:label: pp_kalman + +\begin{aligned} +\gamma_{n+1} &= \gamma_n + P_n \Phi_n\left(U_n - \Phi_n' \gamma_n\right), \\ +P_{n+1} &= P_n - P_n M(\gamma_n) P_n + \sigma^{-2} V , +\end{aligned} +``` + +其中 $\sigma^2$ 是政府赋予其回归误差 $\eta_n$ 的方差。 + +对于固定的 $\gamma$,矩阵 $P_n$ 收敛到代数里卡蒂方程的解 + +```{math} +:label: pp_riccati + +- P M(\gamma) P + \sigma^{-2} V = 0 . +``` + +与 {doc}`phillips_learning` 的联系是精确的。 + +固定增益递归最小二乘法是这样一种特殊情形:政府的先验为 $V = V^* \equiv \epsilon^2 \sigma^2 M(\bar\gamma)^{-1}$ 且 $\sigma = \sigma_1$;此时 {eq}`pp_riccati` 给出 $P = \epsilon M(\bar\gamma)^{-1}$,而 {eq}`pp_kalman` 简化为上一讲中增益为 $\epsilon$ 的递归最小二乘算法。 + +```{code-cell} ipython3 +def solve_riccati(V, M, σ): + "Symmetric positive-definite P solving P M P = σ^{-2} V." + W = V / σ**2 + Mh = sqrtm(M).real + Mh_inv = np.linalg.inv(Mh) + return Mh_inv @ sqrtm(Mh @ W @ Mh).real @ Mh_inv + +M_sce = model.M(γ_sce) +V_star = model.σ**2 * np.linalg.inv(M_sce) # the RLS prior (ε = 1) +P_star = solve_riccati(V_star, M_sce, model.σ) + +print("RLS prior gives P = M^{-1}?", np.allclose(P_star, np.linalg.inv(M_sce))) +``` + +## 均值动态与 E-稳定性 + +与 {doc}`phillips_learning` 一样,信念由均值动态所组织——现在是关于 $(\gamma, P)$ 的*联合*常微分方程, + +```{math} +:label: pp_ode + +\dot\gamma = P\, \bar g(\gamma), +\qquad +\dot P = \sigma^{-2} V - P M(\gamma) P . +``` + +{eq}`pp_ode` 的一个静止点满足 $\bar g(\gamma) = 0$ 且 $P = $ 里卡蒂解——即一个自证均衡。 + +局部稳定性取决于自证均衡处 $\bar g$ 的雅可比矩阵。 + +对于静态模型,这可以求得闭式解, + +```{math} +:label: pp_jacobian + +\frac{\partial \bar g}{\partial \gamma}(\bar\gamma) += - \begin{bmatrix} \tfrac12 & u \\[1mm] \tfrac12 u & u^2 + \sigma_2^2 \end{bmatrix} . +``` + +```{code-cell} ipython3 +def jacobian(model, γ, h=1e-6): + "Numerical Jacobian of g_bar at γ." + J = np.zeros((2, 2)) + for j in range(2): + gp, gm = γ.copy(), γ.copy() + gp[j] += h; gm[j] -= h + J[:, j] = (model.g_bar(gp) - model.g_bar(gm)) / (2 * h) + return J + +J = jacobian(model, γ_sce) +print("∂g/∂γ at SCE =\n", J.round(3)) +``` + +在递归最小二乘法下,{eq}`pp_ode` 中的 $P$ 分块会解耦,稳定性由 $M^{-1}\,\partial\bar g/\partial\gamma$ 的特征值决定——这就是 {cite}`EvansHonkapohja2001` 提出的经典 **E-稳定性**条件。 + +```{code-cell} ipython3 +eig_rls = np.linalg.eigvals(np.linalg.inv(M_sce) @ J) +print(f"E-stability eigenvalues (RLS): {eig_rls.round(3)}") +print("both negative ⇒ the SCE is E-stable, and least squares converges to Nash") +``` + +两个特征值均为负——其中一个恰好等于 $-\tfrac12$,这正是 {doc}`phillips_learning` 中出现过的临界值。 + +因此,在最小二乘法下,信念收敛到纳什自证均衡。 + +但这一化简依赖于特殊的递归最小二乘先验。 + +在*一般*先验 $V$ 下,$P$ 分块**不会**解耦,稳定性反而由 $\bar P\, \partial\bar g/\partial\gamma$ 的特征值决定——其中 $\bar P$ 是该先验下的里卡蒂解。 + +关于参数漂移的先验信念现在会影响自证均衡是否稳定。 + +## 学习循环 + +这里是论文最引人注目的结果:某些先验会使自证均衡变得*不稳定*,并通过霍普夫分岔产生一个**稳定的极限循环**。 + +我们通过*收紧政府对斜率系数的先验*来说明这一点,从递归最小二乘先验 $V^*$ 出发,用因子 $\lambda \in [0, 1]$ 收缩与斜率相关的项: + +```{math} +:label: pp_Vlambda + +V(\lambda) = \begin{bmatrix} V^*_{11} & \sqrt\lambda\, V^*_{12} \\ \sqrt\lambda\, V^*_{12} & \lambda\, V^*_{22} \end{bmatrix} . +``` + +对每个 $\lambda$,我们求解里卡蒂方程并观察 $\bar P(\lambda)\, \partial\bar g/\partial\gamma$ 特征值中最大实部:当该值为正时,自证均衡是不稳定的。 + +```{code-cell} ipython3 +def V_tighten_slope(λ, V_star): + V = V_star.copy() + V[0, 1] = V[1, 0] = np.sqrt(λ) * V_star[0, 1] + V[1, 1] = λ * V_star[1, 1] + return V + +ε = 0.05 # gain (sets the timescale) +λ_grid = np.linspace(0.01, 0.999, 200) +max_re = [] +for λ in λ_grid: + V = ε**2 * V_tighten_slope(λ, V_star) + P = solve_riccati(V, M_sce, model.σ) + max_re.append(np.linalg.eigvals(P @ J).real.max()) + +fig, ax = plt.subplots(figsize=(8, 4.5)) +ax.plot(λ_grid, max_re) +ax.axhline(0, color='k', lw=0.8) +ax.set_xlabel(r'prior-tightening parameter $\lambda$') +ax.set_ylabel('max real part of eigenvalue') +ax.set_title(r'Figure 4: stability of the SCE as the slope prior tightens') +plt.show() +``` + +在一个中间范围的 $\lambda$ 内,最大实部变为*正值*:自证均衡失去稳定性。 + +根据霍普夫分岔定理(见 {cite}`Perko1996`),当实部越过零时,会分岔出一个唯一的稳定极限循环——{cite}`Bullard1994` 称之为*学习均衡*。 + +让我们在 $\lambda = 0.7$(充分位于不稳定范围内)处对回归系数的均值动态进行积分,将 $P$ 固定在其里卡蒂值处,并描绘该循环。 + +```{code-cell} ipython3 +λ = 0.7 +V = ε**2 * V_tighten_slope(λ, V_star) +P_bar = solve_riccati(V, M_sce, model.σ) + +def coeff_ode(t, γ): + return P_bar @ model.g_bar(γ) + +sol = solve_ivp(coeff_ode, [0, 2500], γ_sce + np.array([0.3, 0.05]), + max_step=1.0, rtol=1e-9, atol=1e-11, dense_output=True) +a_path, b_path = sol.y +x_path = -a_path * b_path / (1 + b_path**2) + +# isolate one mature cycle for the phase plot +mask = sol.t > sol.t[-1] - 800 +``` + +```{code-cell} ipython3 +fig, axes = plt.subplots(1, 2, figsize=(12, 5)) + +axes[0].plot(sol.t[mask], a_path[mask], label='intercept') +axes[0].plot(sol.t[mask], b_path[mask], label='slope') +axes[0].set_xlabel('time') +axes[0].set_ylabel('coefficient') +axes[0].set_title('Figure 5a: coefficients cycle') +axes[0].legend() + +axes[1].plot(a_path[mask], b_path[mask]) +axes[1].plot(*γ_sce, 'kx', ms=10, label='SCE') +axes[1].set_xlabel('intercept') +axes[1].set_ylabel('slope') +axes[1].set_title('Figure 5b: the limit cycle') +axes[1].legend() + +plt.tight_layout() +plt.show() +``` + +信念稳定在围绕自证均衡的一个闭合轨道上。 + +由于通胀通过最优反应 {eq}`pp_bestresp` 是系数的函数,信念中的循环表现为通胀在纳什和拉姆齐结果之间振荡的循环。 + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(9, 4.5)) +ax.plot(sol.t[mask], x_path[mask]) +ax.axhline(model.u, color='k', ls='--', lw=1, label='Nash') +ax.axhline(0, color='C2', ls=':', lw=1, label='Ramsey') +ax.set_xlabel('time') +ax.set_ylabel('inflation $x$') +ax.set_title('Figure 6: inflation oscillates between Nash and Ramsey along the cycle') +ax.legend() +plt.show() +``` + +这与 {doc}`phillips_learning` 中的逃逸在性质上不同。 + +在那里,反通胀是*罕见*事件,由不太可能出现的冲击序列驱动;在这些事件之间,系统停留在纳什状态。 + +而这里,反通胀是时间序列的一个*典型*特征,由均值动态本身产生——一种即使增益缩小到零也依然持续存在的确定性循环。 + +## 逃逸动态与逃逸方向 + +对于使自证均衡保持稳定的先验,反通胀又变回罕见的逃逸事件,与 {doc}`phillips_learning` 中的情形完全一致。 + +大偏差理论(在 {doc}`phillips_learning` 的入门材料中展开,并通过 {cite}`Williams2019` 应用于此)将最可能的逃逸刻画为一个控制问题的解:施加代价最小的信念扰动,将信念推离 $\bar\gamma$ 固定距离。 + +*瞬时*逃逸方向有一个非常简洁的刻画:它是信念-新息协方差 $Q(\bar\gamma, \bar P) = \hat V$——即先验本身——的最大特征值对应的特征向量。 + +```{code-cell} ipython3 +w, vecs = np.linalg.eigh(V_star) # baseline prior V* +v_escape = vecs[:, np.argmax(w)] +v_escape = v_escape / np.linalg.norm(v_escape) + +# scale the escape so the slope moves from -1 up to 0 +t_star = 1.0 / v_escape[1] +terminal = γ_sce + t_star * v_escape + +print(f"escape direction ≈ {v_escape.round(3)} (∝ [-u, 1])") +print(f"terminal beliefs ≈ {terminal.round(2)} (Belief 2 = [u, 0] = Ramsey)") +``` + +对于基准先验,逃逸方向正比于 $(-u, 1)$,它使信念从纳什 $(2u, -1)$ 移向 $(u, 0)$——即支持拉姆齐结果的信念 2。 + +因此,逃逸一旦发生,就是朝着零通胀方向的运动。 + +不同的先验会改变逃逸的*路径*并改变逃逸的*速率*——收紧斜率先验甚至可能彻底使均衡失稳(如上面的循环所示),而收紧截距先验则会加快逃逸速度——但目的地始终是拉姆齐结果。 + +## 西姆斯的不收敛现象 + +我们现在可以解决 {doc}`phillips_two_stories` 中提到的一个谜题。 + +{cite}`Sims1988` 和 {cite}`Chung1990` 的模拟从纳什自证结果开始,逃逸到低通胀,然后似乎*无限期地*停留在那里。 + +而 {cite}`Sargent1999` 和 CWS 的模拟则是逃逸后被一再拉回。 + +{cite}`SargentWilliams2005` 将这一差异归因于一个单一的建模选择:政府是否对其回归误差赋予了*正确*的方差。 + +当 $\sigma = \sigma_1$ 时——如在自证均衡中那样,此时回归 {eq}`pp_belief` 与真实模型 {eq}`pp_truth` 一致——政府能正确地分解它所观察到的变异。 + +西姆斯则使用了 $\sigma \neq \sigma_1$(且没有缩小增益),这*错误地分配*了观测到的变异,从而产生了长期、也许是永久性的偏离自证均衡的情形。 + +让我们在两种设定下模拟静态模型。 + +```{code-cell} ipython3 +def simulate(model, σ_govt, ε, λ=1.0, T=3000, seed=0): + "Static Kalman-filter learning; σ_govt is the government's assumed error std." + rng = np.random.default_rng(seed) + u, σ1, σ2 = model.u, model.σ1, model.σ2 + + V = ε**2 * V_tighten_slope(λ, V_star) + γ = γ_sce.copy() + P = ε * np.linalg.inv(M_sce) + infl = np.empty(T) + + for n in range(T): + x = model.x(γ) + w1, w2 = rng.standard_normal(2) + π = x + σ2 * w2 + U = u - σ2 * w2 + σ1 * w1 # truth uses σ1 + Φ = np.array([1.0, π]) + denom = σ_govt**2 + Φ @ P @ Φ + γ = γ + (P @ Φ) / denom * (U - Φ @ γ) + P = P - np.outer(P @ Φ, Φ @ P) / denom + V / σ_govt**2 + infl[n] = π + return infl + +x_base = simulate(model, σ_govt=model.σ1, ε=0.05, seed=1) # σ = σ1 +x_sims = simulate(model, σ_govt=0.1, ε=0.20, seed=1) # σ ≠ σ1 (Sims-like) + +print(f"σ = σ1 : mean inflation {x_base.mean():.2f}, " + f"fraction near Ramsey {(x_base < 2).mean():.0%}") +print(f"σ ≠ σ1 : mean inflation {x_sims.mean():.2f}, " + f"fraction near Ramsey {(x_sims < 2).mean():.0%}") +``` + +```{code-cell} ipython3 +fig, axes = plt.subplots(2, 1, figsize=(9, 7), sharex=True) +axes[0].plot(x_base, lw=0.6) +axes[0].axhline(model.u, color='k', ls='--', lw=1) +axes[0].set_ylabel('inflation') +axes[0].set_title(r'$\sigma = \sigma_1$: recurrent escapes, pulled back to Nash') + +axes[1].plot(x_sims, lw=0.6, color='C1') +axes[1].axhline(model.u, color='k', ls='--', lw=1) +axes[1].set_xlabel('$n$') +axes[1].set_ylabel('inflation') +axes[1].set_title(r'$\sigma \neq \sigma_1$ (Sims): prolonged spells near Ramsey') + +plt.tight_layout() +plt.show() +``` + +在误差方差设定正确的情况下,均值动态会重新发挥作用,通胀被反复拉回纳什水平附近。 + +而在西姆斯的错误分配下,这种拉力被削弱,经济则长期停留在拉姆齐结果附近——政府的行为就好像它已经*永久*学会了一个足够好的自然率假说版本。 + +正如 {cite}`SargentWilliams2005` 所言,这种差异可以用两种等价的方式来理解:要么是西姆斯允许了过多的参数漂移以至于无法收敛,要么是他没有让政府对其回归误差归因足够多的变异。 + +## 结论 + +自由参数是危险的,正如阿瑟·戈德伯格和罗伯特·卢卡斯所警告的那样。 + +本讲座中的政府在其信念漂移的协方差矩阵 $V$ 中携带着自由参数。 + +但这些参数换来了一些东西:后续的实证研究 {cite}`SargentWilliamsZha2006` 表明,根据战后美国数据估计 $V$,可以让该模型反推出一系列政策制定者关于菲利普斯曲线不断演变的主观模型,从而使美国通胀实际的兴衰历程得到合理解释——这正是 {doc}`phillips_two_stories` 中平反故事的量化版本。 + +关于系数漂移的协方差本身随时间变化的相关证据见 {cite}`CogleySargent2005`。 + +### 估计出的信念是否现实? + +那一实证上的成功也伴随着一个挑战,而这个挑战其实是关于*先验*本身的挑战。 + +为了拟合数据,{cite}`SargentWilliamsZha2006` 估计出一个很大的漂移协方差 $V$——这意味着一个对新数据如此开放的政府,其对货币传导机制的信念每月都会大幅摇摆。 + +{cite}`Primiceri2006`、克里斯托弗·西姆斯,以及坦率地说,{cite}`Sargent2008` 本人在其学会主席致辞中,都提出了异议:这种剧烈波动的信念是*不现实的*——由此推算出的政府对失业率的预测很差,持有的观点也是任何真实的中央银行都不会持有的。 + +{cite}`CarboniEllison2009` 通过用美联储实际产生的数据来约束先验,回应了这一异议。 + +他们在要求模型的信念必须能再现美联储《绿皮书》中公布的失业率预测这一约束下重新估计了模型——这为学习模型施加了一种理性预期计量经济学中常见的跨方程约束。 + +施加这一约束后,估计出的 $V$ 缩小了几个数量级,消除了剧烈的信念波动,但低频的"征服"故事依然完好无损:一种*稳定*演化的美联储信念,仍然能够解释通胀的兴衰。 + +事实证明,那些剧烈波动的信念,不过是在对 {cite}`Sargent1999` 从未打算解释的高频波动进行过拟合而已。 + +本讲座的寓意很直接:先验 $V$ 并非一个可以自由最大化的讨厌参数——它是一个经济对象,用关于政策制定者实际信念的独立证据将其确定下来,才使平反故事变得可信。 + +更广泛的信息是:一个适应性政府*如何*学习——它带入自身信念漂移中的先验——并非一个技术细节。 + +它决定了经济是收敛到纳什状态、在纳什和拉姆齐之间循环,还是逃逸到拉姆齐状态并停留在那里。 + +最后一讲,{doc}`phillips_lost_conquest`,将同样的工具——固定增益学习、预期效用菲尔普斯问题以及自证均衡——带入当下,用以解释美联储对 2020 年代通胀的应对。 + +## 练习 + +```{exercise-start} +:label: ppr_ex1 +``` + +上文的学习循环收紧了对*斜率*系数的先验。 + +改为收紧对*截距*系数的先验——使用 + +$$ +V(\lambda) = \begin{bmatrix} \lambda\, V^*_{11} & \sqrt\lambda\, V^*_{12} \\ \sqrt\lambda\, V^*_{12} & V^*_{22} \end{bmatrix} +$$ + +——这*不会*使自证均衡失稳。 + +请通过绘制该截距收紧族中 $\bar P(\lambda)\,\partial\bar g/\partial\gamma$ 特征值最大实部关于 $\lambda$ 的图像来验证这一点,并确认其始终为负。 + +```{exercise-end} +``` + +```{solution-start} ppr_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +def V_tighten_intercept(λ, V_star): + V = V_star.copy() + V[0, 0] = λ * V_star[0, 0] + V[0, 1] = V[1, 0] = np.sqrt(λ) * V_star[0, 1] + return V + +max_re_int = [] +for λ in λ_grid: + V = ε**2 * V_tighten_intercept(λ, V_star) + P = solve_riccati(V, M_sce, model.σ) + max_re_int.append(np.linalg.eigvals(P @ J).real.max()) + +fig, ax = plt.subplots(figsize=(8, 4.5)) +ax.plot(λ_grid, max_re_int, label='tighten intercept') +ax.plot(λ_grid, max_re, ls='--', label='tighten slope (for comparison)') +ax.axhline(0, color='k', lw=0.8) +ax.set_xlabel(r'$\lambda$') +ax.set_ylabel('max real part of eigenvalue') +ax.legend() +plt.show() +``` + +收紧截距先验使最大实部对于所有 $\lambda$ 都保持为负:自证均衡保持稳定,因此不存在学习循环。 + +正如 {cite}`SargentWilliams2005` 所示,这种先验确实仍会改变*逃逸*动态——它会加快逃逸——但不会推翻均值动态。 + +```{solution-end} +``` + +```{exercise-start} +:label: ppr_ex2 +``` + +瞬时逃逸方向是先验协方差 $\hat V$ 的主特征向量。 + +请确认该方向对先验的整体*尺度*是稳健的,但对其*形状*是敏感的。 + +分别计算基准先验 $V^*$ 和斜率收紧先验 $V(\lambda = 0.5)$ 对应的逃逸方向(以及所隐含的终端信念),并比较二者将政府的信念分别送往何处。 + +```{exercise-end} +``` + +```{solution-start} ppr_ex2 +:class: dropdown +``` + +```{code-cell} ipython3 +def escape_terminal(V): + w, vecs = np.linalg.eigh(V) + v = vecs[:, np.argmax(w)] + v = v / np.linalg.norm(v) + if v[1] < 0: # orient toward increasing slope + v = -v + return γ_sce + (1.0 / v[1]) * v, v + +for name, V in [("baseline V*", V_star), + ("slope-tightened V(0.5)", V_tighten_slope(0.5, V_star))]: + term, v = escape_terminal(V) + print(f"{name:24s}: direction {v.round(3)}, terminal {term.round(2)}") +``` + +两种先验都将信念导向斜率为 $0$ 的终端点——即拉姆齐信念——但沿着不同的方向,并到达略有不同的截距。 + +目的地(零通胀)是一个稳健的特征;而*路径*则取决于先验的形状。 + +```{solution-end} +``` \ No newline at end of file From 8782756218d32567903e45507283da68c6796eab Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:23 +1000 Subject: [PATCH 14/21] Update translation: .translate/state/phillips_priors.md.yml --- .translate/state/phillips_priors.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_priors.md.yml diff --git a/.translate/state/phillips_priors.md.yml b/.translate/state/phillips_priors.md.yml new file mode 100644 index 0000000..e9254c1 --- /dev/null +++ b/.translate/state/phillips_priors.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 10 +tool-version: 0.23.0 From 459612deb09f6cf3cda705e1ec5dc36a67babe8a Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:24 +1000 Subject: [PATCH 15/21] Update translation: lectures/phillips_self_confirming.md --- lectures/phillips_self_confirming.md | 570 +++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 lectures/phillips_self_confirming.md diff --git a/lectures/phillips_self_confirming.md b/lectures/phillips_self_confirming.md new file mode 100644 index 0000000..f2a99df --- /dev/null +++ b/lectures/phillips_self_confirming.md @@ -0,0 +1,570 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 自我确认均衡 + headings: + Overview: 概述 + Objects in the Phelps problem: 费尔普斯问题中的要素 + The actual Phillips curve: 实际菲利普斯曲线 + Self-confirming equilibria: 自我确认均衡 + The special case solved by hand: 手工可解的特殊情形 + The special case solved by hand::Why not Ramsey?: 为什么不是拉姆齐? + Equilibrium with misspecified beliefs: 带有误设信念的均衡 + Equilibrium with misspecified beliefs::Approaching Ramsey: 趋近拉姆齐 + Equilibrium with misspecified beliefs::Spectra and impulse responses: 谱与脉冲响应 + Equilibrium with misspecified beliefs::Grounds for optimism: 乐观的理由 + Exercises: 练习 +--- + +(phillips_self_confirming)= +```{raw} jupyter + +``` + +# 自我确认均衡 + +```{contents} Contents +:depth: 2 +``` + +除了 Anaconda 中已有的库之外,本讲座还将使用以下库: + +```{code-cell} ipython3 +:tags: [hide-output] + +!pip install quantecon +``` + +## 概述 + +本讲座完成了 {doc}`phillips_credibility` 中开始的关于菲利普斯曲线权衡的研究。 + +它遵循 {cite}`Sargent1999` 的第 7 章。 + +我们寻求这样一些模型:它们与 {doc}`phillips_credibility` 中 {cite}`KydlandPrescott1977` 的基本模型偏离最小,但同时也让政府的*信念*由其自身政策所产生的数据来塑造。 + +关键的均衡概念是**自我确认均衡**:政府对菲利普斯曲线可能持有*错误*的模型,但它通过最小二乘法将该模型拟合到数据上,而它所观测到的数据恰好证实了它的信念。 + +我们结合了两个文献流派的思想: + +* {cite}`KingWatson1994` 记录了关于菲利普斯曲线的推断如何取决于*拟合方向*——是将失业率对通货膨胀回归(*古典*识别),还是将通货膨胀对失业率回归(*凯恩斯*识别)。 +* 一个可追溯到 Muth、Lucas 和 Prescott 的文献流派 {cite}`muth1961,Lucas_Prescott_1971` 将理性预期均衡表述为从信念到统计模型总体矩的映射的不动点。 + +我们构建了两个除拟合方向外完全相同的自我确认均衡,并发现最小化的方向会影响结果。 + +然后我们研究一个**带有误设信念的均衡**,它将 {doc}`phillips_adaptive` 中的费尔普斯问题与 {doc}`phillips_misspecified` 中的最优误设机制结合起来,并发现了乐观的理由:结果优于纳什均衡,并随着政府变得更有耐心而趋近拉姆齐结果。 + +让我们导入所需的库: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +import quantecon as qe +from scipy.optimize import minimize_scalar +``` + +## 费尔普斯问题中的要素 + +回顾 {doc}`phillips_adaptive` 中一般费尔普斯问题的构成要素。 + +政府相信一个简约形式的菲利普斯曲线,它可以按两个方向拟合: + +$$ +\text{古典:} \quad U_t = \gamma' X_{C,t} + \varepsilon_{C,t}, +\qquad X_{C,t} = \begin{bmatrix} y_t & X_{t-1}' \end{bmatrix}', +$$ + +$$ +\text{凯恩斯:} \quad y_t = \beta' X_{K,t} + \varepsilon_{K,t}, +\qquad X_{K,t} = \begin{bmatrix} U_t & X_{t-1}' \end{bmatrix}' . +$$ + +求解费尔普斯问题以政府的信念 $\gamma$ 为给定,得出通货膨胀的决策规则 $h(\gamma)$。 + +这两种参数化通过如下反演公式相关联 + +```{math} +:label: sc_invert + +\gamma_1 = \beta_1^{-1}, \qquad \gamma_{-1} = - \beta_{-1} / \beta_1 . +``` + +## 实际菲利普斯曲线 + +*实际的*菲利普斯曲线在早期讲座使用的基础上进行了扩展,以允许序列相关的冲击: + +```{math} +:label: sc_actual + +U_t = U^* - \frac{\theta}{1 - \rho_2 L}(y_t - x_t) + \frac{v_{1t}}{1 - \rho_1 L}, +``` + +其中 $|\rho_1| < 1$,$|\rho_2| < 1$,且 $v_t = (v_{1t}, v_{2t})'$ 为向量白噪声,其中 $v_{2t} \equiv y_t - x_t$ 是通货膨胀的意外部分。 + +在本讲座的大部分内容中,我们设 $\rho_1 = \rho_2 = 0$ 以阐明理论要点,这将 {eq}`sc_actual` 化简为 + +$$ +U_t = U^* - \theta(y_t - x_t) + v_{1t} . +$$ + +## 自我确认均衡 + +自我确认均衡使政府的信念与这些信念所产生的环境相协调。 + +```{prf:definition} 自我确认均衡 +:label: sc_def + +自我确认均衡是一个固定的信念向量 $\gamma$、一条政府决策规则 $h = h(\gamma)$,以及一个 $(y_t, U_t, x_t)$ 的平稳过程,满足 + +(a)通货膨胀求解费尔普斯问题,$y_t = h X_{t-1} + v_{2t}$; + +(b)公众对通货膨胀作出最优预测,$x_t = h X_{t-1}$; + +(c)失业率由实际菲利普斯曲线 {eq}`sc_actual` 生成;以及 + +(d)政府的信念满足最小二乘正交性条件 +$E\left[U_t - \gamma' X_{C,t}\right] X_{C,t}' = 0$(**古典**拟合方向)。 +``` + +条件(d)使政府的信念依赖于矩矩阵,而这些矩矩阵通过(a)-(c)本身又依赖于政府的信念。 + +政府的信念隐含着一种行为,该行为产生的数据的矩恰好*证实*了这些信念。 + +将(d)替换为**凯恩斯**拟合方向,会得到一个不同的自我确认均衡: + +> (d′)政府拟合凯恩斯菲利普斯曲线,$E\left[y_t - \beta' X_{K,t}\right] X_{K,t}' = 0$,然后通过反演公式 {eq}`sc_invert` 恢复 $\gamma$。 + +由于政府的信念会影响数据的整个概率分布,最小化的方向会影响结果。 + +```{note} +一般而言,计算自我确认均衡意味着寻找映射 $\gamma = T(h(\gamma))$(古典)或 $\beta = S(h(\gamma(\beta)))$(凯恩斯)的不动点。正交性条件中的矩是通过求解一个离散李雅普诺夫方程,从该系统的状态空间表示中得到的。实践中,人们迭代一个松弛算法 $\beta_{j+1} = \kappa\beta_j + (1-\kappa) S(\beta_j)$,这与 {doc}`phillips_credibility` 中的最小二乘学习递归相似。 +``` + +## 手工可解的特殊情形 + +当 $\rho_1 = \rho_2 = 0$ 时,政府的问题退化为一系列静态问题,每个自我确认均衡都可以手工计算。 + +令 $X_{t-1} = 1$,实际菲利普斯曲线蕴含以下二阶矩 + +```{math} +:label: sc_moments + +\operatorname{var}(U_t) = \theta^2 \sigma_2^2 + \sigma_1^2, +\qquad +\operatorname{var}(y_t) = \sigma_2^2, +\qquad +\operatorname{cov}(U_t, y_t) = -\theta \sigma_2^2 . +``` + +**古典拟合方向**($U$ 对 $y$):斜率为 + +$$ +\gamma_1 = \frac{\operatorname{cov}(U_t, y_t)}{\operatorname{var}(y_t)} = -\theta, +$$ + +而均值必须落在回归线上这一要求给出截距 $\gamma_{-1} = (\gamma_1^2 + 1) U^*$。 + +**凯恩斯拟合方向**($y$ 对 $U$):斜率为 + +$$ +\beta_1 = \frac{\operatorname{cov}(U_t, y_t)}{\operatorname{var}(U_t)} + = \frac{-\theta \sigma_2^2}{\sigma_1^2 + \theta^2 \sigma_2^2}, +$$ + +截距为 $\beta_{-1} = -\frac{\beta_1^2 + 1}{\beta_1} U^*$,由此通过反演得到隐含的古典系数,$\gamma_1 = \beta_1^{-1}$ 和 $\gamma_{-1} = \frac{\beta_1^2 + 1}{\beta_1^2} U^*$。 + +```{code-cell} ipython3 +class SelfConfirmingStatic: + """ + The two static self-confirming equilibria (ρ1 = ρ2 = 0), one for + each direction of fit. + """ + + def __init__(self, θ=1.0, U_star=5.0, σ1=0.3, σ2=0.3): + self.θ, self.U_star, self.σ1, self.σ2 = θ, U_star, σ1, σ2 + + def classical(self): + "Perceived Phillips curve U = γ_{-1} + γ_1 y under classical fit." + θ, U_star = self.θ, self.U_star + γ1 = -θ + γ_1 = (γ1**2 + 1) * U_star + y_bar = -γ_1 * γ1 / (γ1**2 + 1) # mean (= Nash) inflation + return γ1, γ_1, y_bar + + def keynesian(self): + "Perceived Phillips curve under Keynesian fit, inverted to γ." + θ, U_star, σ1, σ2 = self.θ, self.U_star, self.σ1, self.σ2 + β1 = -θ * σ2**2 / (σ1**2 + θ**2 * σ2**2) + β_1 = -(β1**2 + 1) / β1 * U_star + γ1 = 1 / β1 + γ_1 = (β1**2 + 1) / β1**2 * U_star + y_bar = β_1 / (β1**2 + 1) # mean inflation + return γ1, γ_1, y_bar +``` + +```{code-cell} ipython3 +sce = SelfConfirmingStatic(θ=1.0, U_star=5.0, σ1=0.3, σ2=0.3) + +γ1_C, γ0_C, y_C = sce.classical() +γ1_K, γ0_K, y_K = sce.keynesian() + +print("Classical direction of fit") +print(f" γ_1 = {γ1_C:.1f}, γ_(-1) = {γ0_C:.1f}, mean inflation = {y_C:.1f}") +print("Keynesian direction of fit") +print(f" γ_1 = {γ1_K:.1f}, γ_(-1) = {γ0_K:.1f}, mean inflation = {y_K:.1f}") +``` + +这些结果再现了 {cite}`Sargent1999` 第 7 章中的数值例子。 + +在古典拟合方向下,平均通货膨胀为纳什值 $\theta U^* = 5$。 + +在凯恩斯拟合方向下,政府估计出一条*更平坦*的菲利普斯曲线,并相信权衡关系比实际更有利,因此将通货膨胀设定为两倍高,即 $10$。 + +让我们绘制这两条自我确认的菲利普斯曲线,重现图 7.1。 + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(7, 6)) + +U_grid = np.linspace(0, 12, 100) + +# perceived Phillips curves U = γ_{-1} + γ_1 y => y = (U - γ_{-1}) / γ_1 +ax.plot(U_grid, (U_grid - γ0_C) / γ1_C, 'C0', label='P: classical fit') +ax.plot(U_grid, (U_grid - γ0_K) / γ1_K, 'C1', label='Q: Keynesian fit') + +ax.plot(sce.U_star, y_C, 'C0o') +ax.annotate('Nash', (sce.U_star, y_C), (sce.U_star + 0.4, y_C - 0.6)) +ax.plot(sce.U_star, y_K, 'C1o') +ax.annotate('Keynesian mean', (sce.U_star, y_K), + (sce.U_star + 0.4, y_K + 0.2)) + +ax.set_xlim(0, 12) +ax.set_ylim(0, 12) +ax.set_xlabel('unemployment $U$') +ax.set_ylabel('inflation $y$') +ax.legend() +plt.show() +``` + +曲线 P 是用古典拟合方向估计出的自我确认菲利普斯曲线;曲线 Q 是用凯恩斯拟合方向估计出的。 + +由于凯恩斯拟合使政府相信权衡关系更可利用,平均通货膨胀更高。 + +### 为什么不是拉姆齐? + +两个自我确认均衡给出的平均结果都*劣于*拉姆齐结果。 + +这表明 {doc}`phillips_adaptive` 中命题的假设条件出现了失效——该命题原本认为求解费尔普斯问题最终能维持接近拉姆齐的结果。 + +失效的是**归纳假设**。 + +由于 $\rho_1 = \rho_2 = 0$,自我确认均衡是序列不相关的,因此滞后通货膨胀会从经验菲利普斯曲线中消失。 + +停用归纳假设实际上使政府求解一个单期问题,并关闭了促进更好结果的跨期渠道。 + +## 带有误设信念的均衡 + +为了探讨施加一个*不同的*错误模型如何可能*改善*纳什结果,我们现在让*公众*而非政府犯一个微妙的设定误差。 + +这将适应性预期、归纳假设和费尔普斯问题联系了起来。 + +政府知道正确的模型, + +```{math} +:label: sc_bray10 + +U_t = U^* - \theta(y_t - x_t) + v_{1t}, +\qquad +x_t = C y_{t-1} + (1 - C) x_{t-1}, \quad C \in (0, 1), +``` + +其中公众持有常数增益的适应性预期,参数 $C$ 由其*根据数据进行调整*。 + +将 $x_t$ 视为状态变量,政府求解费尔普斯问题:通过选择一个反馈规则 $y_t = f_1 + f_2 x_t + v_{2t}$,最大化 $-E_0 \sum_{t=0}^\infty \delta^t\left[(U^* - \theta(y_t - x_t))^2 + y_t^2\right]$。 + +这恰好是 {doc}`phillips_adaptive` 中带有适应参数 $\lambda = 1 - C$ 的 LQ 费尔普斯问题。 + +```{code-cell} ipython3 +def phelps_policy(C, δ, θ=1.0, U_star=5.0): + "Government feedback rule y_t = f1 + f2 x_t, with public gain C." + λ = 1 - C + a = np.array([[U_star], [θ]]) + R = 0.5 * (a @ a.T) + Q = np.array([[0.5 * (θ**2 + 1)]]) + N = -0.5 * θ * a.T + A = np.array([[1.0, 0.0], [0.0, λ]]) + B = np.array([[0.0], [1 - λ]]) + lq = qe.LQ(Q, R, A, B, N=N, beta=min(δ, 1 - 1e-7)) + P, F, d = lq.stationary_values() + return -F[0, 0], -F[0, 1] +``` + +政府的行为使得*实际*通货膨胀率为 + +```{math} +:label: sc_bray11 + +y_t = \frac{f_1}{1 - f_2} + + \frac{1 - (1 - C)L}{1 - (1 - C(1 - f_2))L} v_{2t} + = \nu + f(L) v_{2t}, +``` + +均值为 $\nu = f_1 / (1 - f_2)$,谱为 $F(\omega; C) = |f(e^{i\omega})|^2 \sigma_2^2$。 + +给定 $C$,公众寻求与 {doc}`phillips_misspecified` 中相同形式的最优拟合误设模型,即积分移动平均形式, + +$$ +y_t = \frac{1 - (1 - c)L}{1 - L}\epsilon_t = g(L)\epsilon_t , +$$ + +而由此得出的最优估计映射 $c = B(C)$ 将**预测误设均衡**定义为不动点 $C = B(C)$。 + +这使得真实模型和近似模型都成为均衡结果,并将适应参数 $C$ 从自由参数转变为一个结果。 + +```{code-cell} ipython3 +class MisspecifiedPhillips: + """ + Equilibrium with misspecified public beliefs: a fixed point of the + best-estimate map, with the government solving the Phelps problem. + """ + + def __init__(self, θ=1.0, U_star=5.0, σ2=0.3, δ=0.97, ρ=0.995, N=1024): + self.θ, self.U_star, self.σ2 = θ, U_star, σ2 + self.δ, self.ρ, self.N = δ, ρ, N + ω = 2 * np.pi * np.arange(N) / N + self.z = np.exp(1j * ω) + self.ω = ω + + def true_process(self, C): + "Return the mean ν, spectrum F, and policy (f1, f2) given belief C." + f1, f2 = phelps_policy(C, self.δ, self.θ, self.U_star) + ν = f1 / (1 - f2) + ψ = 1 - C * (1 - f2) + f = (1 - (1 - C) * self.z) / (1 - ψ * self.z) + F = np.abs(f)**2 * self.σ2**2 + return ν, F, (f1, f2) + + def best_estimate(self, C): + "The best-estimate map c = B(C)." + ν, F, _ = self.true_process(C) + z, ρ = self.z, self.ρ + + def profile(c): + H = np.abs((1 - (1 - c) * z) / (1 - ρ * z))**2 + σ_ε2 = np.mean(F / H) + ν**2 / H[0] + return np.log(σ_ε2) + np.mean(np.log(H)) + + return minimize_scalar(profile, bounds=(1e-4, 0.99), + method='bounded').x + + def solve(self, C0=0.1, tol=1e-10, maxit=500): + "Iterate the best-estimate map to a fixed point." + C = C0 + for _ in range(maxit): + C_new = self.best_estimate(C) + if abs(C_new - C) < tol: + break + C = C_new + ν, _, (f1, f2) = self.true_process(C_new) + return C_new, ν, (f1, f2) +``` + +```{code-cell} ipython3 +mp = MisspecifiedPhillips(δ=0.97) +C_star, ν_star, (f1, f2) = mp.solve() + +print(f"equilibrium gain C = {C_star:.4f}") +print(f"policy rule y = {f1:.4f} + {f2:.4f} x") +print(f"mean inflation ν = {ν_star:.3f}") +print(f"Nash inflation θ U* = {mp.θ * mp.U_star:.3f}") +``` + +最重要的结果是:隐含的平均通货膨胀率大幅*低于*纳什值 $5$。 + +嵌入在适应性预期方案中的归纳假设,连同较高的贴现因子,共同带来了这一改进——并且由于 $C$ 现在是一个均衡结果,这一机制比 {doc}`phillips_adaptive` 中更为鲜明,在那里 $C$ 可以独立于 $\delta$ 被操纵。 + +### 趋近拉姆齐 + +随着政府变得更有耐心,均衡平均通货膨胀率会降至拉姆齐值零附近。 + +```{code-cell} ipython3 +δ_grid = np.array([0.95, 0.96, 0.97, 0.98, 0.99, 0.995]) +C_vals, ν_vals = [], [] +for δ in δ_grid: + C, ν, _ = MisspecifiedPhillips(δ=δ).solve() + C_vals.append(C) + ν_vals.append(ν) + +fig, axes = plt.subplots(1, 2, figsize=(11, 4.5)) +axes[0].plot(δ_grid, ν_vals, 'o-') +axes[0].axhline(mp.θ * mp.U_star, color='k', ls='--', lw=1, label='Nash') +axes[0].set_xlabel(r'discount factor $\delta$') +axes[0].set_ylabel('mean inflation') +axes[0].legend() + +axes[1].plot(δ_grid, C_vals, 'o-', color='C1') +axes[1].set_xlabel(r'discount factor $\delta$') +axes[1].set_ylabel('equilibrium gain $C$') + +plt.tight_layout() +plt.show() +``` + +在每个贴现因子下,平均通货膨胀都远低于纳什值,并随着 $\delta \to 1$ 趋近于拉姆齐值零。 + +```{note} +精确的均衡值取决于用来保证被感知模型谱密度良好定义的近单位根近似 $\rho$,正如 {doc}`phillips_misspecified` 中所讨论的那样。定性的结论——即结果优于纳什,并随着 $\delta \to 1$ 趋近拉姆齐——是稳健的。 +``` + +### 谱与脉冲响应 + +让我们比较均衡处真实与近似的通货膨胀过程,如 {cite}`Sargent1999` 的图 7.2 和图 7.3 所示。 + +```{code-cell} ipython3 +ν_star, F, _ = mp.true_process(C_star) +c_star = mp.best_estimate(C_star) +H = np.abs((1 - (1 - c_star) * mp.z) / (1 - mp.ρ * mp.z))**2 +σ_ε2 = np.mean(F / H) + ν_star**2 / H[0] +G = H * σ_ε2 + +half = mp.N // 2 +fig, ax = plt.subplots(figsize=(8, 5)) +ax.plot(mp.ω[:half], np.log(F[:half]), 'C0', label='true model') +ax.plot(mp.ω[:half], np.log(G[:half]), 'C1--', label='approximating model') +ax.set_xlabel(r'angular frequency $\omega$') +ax.set_ylabel('log spectral density') +ax.legend() +plt.show() +``` + +真实谱密度与近似谱密度除了在最低频率处之外都拟合得很好。 + +真实的通货膨胀率仅具有中等程度的序列相关性,而——正如 {doc}`phillips_misspecified` 中的布雷模型一样——近似模型使用单位根来模拟均值,即用二阶矩来捕捉一阶矩。 + +```{code-cell} ipython3 +def ima_impulse(num, den, T=25): + "IRF of (1 - num L)/(1 - den L)." + h = np.empty(T) + h[0] = 1.0 + for k in range(1, T): + h[k] = den * h[k - 1] + h[1:] -= num * h[:-1] + return h + +ψ = 1 - C_star * (1 - f2) +irf_true = ima_impulse(1 - C_star, ψ) +irf_approx = ima_impulse(1 - c_star, mp.ρ) + +fig, ax = plt.subplots(figsize=(8, 5)) +ax.plot(irf_true, 'C0o-', ms=4, label='true model') +ax.plot(irf_approx, 'C1s--', ms=4, label='approximating model') +ax.set_xlabel('lag') +ax.set_ylabel('response') +ax.legend() +plt.show() +``` + +近似模型中的单位根表现为其脉冲响应中的一个非零渐近值。 + +### 乐观的理由 + +在自我确认均衡带来失望之后,带有预测误设的均衡令人振奋:它支持了优于纳什的结果。 + +这个均衡概念不是自我确认的,但它具有那种精神——它体现了一种用*错误*模型进行自我确认的类型。 + +近似误差之小表明,存在一个近乎自我确认、且结果远优于纳什的模型。 + +本系列后续的讲座——{doc}`phillips_learning`、{doc}`phillips_escaping_nash` 和 {doc}`phillips_priors`——构建了这些模型的自适应实时版本,其中政府从最新数据中递归地估计其菲利普斯曲线。 + +在那里,此处计算出的自我确认均衡成为学习动态的*吸引子*,而优于纳什的结果则以反复的*逃逸*现象重新出现,远离该吸引子。 + +## 练习 + +```{exercise-start} +:label: sc_ex1 +``` + +两个静态自我确认均衡之间的差距是由方差 $\sigma_1$(菲利普斯曲线冲击)和 $\sigma_2$(通货膨胀意外)驱动的。 + +古典均衡总是给出等于纳什值 $\theta U^*$ 的平均通货膨胀,但凯恩斯平均通货膨胀取决于比率 $\sigma_1 / \sigma_2$。 + +固定 $\sigma_2 = 0.3$、$\theta = 1$、$U^* = 5$,绘制凯恩斯平均通货膨胀作为 $\sigma_1 \in [0.05, 1.0]$ 的函数。 + +当 $\sigma_1 \to 0$ 时会发生什么,为什么? + +```{exercise-end} +``` + +```{solution-start} sc_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +σ1_grid = np.linspace(0.05, 1.0, 50) +y_keynes = [SelfConfirmingStatic(σ1=σ1, σ2=0.3).keynesian()[2] + for σ1 in σ1_grid] + +fig, ax = plt.subplots(figsize=(8, 4.5)) +ax.plot(σ1_grid, y_keynes, label='Keynesian mean inflation') +ax.axhline(5.0, color='k', ls='--', lw=1, label='Nash') +ax.set_xlabel(r'$\sigma_1$') +ax.set_ylabel('mean inflation') +ax.legend() +plt.show() +``` + +当 $\sigma_1 \to 0$ 时,菲利普斯曲线趋于近乎确定,凯恩斯斜率 $\beta_1 \to -1/\theta$,两个拟合方向趋于一致,因此凯恩斯平均通货膨胀趋近纳什值。 + +随着 $\sigma_1$ 增大,失业率变得更嘈杂,$y$ 对 $U$ 的凯恩斯回归变得更平坦,政府感知到一个更可利用的权衡关系,从而提高了平均通货膨胀。 + +```{solution-end} +``` + +```{exercise-start} +:label: sc_ex2 +``` + +验证误设信念均衡确实是一个真正的不动点。 + +对于 $\delta = 0.97$,绘制最优估计映射 $C \mapsto B(C)$ 与 45 度线的关系,并标出不动点。 + +```{exercise-end} +``` + +```{solution-start} sc_ex2 +:class: dropdown +``` + +```{code-cell} ipython3 +mp = MisspecifiedPhillips(δ=0.97) +C_grid = np.linspace(0.02, 0.3, 20) +B_vals = [mp.best_estimate(C) for C in C_grid] +C_star, _, _ = mp.solve() + +fig, ax = plt.subplots(figsize=(6, 6)) +ax.plot(C_grid, B_vals, 'C0', label='$B(C)$') +ax.plot(C_grid, C_grid, 'k--', lw=1, label='45 degrees') +ax.plot(C_star, C_star, 'ko') +ax.annotate('equilibrium', (C_star, C_star), (C_star + 0.03, C_star - 0.03)) +ax.set_xlabel('$C$') +ax.set_ylabel('$B(C)$') +ax.legend() +plt.show() +``` + +最优估计映射在均衡增益处与 45 度线相交,证实了 $C = B(C)$。 + +```{solution-end} +``` \ No newline at end of file From 817cc3d41cea51b07cd75ae8d856d27239a00371 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:24 +1000 Subject: [PATCH 16/21] Update translation: .translate/state/phillips_self_confirming.md.yml --- .translate/state/phillips_self_confirming.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_self_confirming.md.yml diff --git a/.translate/state/phillips_self_confirming.md.yml b/.translate/state/phillips_self_confirming.md.yml new file mode 100644 index 0000000..2242d8f --- /dev/null +++ b/.translate/state/phillips_self_confirming.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 7 +tool-version: 0.23.0 From 85451cff2aba2c086cc2240af5bbd02acff5ace7 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:25 +1000 Subject: [PATCH 17/21] Update translation: lectures/phillips_two_stories.md --- lectures/phillips_two_stories.md | 576 +++++++++++++++++++++++++++++++ 1 file changed, 576 insertions(+) create mode 100644 lectures/phillips_two_stories.md diff --git a/lectures/phillips_two_stories.md b/lectures/phillips_two_stories.md new file mode 100644 index 0000000..67f904d --- /dev/null +++ b/lectures/phillips_two_stories.md @@ -0,0 +1,576 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 美国通货膨胀的兴衰 + headings: + Overview: 概述 + Facts: 事实 + The Phillips curve in the data: 数据中的菲利普斯曲线 + Two interpretations: 两种解释 + Two interpretations::The triumph of natural-rate theory: 自然率理论的胜利 + Two interpretations::The vindication of econometric policy evaluation: 计量经济学政策评估的平反 + Ignoring the Lucas Critique: 忽略卢卡斯批判 + Ignoring the Lucas Critique::The Critique: 批判 + Ignoring the Lucas Critique::The appeal to drifting coefficients: 对漂移系数的诉求 + Ignoring the Lucas Critique::Parameter drift as a point of departure: 以参数漂移为出发点 + 'A premature summary: triumph or vindication?': 一个尚早的总结:胜利还是平反? + 'A premature summary: triumph or vindication?::The road ahead': 前路展望 + 'A premature summary: triumph or vindication?::The induction hypothesis: villain and hero': 归纳假说:反派与英雄 + 'A premature summary: triumph or vindication?::The reservation': 保留意见 + Data patterns after 1999: 1999 年之后的数据模式 + Data patterns after 1999::The rise and fall, extended: 延伸后的兴与衰 + Data patterns after 1999::Unemployment and inflation to the present: 延续至今的失业率与通货膨胀 + Data patterns after 1999::The Phillips curve across three eras: 三个时代中的菲利普斯曲线 + Data patterns after 1999::What the new data mean for the two stories: 新数据对这两个故事意味着什么 + Exercises: 练习 +--- + +(phillips_two_stories)= +```{raw} jupyter + +``` + +# 美国通货膨胀的兴衰 + +```{contents} Contents +:depth: 2 +``` + +除了 Anaconda 中已有的库之外,本讲座还将使用以下库来下载和过滤宏观经济数据: + +```{code-cell} ipython3 +:tags: [hide-output] + +!pip install pandas_datareader +``` + +## 概述 + +这是基于托马斯·萨金特《美国通货膨胀的征服》(*The Conquest of American Inflation* {cite}`Sargent1999`)的系列讲座中的第一讲。 + +它综合了该书第一章和第二章的内容。 + +这个系列提出了一个关于战后美国宏观经济史的问题: + +> 如果我们认为通货膨胀是由美联储控制的,那么我们该如何解释美国通货膨胀在 20 世纪 70 年代的上升,以及在 20 世纪 80 年代初保罗·沃尔克治下的骤然下降? + +这篇文章评估了两种解释,两者都基于政策制定者对菲利普斯曲线的*信念*。 + +在这两个故事中,美联储都是通过经验与*先验*推理相结合的方式,学到了自然失业率理论。 + +两个故事的区别在于该理论是如何被采纳的: + +* **自然率理论的胜利。** 学术经济学家发现了自然率假说,指出任何通货膨胀与失业之间的权衡都是暂时的,并最终说服政策制定者追求低通货膨胀。 +* **计量经济学政策评估的平反。** 政策制定者从未放弃罗伯特·卢卡斯在其著名批判中所抨击的方法。他们反复重新估计菲利普斯曲线并用它来选择目标,而正是*数据本身*——一条不断向不利方向漂移的经验菲利普斯曲线——引导他们走向更低的通货膨胀。 + +本讲座介绍了支持这两个故事的事实,勾勒出这两种解释,并回顾了第二章既援引又修正的卢卡斯批判。 + +该系列的其余讲座建立了相应的模型: + +* {doc}`phillips_credibility` —— 单期基德兰德-普雷斯科特(Kydland-Prescott)可信度问题(第三章)。 +* {doc}`phillips_adaptive` —— 适应性预期与菲尔普斯问题(第五章)。 +* {doc}`phillips_misspecified` —— 最优错误设定信念下的均衡(第六章)。 +* {doc}`phillips_self_confirming` —— 自我确认均衡(第七章)。 +* {doc}`phillips_learning` —— 适应性学习、逃逸动态以及模拟的沃尔克稳定化过程(第八章)。 +* {doc}`phillips_escaping_nash` —— 以分析方式刻画的逃逸动态({cite}`ChoWilliamsSargent2002`)。 +* {doc}`phillips_priors` —— 政府关于漂移系数的先验如何影响收敛、循环与逃逸({cite}`SargentWilliams2005`)。 +* {doc}`phillips_lost_conquest` —— 将同样的工具应用于 2020 年代的通货膨胀以及美联储的迟缓反应({cite}`SargentWilliams2025`)。 +* {doc}`phillips_drifts_volatilities` —— 一篇实证后记,将带漂移系数、随机波动率的向量自回归模型拟合到数据上,探讨大通胀究竟是政策不当还是运气不佳造成的({cite}`CogleySargent2005`)。 + +让我们从一些导入开始: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import datetime +from pandas_datareader import data as web +from statsmodels.tsa.filters.bk_filter import bkfilter +``` + +```{note} +接下来两节中的图表复现了 {cite}`Sargent1999` 第一章和第二章中的图表,这些图表所用的数据取自 20 世纪 90 年代末。 +我们从 [FRED](https://fred.stlouisfed.org/) 下载相应的原始数据序列,并将关注范围限定在与原书相同的历史区间内。 +之后的 {ref}`phillips_after_1999` 一节会将其中最具启发性的图表延伸到当下,并探讨这额外的四分之一个世纪的数据对这两个故事意味着什么。 +``` + +## 事实 + +我们从整篇文章要解释的这一个事实开始:二战以来美国通货膨胀呈现的驼峰形走势。 + +我们用消费者价格指数(所有项目)月度变化的年化值来衡量通货膨胀,并用 13 个月的居中移动平均对其进行平滑,以去除季节性和高频噪声。 + +```{code-cell} ipython3 +start, end = datetime.datetime(1948, 1, 1), datetime.datetime(1999, 1, 1) + +cpi = web.DataReader('CPIAUCNS', 'fred', start, end)['CPIAUCNS'] + +# 年化月度通货膨胀率,再取 13 个月居中移动平均 +inflation = 1200 * np.log(cpi).diff() +inflation_ma = inflation.rolling(13, center=True).mean() +``` + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(9, 5)) +ax.plot(inflation_ma, lw=1.2) +ax.axhline(0, color='k', lw=0.5) +ax.set_xlabel('year') +ax.set_ylabel('inflation (percent, annualized)') +ax.set_title('Figure 1.1: Monthly inflation, CPI all items, ' + '13-month centered moving average') +plt.show() +``` + +在 20 世纪 50 年代末和 60 年代初,通货膨胀水平较低,随后在 70 年代急剧上升,接着又在 80 年代初随着沃尔克的稳定化政策而骤然下降。 + +任何将通货膨胀视为受美联储控制的解释,都必须说明这一上升与下降的过程。 + +## 数据中的菲利普斯曲线 + +尽管菲利普斯曲线在一些学术界和政策制定圈中名誉扫地,但它在美国数据中依然顽强存在,简单的方法就能将其检测出来。 + +为了从数据中提炼出菲利普斯曲线,我们沿用原书的两种做法。 + +第一,我们使用单一人口群体——20 岁及以上的白人男性——的失业率,而非整体失业率,因为整体失业率会受到人口结构缓慢变化的干扰。 + +第二,我们关注*商业周期*频率,滤除缓慢变化的成分,以便肉眼能够察觉通货膨胀与失业率之间的反向关系。 + +```{code-cell} ipython3 +u = web.DataReader('LNS14000028', 'fred', start, end)['LNS14000028'] # white men 20+ + +data = pd.concat([inflation.rename('inflation'), + u.rename('unemployment')], axis=1).dropna() +data.head() +``` + +图 1.2 将这两个原始序列绘制在一起。 + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(9, 5)) +ax.plot(data.index, data['inflation'], 'C0', lw=1, label='inflation (CPI)') +ax.plot(data.index, data['unemployment'], 'C1:', lw=1.2, + label='unemployment (white men 20+)') +ax.axhline(0, color='k', lw=0.5) +ax.set_xlabel('year') +ax.set_ylabel('percent') +ax.set_title('Figure 1.2: Monthly unemployment and inflation rates') +ax.legend() +plt.show() +``` + +为了分离出商业周期层面的关系,我们采用巴克斯特(Baxter)和金(King)提出的有限滞后带通滤波器 {cite}`BaxterKing1999`。 + +按照原书的做法,我们保留周期在 24 到 84 个月之间的波动,并使用 84 个月的超前-滞后截断。 + +```{code-cell} ipython3 +# Baxter-King bandpass: periods between 24 and 84 months, truncation 84 +bk = bkfilter(data, low=24, high=84, K=84) +bk.columns = ['inflation_cycle', 'unemployment_cycle'] +``` + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(9, 5)) +ax.plot(bk.index, bk['inflation_cycle'], 'C0', lw=1, label='inflation') +ax.plot(bk.index, bk['unemployment_cycle'], 'C1:', lw=1.2, + label='unemployment') +ax.axhline(0, color='k', lw=0.5) +ax.set_xlabel('year') +ax.set_ylabel('deviation from trend (percent)') +ax.set_title('Figure 1.3: Business-cycle components ' + '(Baxter-King bandpass filter)') +ax.legend() +plt.show() +``` + +经过滤波的两个成分往往朝相反的方向变动:这是一条商业周期意义上的菲利普斯曲线。 + +我们可以在最令我们感兴趣的子时期——1960 年至 1982 年——的散点图中更直观地看到这种权衡关系。 + +图 1.4 将原始序列相互对照绘制,图 1.5 则展示了商业周期成分。 + +```{code-cell} ipython3 +sub = slice('1960', '1982') + +fig, axes = plt.subplots(1, 2, figsize=(12, 5)) + +axes[0].scatter(data.loc[sub, 'inflation'], + data.loc[sub, 'unemployment'], s=8, alpha=0.6) +axes[0].set_xlabel('inflation') +axes[0].set_ylabel('unemployment (white men 20+)') +axes[0].set_title('Figure 1.4: Raw series, 1960-1982') + +axes[1].scatter(bk.loc[sub, 'inflation_cycle'], + bk.loc[sub, 'unemployment_cycle'], s=8, alpha=0.6) +axes[1].set_xlabel('inflation (business-cycle component)') +axes[1].set_ylabel('unemployment (business-cycle component)') +axes[1].set_title('Figure 1.5: Business-cycle components, 1960-1982') + +plt.tight_layout() +plt.show() +``` + +聚焦于商业周期成分使得表面上的菲利普斯曲线更加清晰。 + +图 1.5 揭示了**菲利普斯回路**:通货膨胀与失业率描绘出的是逆时针方向的回路,而非单一的稳定曲线,这正是自然率理论所强调的、位于故事核心的预期转变的特征表现。 + +```{note} +原书通过选取单一失业率序列来调整人口结构变化的影响。若采用更广义的失业定义,就会引入额外的低频人口结构成分,人们可能会用单位根过程来对其建模。而本文则从另一个来源——即摆脱布雷顿森林体系约束后货币当局*漂移的信念*——将单位根引入通货膨胀-失业率过程之中。 +``` + +## 两种解释 + +这两个故事都从相同的初始条件出发——即政策制定者在 1960 年前后所继承的通货膨胀与失业史,以及当时的预期状态——而且都假设数据符合自然率假说,无论政策制定者当时是否意识到这一点。 + +### 自然率理论的胜利 + +对金本位制、继而对布雷顿森林体系的坚持,使美国得以维持低通货膨胀和低通货膨胀预期。 + +1960 年,保罗·萨缪尔森和罗伯特·索洛 {cite}`SamuelsonSolow1960` 在美国数据中发现了一条菲利普斯曲线,并宣称它是*可利用的*——即政策可以通过提高通货膨胀来降低失业率。 + +在不到十年的时间里,这一建议被广泛接受并付诸实施。 + +令所有人沮丧的是,菲利普斯曲线随后发生了不利的移动:通货膨胀上升了,但失业率平均而言并未下降。 + +与此同时,埃德蒙·费尔普斯(Edmund Phelps) {cite}`Phelps1967`、米尔顿·弗里德曼 {cite}`friedman1968role` 以及罗伯特·卢卡斯 {cite}`Lucas1972` 提出并完善了自然失业率的概念,该概念将通货膨胀预期置于确定菲利普斯曲线位置的核心地位。 + +自然率理论只允许*暂时性*的权衡取舍,并解释了这种不利的转移;其理性预期版本则意味着政策制定者应当忽视这种暂时的权衡,只应努力实现低通货膨胀。 + +在这个故事里,这些思想从学术界扩散到政策制定者手中,并最终带来了 20 世纪 80 年代和 90 年代较低的通货膨胀。 + +历史的走向由政策制定者的信念——有些是错误的,有些是正确的——以及这些信念所激发的行动共同塑造。 + +### 计量经济学政策评估的平反 + +另一种解释则将沃尔克的胜利部分归功于卢卡斯所质疑的那些计量经济学和政策制定程序本身的*成功*。 + +政策制定者接受了萨缪尔森-索洛菲利普斯曲线,将其视为一种可利用的权衡关系,并采用了他们从数据中学习并据此推导政策的方法。 + +他们反复重新估计一个分布滞后的菲利普斯曲线,并用它来重新设定目标通货膨胀率与失业率的组合。 + +如果机械地解读这一过程——不将预期识别为隐藏的状态变量——那么这条不断向不利方向移动的经验菲利普斯曲线最终引导政策制定者走向了更低的通货膨胀。 + +这个故事是用一种与理性预期相去甚微的*适应性*政策理论来讲述的。 + +它将该系列后续发展的一系列思想串联起来:漂移系数、自我确认均衡、最小二乘法及其他递归学习算法、最小二乘学习者向自我确认均衡的收敛,以及沿着从这些均衡中*逃逸的路径*所展现的周期性动态。 + +这一关键思想取自克里斯托弗·西姆斯(Christopher Sims) {cite}`Sims1988`,即适应性模型使政府能够从其过去利用菲利普斯曲线的尝试中*学习*,并最终发现某种版本的自然率假说,指导其降低通货膨胀。 + +## 忽略卢卡斯批判 + +该书第二章直面对平反故事的一个显而易见的质疑:卢卡斯批判难道不正是禁止使用那种机械的、可利用的菲利普斯曲线吗?而这正是平反故事的立论基础。 + +本文重新启用了卢卡斯曾坚决批判的计量经济学与政策评估程序 {cite}`lucas1976econometric`,并强调了其批判中一个被忽视的方面:**漂移系数**。 + +### 批判 + +一个计量经济学模型是一组随机差分方程的集合,其中一些描述了私人主体的决策规则。 + +丁伯根-泰尔(Tinbergen-Theil)传统中的计量经济学政策评估,是在政府针对某一目标函数优化自身规则的同时,将这些私人决策规则视为*固定不变*的。 + +卢卡斯指出,如果私人主体求解跨期最优化问题,那么他们的决策规则将*取决于*政府的规则。 + +由于忽略了这种依赖关系,丁伯根-泰尔方法错误地将政府对结果的偏好,转译为对决策规则的排序,从而给出不可靠的政策建议。 + +### 对漂移系数的诉求 + +卢卡斯承认凯恩斯主义模型在预测方面表现出色,但他认为,良好的预测表现并不能证明丁伯根-泰尔方法所假设的那种*干预下的不变性*成立。 + +他强调,预测者们习惯性地调整关键方程中的常数项,并将这些调整解读为一种与库利(Cooley)和普雷斯科特(Prescott) {cite}`CooleyPrescott1973` 思路一致的适应性系数模型。 + +所估计关系在跨期上的不稳定性——即系数漂移——削弱了将其视为对政策规则系统性变化保持不变的这种做法。 + +然而卢卡斯并未对这种漂移作出*解释*,而无论是批判之后建立的宏观经济理论,还是理性预期计量经济学,都没有对此作出说明:二者都聚焦于具有时不变转移函数的环境。 + +### 以参数漂移为出发点 + +本文以参数漂移为出发点,将其视为一个*确凿的证据*——这正是表明政府关于经济的信念、进而其通货膨胀政策,随时间演化的关键证据。 + +它由两个部分构建出一个模型: + +1. 一个关于政府决策的丁伯根-泰尔理论——即 {doc}`phillips_adaptive` 中的费尔普斯问题;以及 +2. 一个针对政府的漂移系数计量经济学程序,其中包含卢卡斯所描述的那种常数项调整。 + +在一个**自我确认均衡**(在 {doc}`phillips_self_confirming` 中展开)中,卢卡斯批判的部分效力便消失了。 + +尽管政府的不变性假设是错误的,但它并未在结果中受挫,因为这些结果在统计上与它的信念是一致的。 + +自我确认均衡是一种理性预期均衡,但其自由参数比卢卡斯所使用的模型*更少*——而恰恰正是这些缺失的参数,才是表现制度变迁所需要的。 + +要容纳制度变迁和漂移系数,就必须*抵制*向自我确认均衡的收敛。 + +本文通过用一种赋予近期数据更高权重的恒定增益、适应性系数算法,取代政府的最小二乘估计量,从而阻止这种收敛——这使政府具备了一种"环境可能不稳定"的疑虑。 + +这削弱了向自我确认均衡的牵引力,并维持了沿着某条逃逸路径的动态,制度变迁正是沿此路径发生的。 + +具有讽刺意味的是,正如我们将在 {doc}`phillips_learning` 中看到的那样,*违反*卢卡斯批判的程序,反而可能带来比遵循它的程序更好的结果。 + +## 一个尚早的总结:胜利还是平反? + +本系列后续讲座将建立各种模型。 + +在我们开始之前,值得先预览一下这些模型将引向何方,以及它们留下的尚未解决的张力——这是对整个旅程的一个提前总结,改编自 {cite}`Sargent1999` 的结论章节。 + +一切都可以围绕两个*基准*模型来组织。 + +第一个模型源自 {cite}`Phelps1967`,公众以*适应性*方式形成预期,而政府在将公众的规则视为既定的前提下*最优地*选择政策。 + +第二个模型是理性预期自然率模型,其中公众是*理性的*,而政府的政策则被视为*外生且任意的*。 + +卢卡斯建议用第二个基准取代第一个。 + +正视这两个故事,促使我们提出在这两极之间做出各种*折衷*的模型——而后续讲座正是这些折衷方案。 + +### 前路展望 + +我们在 {doc}`phillips_credibility` 中开始,先在*双方*都施加理性的假设。 + +单期的 {cite}`KydlandPrescott1977` 模型得出了一个悲观的预测——即高通货膨胀的时间一致(纳什)结果——但可信政策理论的重复经济版本,用*不可知论*取代了这种悲观:太多的结果都变得可维持,以至于该理论只能给出微弱的预测。 + +这种弱预测性是我们在宣称自然率理论取得胜利之前应当迟疑的第一个理由。 + +随后我们从卢卡斯批判处折返,重新从费尔普斯基准出发,但作一处改动:政府对私人部门的模型不再是任意的——它是*拟合历史数据*得到的。 + +改变这一拟合问题的各种细节,便产生了该系列的其余内容: + +* 自我确认均衡({doc}`phillips_self_confirming`), +* 具有最优*错误设定*预测函数的均衡({doc}`phillips_misspecified`),以及 +* 适应性、"预期效用"学习模型({doc}`phillips_learning`、{doc}`phillips_escaping_nash` 和 {doc}`phillips_priors`)。 + +这些适应性模型是对理性预期一种*有节制的*退让,而非对其的彻底抛弃。 + +它们不包含控制预期的自由参数;在每一期,它们都施加与理性预期模型相同的跨方程约束;并且——由于自我确认均衡是其*均值动态*的吸引子——它们在平静的条件下会收敛回理性预期,满足了 {cite}`Kreps1998` 所提出的一个诉求。 + +但是,遵循 {cite}`Sims1988` 的思路,我们真正感兴趣的是适应性所带来的*周期性*动态。 + +由于怀疑菲利普斯曲线容易发生漂移,政府使用了一种恒定增益算法,这在系数发生漂移时是明智的选择。 + +其成果颇为惊人:适应性模型产生了通货膨胀的骤然*稳定化*,这一结果违背了均值动态所指向的那种较差的自我确认结果。 + +这些制度转变既不是源于政府程序的任何改变,也不是源于巨大的冲击,而是源于*政府自身的计量经济学所引发的信念变化*——即在近似模型空间中逃逸路径的数学机制。 + +### 归纳假说:反派与英雄 + +这个故事的核心是**归纳假说**——即预期方程中滞后通货膨胀项的权重之和为一的这一限制,从而使得一个永久性更高的通货膨胀率最终会被完全预期到。 + +它几乎未经任何评论便被内嵌于 {cite}`Friedman1957` 和 {cite}`Cagan` 的适应性预期假说之中,并且是索洛与托宾对自然率假说所做早期检验的基础 {cite}`Solow1968,Tobin1968`。 + +在卢卡斯的批判中,它被塑造为*反派*角色——一种理性预期并不蕴含的天真限制——而在适应性模型中,归纳假说却又重新以*英雄*的身份出现:正是激活这一假说,才使得政府的费尔普斯问题呼唤出接近拉姆齐最优、低通货膨胀的政策。 + +我们的模拟所遵循的逃逸路径,恰恰就是政府所估计的模型——通过用单位根来近似一个常数——逐渐误入相信归纳假说的那些路径。 + +正是与此类近似问题的角力,以及同时存在若干个模型的情形,促使 {cite}`Sims1980` 将有限理性称为一片*荒野*,与理性预期那个整洁的单一模型世界截然不同。 + +### 保留意见 + +那么,究竟哪个故事才是正确的——胜利还是平反? + +这场争论并非理性预期与其替代方案之间的对立,因为*两个*故事都是有选择性地采用或放弃理性预期。 + +而平反的故事,无论它多么契合数据,都只是一项*实证*经济学的练习,而非*规范*经济学的论断。 + +人们很容易把书中长期出现的接近拉姆齐最优的通货膨胀,解读为对产生这种结果的适应性政策制定程序的一种肯定——但这种诱惑应当被抵制。 + +因为正是那使得稳定化得以实现的同一套均值动态,也同样保证了这种稳定化只是暂时的:一旦信念漂移到足够接近归纳假说,均值动态便开始指向*远离*它的方向,回到费尔普斯问题建议重新推高通货膨胀的那个区域。 + +模拟结果中既包含了看起来像保罗·沃尔克的长时段,也包含了看起来像亚瑟·伯恩斯的长时段。 + +{cite}`KydlandPrescott1977` 以及 {cite}`Rogoff1985` 之后的理论研究坚持认为,持久的低通货膨胀必须依赖于*承诺机制*,使货币当局无法逐期相机抉择——而不能寄希望于一个装备了近似模型的适应性政府,能够碰巧最终学会大致做正确的事情。 + +因此,本书的结尾留下的是一种期望,而非定论:我们*希望*胜利的故事才是正确的那一个——即政策制定者已经学到了自然率假说的正确理性预期版本,并找到了使自己承诺于低通货膨胀的手段。 + +因为如果平反的故事更接近真相,那么曾经把通货膨胀拉低的同一套均值动态,也始终等待着最终把它重新推高。 + +自 1999 年以来的这四分之一个世纪的数据——一段长期而平静的*大缓和*,中间被 2021-2022 年的骤然飙升所打断——正是对这一期望的一次持续检验,接下来我们将转向对它的探讨。 + +(phillips_after_1999)= +## 1999 年之后的数据模式 + +{cite}`Sargent1999` 写于始于沃尔克的长期反通货膨胀过程结束之际。 + +如今我们又有了四分之一个世纪的新数据。 + +本节将把书中最具启发性的图表延伸到当下,并探讨这些新的观测数据对这两个故事意味着什么。 + +让我们把样本扩展到最新可获得的月份。 + +```{code-cell} ipython3 +end_recent = datetime.datetime(2026, 7, 1) + +cpi_full = web.DataReader('CPIAUCNS', 'fred', start, end_recent)['CPIAUCNS'] +u_full = web.DataReader('LNS14000028', 'fred', start, end_recent)['LNS14000028'] + +# 原书所用的度量方式(月度变化年化值,13 个月居中移动平均) +inflation_full = 1200 * np.log(cpi_full).diff() +inflation_ma_full = inflation_full.rolling(13, center=True).mean() + +# 同比通货膨胀率:更为平滑,也是当今通常引用的度量方式 +inflation_yoy = 100 * (cpi_full / cpi_full.shift(12) - 1) +``` + +### 延伸后的兴与衰 + +图 1.1 展示了通货膨胀在 20 世纪 70 年代的上升以及在沃尔克治下的下降。 + +将其延伸至今,增添了原书所无法看到的三段历程:从 20 世纪 80 年代中期开始、通货膨胀低而稳定的*大缓和*时期;2008 年金融危机后,一段长期接近于零、并一度略低于零的时期;以及 2021-2022 年一次骤然飙升至 1981 年以来最高水平、随后又迅速回落的过程。 + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(11, 5)) +ax.plot(inflation_ma_full, lw=1) +ax.axhline(0, color='k', lw=0.5) +ax.axvspan(pd.Timestamp('1948-01-01'), pd.Timestamp('1999-01-01'), + color='C0', alpha=0.06, label="the book's window") +for date, y, txt in [('1980-03-01', 13.7, '1970s\nacceleration'), + ('1983-06-01', 3.0, 'Volcker'), + ('2009-07-01', -1.5, '2009\ndeflation scare'), + ('2022-06-01', 8.9, '2021-22\nsurge')]: + ax.annotate(txt, (pd.Timestamp(date), y), ha='center', fontsize=9, + color='C3') +ax.set_xlabel('year') +ax.set_ylabel('inflation (percent, annualized)') +ax.set_title('Inflation, CPI all items, 13-month centered moving average, ' + '1948-2026') +ax.legend(loc='upper right') +plt.show() +``` + +原书所要解释的那个驼峰,如今变成了*两个*驼峰中的第一个。 + +第二个驼峰出现在 2021-2022 年,是一段真正意义上全新的经历——一次快速的加速,随后又几乎同样迅速地实现了反通货膨胀,整个过程被压缩在大约三年之内。 + +### 延续至今的失业率与通货膨胀 + +图 1.2 绘制了战后时期这两个序列的对比图。 + +将其延伸后,展示了新数据中最引人注目的两大宏观经济事件:2020 年新冠疫情导致的失业率骤升——一度是大萧条以来的最高水平——以及随之而来的通货膨胀飙升。 + +```{code-cell} ipython3 +recent = slice('1990', None) + +fig, ax = plt.subplots(figsize=(11, 5)) +ax.plot(inflation_yoy[recent], 'C0', lw=1, label='inflation (CPI, year-over-year)') +ax.plot(u_full[recent], 'C1:', lw=1.2, label='unemployment (white men 20+)') +ax.axhline(0, color='k', lw=0.5) +ax.set_xlabel('year') +ax.set_ylabel('percent') +ax.set_title('Unemployment and inflation, 1990-2026') +ax.legend() +plt.show() +``` + +有两个特征十分突出。 + +从 20 世纪 90 年代中期到 2020 年,即使失业率大幅波动——在 90 年代末和 2019 年降至历史低点,又在 2008 年经济衰退中翻倍——通货膨胀却出奇地平静。 + +而在新冠疫情导致的失业率骤升之后,失业率又迅速回落,通货膨胀随即飙升——这一模式带有*供给*冲击的印记,而非经典菲利普斯曲线所描绘的那种需求驱动型权衡关系。 + +### 三个时代中的菲利普斯曲线 + +原书从 1960-1982 年的数据中提炼出了一条菲利普斯曲线。 + +1999 年之后最引人注目的模式,是通货膨胀与失业率的散点图在不同时代之间表现出的*不稳定性*。 + +我们将样本划分为原书所涉及的加速时期、大缓和时期,以及 2008 年之后的时期,并在每个时期分别绘制通货膨胀对失业率的散点图。 + +```{code-cell} ipython3 +scatter_data = pd.concat([inflation_yoy.rename('inflation'), + u_full.rename('unemployment')], axis=1).dropna() + +eras = [('1960', '1983', '1960-1983 (acceleration)'), + ('1984', '2007', '1984-2007 (Great Moderation)'), + ('2008', None, '2008-2026 (crisis, COVID, surge)')] + +fig, axes = plt.subplots(1, 3, figsize=(14, 4.5), sharex=True, sharey=True) +for ax, (lo, hi, title) in zip(axes, eras): + era_data = scatter_data.loc[lo:hi] + ax.scatter(era_data['unemployment'], era_data['inflation'], s=8, alpha=0.5) + ax.axhline(0, color='k', lw=0.5) + ax.set_xlabel('unemployment') + ax.set_title(title, fontsize=10) +axes[0].set_ylabel('inflation (year-over-year)') +plt.tight_layout() +plt.show() +``` + +这三片散点云的样貌几乎不可能相差更大。 + +在 1960-1983 年间,数据点散布在一个很宽的通货膨胀率范围内——这正是预期不断变化、菲利普斯曲线呈现*回路*形态的时代。 + +在 1984-2007 年间,它们收缩成一团紧密、低位、近乎平坦的点云——这就是大缓和时期,此时通货膨胀几乎对失业率毫无反应。 + +自 2008 年以来,这种关系瓦解成一片由两个离群点主导的散点:一个是新冠疫情引发的经济衰退,其特征是两位数的失业率与依然偏低的通货膨胀;另一个是 2021-2022 年的飙升,其特征是高通货膨胀与低失业率。 + +无论菲利普斯曲线究竟是什么,它都不是一种稳定的结构性关系——这恰恰正是促使本书提出*漂移信念*这一说法的那种不稳定性。 + +### 新数据对这两个故事意味着什么 + +这额外的四分之一个世纪的数据,既没有干净利落地推翻其中任何一个故事,也没有干净利落地证实它们,但它使两者都变得更加清晰。 + +**对自然率理论的胜利而言。** +大缓和时期可以被解读为这场胜利的最终完成:随着自然率共识的确立以及央行独立性的确立,通货膨胀在整整一代人的时间里保持低位,预期也保持*锚定*。 + +用本书的语言来说,经济安顿进入了一个低通货膨胀的自我确认均衡,并一直停留在那里。 + +即便是 2021-2022 年的飙升,按照这种解读,也支持了胜利的故事:一旦美联储采取果断行动,通货膨胀便迅速回落,长期预期从未失去锚定——低通货膨胀均衡经受住了一次巨大冲击的考验。 + +**对计量经济学政策评估的平反而言。** +这次飙升也提醒我们,货币当局的*模型*仍然可能误导它:2021 年广泛流行的"通货膨胀只是暂时的"观点,正是一个被数据证伪了的模型,而政策只是在信念发生转变之后才随之调整。 + +2020 年之前那十年近乎零通货膨胀的时期——那条看似*平坦*的菲利普斯曲线,既没有出现 2009-2013 年"消失的反通货膨胀",也没有出现 2015-2019 年"消失的通货膨胀",都不符合一条稳定曲线——恰恰正是本书中适应性政府会实时追踪其斜率和截距不断变化的那种漂移型经验关系。 + +```{note} +本书自身也会坚持提出这样一个警示:其机制假设*基本面*——即真实的数据生成过程——是稳定的,因此所有的作用都来自政府不断演化的信念。而 2021-2022 年这一事件涉及了真实的供给冲击(疫情引发的中断、能源价格),这已超出了该假设的范围。将信念的转变与基本面的转变区分开来,正是使这段历史如此难以捉摸、也如此引人入胜的那个识别问题。 +``` + +本系列后续讲座中所建立的工具——自我确认均衡、漂移系数以及逃逸动态——仍然是探讨新数据所提出的这一问题的一种自然语言:一个可信的低通货膨胀均衡,是否会在每次冲击之后重新锚定,还是说一连串的意外仍可能使信念重新开始漂移,就像 1965 年之后所发生的那样? + +最后一讲,{doc}`phillips_lost_conquest`,正是把这些工具应用于 2021-2022 年的飙升,并探讨了为什么美联储的反应如此迟缓。 + +## 练习 + +```{exercise-start} +:label: ts_ex1 +``` + +"聚焦于商业周期成分使得表面上的菲利普斯曲线更加清晰"这一论断,可以被定量地表述出来。 + +计算 1960-1982 年期间通货膨胀与失业率之间的相关系数,分别针对 + +* 原始序列(如图 1.4 所示),以及 +* 巴克斯特-金商业周期成分(如图 1.5 所示)。 + +带通滤波将负向的菲利普斯相关性锐化了多少? + +```{exercise-end} +``` + +```{solution-start} ts_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +corr_raw = data.loc[sub].corr().iloc[0, 1] +corr_cycle = bk.loc[sub].corr().iloc[0, 1] + +print(f"raw correlation, 1960-1982 : {corr_raw:+.2f}") +print(f"business-cycle correlation, 1960-82: {corr_cycle:+.2f}") +``` + +在原始序列中,相关系数接近于零:菲利普斯曲线的不利*移动*——即自然率理论所强调的那种缓慢移动的预期成分——淹没了商业周期层面的权衡关系。 + +一旦滤除这些低频移动,一种强烈的负相关关系便显现出来,证实了菲利普斯权衡关系是在商业周期频率上发挥作用的。 + +```{solution-end} +``` \ No newline at end of file From 742a6689169373c7d7f64b763fb27203fabc7465 Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:26 +1000 Subject: [PATCH 18/21] Update translation: .translate/state/phillips_two_stories.md.yml --- .translate/state/phillips_two_stories.md.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .translate/state/phillips_two_stories.md.yml diff --git a/.translate/state/phillips_two_stories.md.yml b/.translate/state/phillips_two_stories.md.yml new file mode 100644 index 0000000..4e4bbb3 --- /dev/null +++ b/.translate/state/phillips_two_stories.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 8 +tool-version: 0.23.0 From c34b5f61a021c7f2ccf7e1425bfc02ed256b08be Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 07:54:26 +1000 Subject: [PATCH 19/21] Update translation: lectures/_toc.yml --- lectures/_toc.yml | 66 +++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 22 deletions(-) diff --git a/lectures/_toc.yml b/lectures/_toc.yml index 6fce846..e16fd96 100644 --- a/lectures/_toc.yml +++ b/lectures/_toc.yml @@ -1,7 +1,7 @@ format: jb-book root: intro parts: -- caption: 基础工具 +- caption: Tools and Techniques numbered: true chapters: - file: sir_model @@ -11,7 +11,7 @@ parts: - file: svd_intro - file: var_dmd - file: newton_method -- caption: 基础统计学 +- caption: Elementary Statistics numbered: true chapters: - file: prob_matrix @@ -24,13 +24,13 @@ parts: - file: back_prop - file: rand_resp - file: util_rand_resp -- caption: 贝叶斯定律 +- caption: Bayes Law numbered: true chapters: - file: bayes_nonconj - file: ar1_bayes - file: ar1_turningpts -- caption: 统计与信息论 +- caption: Statistics and Information numbered: true chapters: - file: divergence_measures @@ -48,12 +48,12 @@ parts: - file: navy_captain - file: merging_of_opinions - file: survival_recursive_preferences -- caption: 线性规划 +- caption: Linear Programming numbered: true chapters: - file: opt_transport - file: von_neumann_model -- caption: 动态系统导论 +- caption: Introduction to Dynamics numbered: true chapters: - file: finite_markov @@ -65,10 +65,10 @@ parts: - file: wealth_dynamics - file: kalman - file: kalman_2 - - file: kalman_filter_var + - file: kalman_filter_var - file: organization_capital - file: measurement_models -- caption: 搜索 +- caption: Search numbered: true chapters: - file: mccall_model @@ -78,30 +78,31 @@ parts: - file: mccall_persist_trans - file: career - file: jv - - file: mccall_q - file: odu +- caption: Reinforcement Learning + numbered: true + chapters: - file: inventory_q - file: rs_inventory_q -- caption: 消费、储蓄与资本 + - file: mccall_q +- caption: Introduction to Optimal Savings numbered: true chapters: - - file: cass_koopmans_1 - - file: cass_koopmans_2 - - file: cass_fiscal - - file: cass_fiscal_2 - - file: ak2 - file: os - file: os_numerical - file: os_stochastic - file: os_time_iter - file: os_egm - file: os_egm_jax +- caption: Household Problems + numbered: true + chapters: - file: ifp_discrete - file: ifp_opi - file: ifp_egm - file: ifp_egm_transient_shocks - file: ifp_advanced -- caption: LQ控制 +- caption: LQ Control numbered: true chapters: - file: lqcontrol @@ -116,7 +117,27 @@ parts: - file: lq_bewley_complete_markets - file: lq_robust_smoothing - file: lq_inventories -- caption: 多主体模型 +- caption: Phillips Curve Tradeoffs + numbered: true + chapters: + - file: phillips_two_stories + - file: phillips_credibility + - file: phillips_adaptive + - file: phillips_misspecified + - file: phillips_self_confirming + - file: phillips_learning + - file: phillips_escaping_nash + - file: phillips_priors + - file: phillips_lost_conquest + - file: phillips_drifts_volatilities +- caption: Optimal Growth + numbered: true + chapters: + - file: cass_koopmans_1 + - file: cass_koopmans_2 + - file: cass_fiscal + - file: cass_fiscal_2 +- caption: Multiple Agent Models numbered: true chapters: - file: lake_model @@ -127,9 +148,10 @@ parts: - file: uncertainty_traps - file: aiyagari - file: aiyagari_egm + - file: ak2 - file: ak_aiyagari - file: two_computation -- caption: 资产定价与金融 +- caption: Asset Pricing and Finance numbered: true chapters: - file: markov_asset @@ -144,7 +166,7 @@ parts: - file: ross_recovery - file: long_run_risk_operator - file: misspecified_recovery -- caption: 数据与实证 +- caption: Data and Empirics numbered: true chapters: - file: pandas_panel @@ -152,14 +174,14 @@ parts: - file: mle - file: unemployment_linear - file: unemployment_shocks -- caption: 拍卖 +- caption: Auctions numbered: true chapters: - file: two_auctions - file: house_auction -- caption: 其他 +- caption: Other numbered: true chapters: - file: troubleshooting - file: zreferences - - file: status \ No newline at end of file + - file: status From 08f7d48d03ef39723677427646e458acc386899c Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 08:59:11 +1000 Subject: [PATCH 20/21] Add phillips_lost_conquest, the lecture the sync run failed to translate The sync for source PR #992 processed ten new lectures; nine succeeded and lectures/phillips_lost_conquest.md failed the structural parity check with its directive sequence scrambled and the (phillips_lost_conquest)= anchor dropped. The run committed _toc.yml naming it anyway, and four of the nine siblings cross-reference it, so the build failed with six dangling references (QuantEcon/action-translation#156). Retranslated with the v0.23.0 CLI against the same source commit (370a58f) and the same 357-term glossary. The CLI output needed the wrapper repaired by hand: both attempts wrapped the whole document in a bare code fence and derived translation.title from a figure caption rather than the H1, which is QuantEcon/action-translation#118 still reproducing at v0.23.0. The body itself was sound in both runs; only the frontmatter/fence wrapper was rebuilt, to match the convention the nine sibling files already use. Validated against the English source: directive sequence 28/28 in order, anchors, heading count and levels, code-cell count, display-math count, fence balance, and every {doc}/{cite} link target identical. section-count 7 matches the H2 count, consistent with the siblings. --- .../state/phillips_lost_conquest.md.yml | 6 + lectures/phillips_lost_conquest.md | 490 ++++++++++++++++++ 2 files changed, 496 insertions(+) create mode 100644 .translate/state/phillips_lost_conquest.md.yml create mode 100644 lectures/phillips_lost_conquest.md diff --git a/.translate/state/phillips_lost_conquest.md.yml b/.translate/state/phillips_lost_conquest.md.yml new file mode 100644 index 0000000..2242d8f --- /dev/null +++ b/.translate/state/phillips_lost_conquest.md.yml @@ -0,0 +1,6 @@ +source-sha: 370a58fa8dd0bcac220f17a59afbfb2716d04e1e +synced-at: "2026-07-23" +model: claude-sonnet-5 +mode: NEW +section-count: 7 +tool-version: 0.23.0 diff --git a/lectures/phillips_lost_conquest.md b/lectures/phillips_lost_conquest.md new file mode 100644 index 0000000..7ada20d --- /dev/null +++ b/lectures/phillips_lost_conquest.md @@ -0,0 +1,490 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.16.7 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +translation: + title: 失落的征服:2020 年代的美联储政策 + headings: + Overview: 概览 + The three elements: 三个要素 + The Fed's drifting-coefficients beliefs: 美联储的漂移系数信念 + The Fed's Phelps problem: 美联储的菲尔普斯问题 + 'Why the Fed was slow: a counterfactual': 美联储为何反应缓慢:一个反事实分析 + 'A self-confirming equilibrium: nature''s New Keynesian model': 一个自我确认均衡:自然界的新凯恩斯主义模型 + 'A self-confirming equilibrium: nature''s New Keynesian model::The trap': 陷阱 + Exercises: 练习 +--- + +(phillips_lost_conquest)= +```{raw} jupyter + +``` + +# 失落的征服:2020 年代的美联储政策 + +```{contents} Contents +:depth: 2 +``` + +除了 Anaconda 中已有的库之外,本讲座还将使用以下库从 FRED 下载数据: + +```{code-cell} ipython3 +:tags: [hide-output] + +!pip install pandas_datareader +``` + +## 概览 + +本讲座是《菲利普斯曲线权衡》系列的当代续篇。 + +它遵循 {cite}`SargentWilliams2025` 的思路,将 {doc}`phillips_learning` 和 {doc}`phillips_priors` 中的工具——{doc}`菲尔普斯控制问题 `、一个*预期效用*政府、一个通过*常增益递归最小二乘法*估计的*漂移系数*模型,以及一个*自我确认均衡*——运用到 2020 年代的通货膨胀问题上。 + +这是一个仍在持续的谜题。 + +在 COVID-19 大流行之后,美国通货膨胀率飙升至上世纪 80 年代初以来的最高水平——这正是我们在 {doc}`phillips_two_stories` 的 1999 年后数据中绘制的那段情节。 + +然而,联邦储备委员会(美联储)超过一年时间没有作出反应;直到 2022 年,在通货膨胀已接近峰值时,它才开始积极加息。 + +美联储为何反应如此迟缓? + +{cite}`SargentWilliams2025` 构建了一个*人工美联储*,它在每一期都会: + +* 通过常增益递归最小二乘法重新估计一条漂移系数的菲利普斯曲线,并且 +* 在预期效用假设下——按照 {cite}`Kreps1998` 的意义——求解一个线性二次型菲尔普斯问题,以设定其利率工具。 + +这是一种“模型预测控制”:与推动 {doc}`phillips_learning` 中学习型政府的*先估计再优化*循环相同,只是现在的工具变成了政策利率,而信念所涉及的是通货膨胀的*持续性*和菲利普斯曲线的*斜率*。 + +三个漂移的信念最终解释了这种缓慢的反应: + +1. **通货膨胀持续性下降**——美联储已经了解到通货膨胀冲击消退得很快,因此这次飙升看起来是*暂时性的*。 +2. **更平坦的菲利普斯曲线**——美联储已经了解到通货膨胀对经济松弛的反应很弱,因此抑制通货膨胀看起来*代价高昂*。 +3. **实时产出缺口的测量误差**——美联储所感知到的经济松弛程度比实际情况更大。 + +我们从公开数据中重现前两个信念,展示它们如何生成一条能够追踪实际联邦基金利率的菲尔普斯规则,然后——遵循论文中的新凯恩斯主义附录——提出一个自我确认均衡的问题:*美联储的良性信念是否是其自身过去成功的结果?* + +让我们导入所需的库: + +```{code-cell} ipython3 +import matplotlib.pyplot as plt +import matplotlib as mpl # i18n +FONTPATH = "_fonts/SourceHanSerifSC-SemiBold.otf" # i18n +mpl.font_manager.fontManager.addfont(FONTPATH) # i18n +mpl.rcParams['font.family'] = ['Source Han Serif SC'] # i18n +import numpy as np +import pandas as pd +import datetime +from pandas_datareader import data as web +from scipy.linalg import solve_discrete_are +``` + +## 三个要素 + +前两个要素是现代宏观经济学中记录最为详实的事实之一。 + +**持续性下降。** +从 20 世纪 70 年代到 80 年代,通货膨胀具有很强的持续性;一次冲击会使通货膨胀持续数年之久。 +{cite}`CogleySargentConquest2005` 和 {cite}`StockWatson2007` 记录了 20 世纪 80 年代中期之后持续性的显著下降——通货膨胀开始更快地回归目标值。 + +**更平坦的菲利普斯曲线。** +自 20 世纪 90 年代以来,菲利普斯曲线斜率的估计值趋于零——大衰退之后的“消失的反通胀”便是最典型的例子。 +这两个事实都曾出现在政策制定者的脑海中。 +前美联储主席珍妮特·耶伦在 2019 年曾指出:“菲利普斯曲线的斜率……自 20 世纪 60 年代以来已显著下降……而且……通货膨胀的持续性已大大降低。” +正如 {cite}`Bernanke2022` 所写:“平坦的菲利普斯曲线意味着通货膨胀作为经济过热的指标可靠性降低了,将通货膨胀重新降至目标水平所需付出的失业代价,可能比过去更高。” + +**实时不确定性。** +{cite}`Orphanides2001` 强调的第三个要素是,产出缺口在*实时*中会被严重误测,尤其是在商业周期的转折点。 +在 2020 年至 2023 年间,实时缺口持续*低于*后来修订后的度量值,因此美联储感知到了更多的经济松弛——这强化了通货膨胀会自行消退的信念。 +我们在下文使用当前版本的数据,并在结论部分回到实时数据的区别问题上。 + +## 美联储的漂移系数信念 + +我们赋予人工美联储一条具有漂移系数的前瞻性菲利普斯曲线: + +```{math} +:label: lc_pc + +\pi_t = \alpha_{0,t} + \rho_t\, \pi_{t-1} + \kappa_t\, x_t + \varepsilon^{\pi}_t , +``` + +其中 $\pi_t$ 是通货膨胀率,$x_t$ 是产出缺口,$\rho_t$ 是*感知的持续性*,$\kappa_t$ 是*感知的斜率*。 + +美联储通过常增益递归最小二乘法更新 $\theta_t = (\alpha_{0,t}, \rho_t, \kappa_t)$——这正是 {doc}`phillips_learning` 和 {doc}`phillips_priors` 中的算法,增益 $\gamma$ 对过去的数据进行折扣,从而使估计值能够*追踪*漂移: + +$$ +\theta_{t+1} = \theta_t + \gamma R_t^{-1} X_t\left(\pi_t - X_t'\theta_t\right), +\qquad +R_{t+1} = R_t + \gamma\left(X_t X_t' - R_t\right), +$$ + +其中 $X_t = (1, \pi_{t-1}, x_t)'$。 + +我们从 FRED 下载季度个人消费支出(PCE)通货膨胀率、国会预算办公室(CBO)产出缺口和联邦基金利率。 + +```{code-cell} ipython3 +start, end = datetime.datetime(1959, 1, 1), datetime.datetime(2025, 7, 1) + +pcepi = web.DataReader('PCEPI', 'fred', start, end)['PCEPI'].resample('QS').mean() +gdp = web.DataReader('GDPC1', 'fred', start, end)['GDPC1'] # 实际 GDP +pot = web.DataReader('GDPPOT', 'fred', start, end)['GDPPOT'] # CBO 潜在产出 +ff = web.DataReader('FEDFUNDS', 'fred', start, end)['FEDFUNDS'].resample('QS').mean() + +inflation = 100 * (pcepi / pcepi.shift(4) - 1) # 同比 PCE 通货膨胀率 +gap = 100 * (gdp / pot - 1) # 产出缺口,百分比 + +data = pd.concat([inflation.rename('pi'), gap.rename('x'), + ff.rename('i')], axis=1).dropna() +print(f"样本区间:{data.index[0].date()} 至 {data.index[-1].date()}," + f"共 {len(data)} 个季度") +``` + +遵循原论文的做法,我们在 2020-2021 年冻结信念(将增益设为零),因为疫情期间的观测值是极端异常值,否则会使估计值剧烈波动;信念更新在 2022 年恢复。 + +```{code-cell} ipython3 +def estimate_beliefs(data, gain=0.03, freeze=(2020, 2021)): + "对漂移菲利普斯曲线进行常增益递归最小二乘估计;返回 α₀、ρ、κ 路径。" + pi, x = data['pi'].values, data['x'].values + θ = np.array([0.5, 0.9, 0.05]) # [截距,持续性,斜率] + R = np.diag([1.0, 10.0, 5.0]) + rows = [] + for t in range(1, len(data)): + g = 0.0 if data.index[t].year in freeze else gain + X = np.array([1.0, pi[t - 1], x[t]]) + err = pi[t] - X @ θ + R = R + g * (np.outer(X, X) - R) + θ = θ + g * np.linalg.solve(R, X * err) + rows.append((θ[0], θ[1], θ[2])) + return pd.DataFrame(rows, index=data.index[1:], + columns=['alpha0', 'rho', 'kappa']) + +beliefs = estimate_beliefs(data) +``` + +```{code-cell} ipython3 +fig, axes = plt.subplots(2, 1, figsize=(10, 6), sharex=True) +axes[0].plot(beliefs['rho']) +axes[0].axhline(1, color='k', lw=0.5, ls=':') +axes[0].set_ylabel('持续性 $\\rho_t$') +axes[0].set_title('感知的通货膨胀持续性') + +axes[1].plot(beliefs['kappa'], color='C1') +axes[1].axhline(0, color='k', lw=0.5, ls=':') +axes[1].set_ylabel('斜率 $\\kappa_t$') +axes[1].set_xlabel('年份') +axes[1].set_title('感知的菲利普斯曲线斜率') + +plt.tight_layout() +plt.show() +``` + +这两幅图讲述了这个故事。 + +在通货膨胀高企的 20 世纪 70 年代和 80 年代,感知的**持续性** $\rho_t$ 接近 1,随后在 80 年代中期之后逐渐下降,在 2008 年之后触底——然后在 2022 年信念更新恢复时*又跳回*接近 1 的水平,恰好也是美联储放弃“暂时性”表述并开始收紧政策的时候。 + +感知的**斜率** $\kappa_t$ 在整个 2010 年代趋向于零:菲利普斯曲线趋于平坦。 + +到 2019 年,美联储的模型认为通货膨胀*并非持续性的*,且*与经济松弛的联系较弱*——这些信念在输入到菲尔普斯问题后,会得出建议保持耐心的结论。 + +## 美联储的菲尔普斯问题 + +美联储在每一期通过求解一个线性二次型菲尔普斯问题来设定其政策利率,将其*当前*的估计值视为将永远成立——这正是我们在 {doc}`phillips_learning` 中遇到的 {cite}`Kreps1998` 的预期效用假设。 + +将信念菲利普斯曲线 {eq}`lc_pc` 与一条固定的“IS 曲线” $x_t = b_0 + b_1 x_{t-1} + g(i_{t-1} - \pi_{t-1}) + \varepsilon^x_t$ 相配对,可以得到状态 $X_t = (1, \pi_t, x_t, i_{t-1})'$ 的线性动态: + +$$ +X_{t+1} = A_t X_t + B_t\, i_t + C \varepsilon_{t+1}, +$$ + +其矩阵取决于第 $t$ 期的信念。 + +美联储最小化以下目标: + +```{math} +:label: lc_loss + +\mathbb E_t \sum_{s=t}^{\infty}\beta^{s-t} +\Big[ (\pi_s - \pi^*)^2 + \lambda_x\, x_s^2 + \eta\,(i_s - i_{s-1})^2 \Big], +``` + +其中 $\pi^*$ 是 2% 的目标值,最后一项对利率的突然变化施加惩罚。 + +这是一个带有交叉项的贴现线性二次型调节器问题;其解为一条*平滑化的泰勒规则* $i_t = -F_t X_t$,其系数会随着信念的变化而变化。 + +```{code-cell} ipython3 +# 固定 IS 曲线,通过对全样本进行一次性 OLS 估计得到 +pi, x, i_ = data['pi'].values, data['x'].values, data['i'].values +n = len(data) +X_is = np.column_stack([np.ones(n - 1), x[:-1], i_[:-1] - pi[:-1]]) +b0, b1, g = np.linalg.lstsq(X_is, x[1:], rcond=None)[0] + +β, π_star, λ_x, η = 0.95, 2.0, 0.2, 0.5 + +def phelps_rate(θ, state): + "在给定信念 θ=(α₀,ρ,κ) 和状态的情况下计算(主观上)最优的联邦基金利率。" + α0, ρ, κ = θ + A = np.array([[1, 0, 0, 0], + [α0 + κ * b0, ρ - κ * g, κ * b1, 0], + [b0, -g, b1, 0], + [0, 0, 0, 0]], float) + B = np.array([[0], [κ * g], [g], [1]], float) + c_π = np.array([-π_star, 1, 0, 0.]) # π − π* + c_x = np.array([0, 0, 1, 0.]) # x + e_i = np.array([0, 0, 0, 1.]) # i_{-1} + Q = np.outer(c_π, c_π) + λ_x * np.outer(c_x, c_x) + η * np.outer(e_i, e_i) + N = (-η * e_i).reshape(4, 1) + R = np.array([[η]]) + sb = np.sqrt(β) + P = solve_discrete_are(sb * A, sb * B, Q, R, s=sb * N) + F = np.linalg.solve(R + β * B.T @ P @ B, β * B.T @ P @ A + N.T) + return max((-F @ state).item(), 0.0) # 施加零利率下限 +``` + +```{code-cell} ipython3 +θ = np.array([0.5, 0.9, 0.05]) +R = np.diag([1.0, 10.0, 5.0]) +gain = 0.03 +opt, θ_2000 = [], None +for t in range(1, n): + yr = data.index[t].year + g_t = 0.0 if yr in (2020, 2021) else gain + X = np.array([1.0, pi[t - 1], x[t]]) + R = R + g_t * (np.outer(X, X) - R) + θ = θ + g_t * np.linalg.solve(R, X * (pi[t] - X @ θ)) + if data.index[t].year == 2000 and θ_2000 is None: + θ_2000 = θ.copy() # 保存用于反事实分析的信念 + state = np.array([1.0, pi[t], x[t], i_[t - 1]]) + opt.append(phelps_rate(θ, state)) + +optimal = pd.Series(opt, index=data.index[1:]) +``` + +```{code-cell} ipython3 +fig, ax = plt.subplots(figsize=(10, 4.5)) +window = slice('1991', None) +ax.plot(optimal[window], 'C0', label="菲尔普斯问题的建议利率") +ax.plot(data['i'][window], 'C3', lw=1, label='实际联邦基金利率') +ax.set_xlabel('年份') +ax.set_ylabel('百分比') +ax.set_title("信念驱动的菲尔普斯规则与实际政策对比") +ax.legend() +plt.show() + +corr = np.corrcoef(optimal['1991':], data['i']['1991':optimal.index[-1]])[0, 1] +print(f"1991-2025 年建议利率与实际利率的相关性:{corr:.2f}") +``` + +在长达三十年的时间跨度里,主观最优利率追踪了实际政策的水平和转折点(相关性约为 0.95):20 世纪 90 年代末的紧缩、2001 年的宽松、2008 年之后的零利率时代,以及 2015 年的政策正常化。 + +关键的是,在 2021 年通货膨胀飙升期间,建议利率几乎没有变动——信念驱动的规则*同样*建议缓慢作出反应,仅在 2022 年才开始收紧,与美联储的实际行为如出一辙。 + +## 美联储为何反应缓慢:一个反事实分析 + +为了分离出漂移信念所起的作用,我们重新计算菲尔普斯建议利率,这次将信念*固定*在 2000 年 1 月的取值上——当时人们仍然认为通货膨胀具有持续性,且菲利普斯曲线更陡峭。 + +```{code-cell} ipython3 +counterfactual = pd.Series( + [phelps_rate(θ_2000, np.array([1.0, pi[t], x[t], i_[t - 1]])) + for t in range(1, n)], + index=data.index[1:]) + +fig, ax = plt.subplots(figsize=(10, 4.5)) +w = slice('2015', None) +ax.plot(optimal[w], 'C0', label='基准情形(漂移信念)') +ax.plot(counterfactual[w], 'C1--', label='反事实情形(信念冻结于 2000 年)') +ax.plot(data['i'][w], 'C3', lw=1, alpha=0.7, label='实际联邦基金利率') +ax.set_xlabel('年份') +ax.set_ylabel('百分比') +ax.set_title('反事实分析:一个自 2000 年以来未曾更新信念的美联储') +ax.legend() +plt.show() +``` + +对比结果十分鲜明。 + +一个持有 2000 年信念的美联储——认为通货膨胀具有持续性且菲利普斯曲线更陡峭——本应在 2021 年*立即而剧烈地*收紧政策,在实际美联储尚未采取任何行动之前,就将联邦基金利率推高至远超 4% 的水平。 + +这种温和而滞后的反应,并非目标的改变,而是*信念*的改变。 + +由于将通货膨胀视为暂时性,将菲利普斯曲线视为平坦,美联储自身的菲尔普斯问题告诉它应当耐心等待。 + +## 一个自我确认均衡:自然界的新凯恩斯主义模型 + +这些良性信念是*正确的*吗? + +在这里,原论文加入了一个转折,它直接与 {doc}`phillips_self_confirming` 和 {doc}`phillips_escaping_nash` 相联系:一个**自我确认均衡**,其中美联储关于菲利普斯曲线平坦、持续性低的信念,是其*自身过去激进政策的结果*。 + +假设自然实际上运行着一个小型的新凯恩斯主义模型: + +```{math} +:label: lc_nk + +\begin{aligned} +\pi_t &= \beta\, \mathbb E_t \pi_{t+1} + \gamma_b\, \pi_{t-1} + \kappa\, x_t + u_t, \\ +x_t &= \mathbb E_t x_{t+1} - \sigma\left(i_t - \mathbb E_t \pi_{t+1} - r^n_t\right), \\ +i_t &= \phi_\pi\, \pi_t , +\end{aligned} +``` + +其结构斜率为 $\kappa$,泰勒规则的激进程度为 $\phi_\pi$。 + +在其最小状态变量理性预期均衡中,$\mathbb E_t \pi_{t+1} = \lambda\, \pi_t$,其中 $\lambda$——即计量经济学家能够恢复的*测量*持续性——是取决于 $\phi_\pi$ 的一个三次方程的稳定根。 + +原论文证明了两个比较静态结果。 + +```{prf:proposition} 激进的政策降低了测量的持续性 +:label: lc_prop1 + +在确定性区域内,稳定根 $\lambda(\phi_\pi)$ 严格随着政策激进程度 $\phi_\pi$ 的增加而下降:更加激进的美联储会使通货膨胀*看起来*不那么持续。 +``` + +```{prf:proposition} 激进的政策使测量的斜率变得平坦 +:label: lc_prop2 + +在满足一定条件下(滞后通货膨胀项较小,且规则足够激进),前瞻性菲利普斯曲线的总体 OLS 斜率也会随着 $\phi_\pi$ 的增加而下降:更加激进的美联储会使菲利普斯曲线*看起来*更加平坦。 +``` + +让我们通过求解三次方程的稳定根来重现 {prf:ref}`lc_prop1`。 + +```{code-cell} ipython3 +def measured_persistence(φ_π, β=0.99, γ_b=0.5, κ=0.1, σ=1.0): + "稳定的最小状态变量根 λ(φ_π):计量经济学家将测得的持续性。" + coeffs = [β, -(1 + β + κ * σ), 1 + γ_b + κ * σ * φ_π, -γ_b] + roots = np.roots(coeffs) + real = roots[np.abs(roots.imag) < 1e-9].real + stable = real[np.abs(real) < 1.0] + return stable[np.argmin(np.abs(stable))] + +φ_grid = np.linspace(1.05, 3.0, 40) +λ_path = [measured_persistence(φ) for φ in φ_grid] + +fig, ax = plt.subplots(figsize=(8, 4.5)) +ax.plot(φ_grid, λ_path) +ax.set_xlabel(r'泰勒规则激进程度 $\phi_\pi$') +ax.set_ylabel(r'测量的持续性 $\lambda$') +ax.set_title('激进的政策使通货膨胀看起来持续性更低') +plt.show() +``` + +随着政策变得愈发激进,测量的持续性从接近 1 下降到大约二分之一。 + +这两个命题背后的直觉是*政策的内生性*,这一点被 {cite}`McLeayTenreyro2019` 所强调:当美联储及时抵消通货膨胀压力时,一个将产出缺口视为外生驱动因素的回归分析,所恢复出的斜率会*更小*,通货膨胀过程的*均值回归速度*也会比结构参数所暗示的*更快*。 + +### 陷阱 + +现在,将 {eq}`lc_nk` 视为自然界的真实模型,将前几节的漂移系数模型视为美联储的*近似*模型。 + +在一条持续激进的政策路径上——沃尔克-格林斯潘式的征服——美联储所产生的数据会使通货膨胀*看起来*是暂时性的,菲利普斯曲线*看起来*是平坦的。 + +在估计其前瞻性模型时,美联储便真的相信了这一点。 + +这些信念在 {doc}`phillips_self_confirming` 意义上构成了一个**自我确认均衡**:在美联储*当前*的激进政策下,其简化形式模型与自然界的新凯恩斯主义模型在观测上是等价的。 + +但这些信念在*均衡路径之外是错误的*——在*不那么*激进的政策下,持续性和斜率会重新回升。 + +美联储无法看到这一点,因为它没有理由去进行试验:它陷入了 {doc}`phillips_learning` 中所描述的**缺乏试验的陷阱**,其自满情绪由一个关于它从未执行过的政策的信念所支撑。 + +当疫情后的巨大冲击最终来袭时,这些自我确认的信念告诉美联储,这次飙升是暂时性的,收紧政策代价高昂——于是,这场征服在一段时间内*失落了*。 + +这是《征服》一书中反复出现的动态在更高层次上的一次现代重演:这一机制现在通过菲利普斯曲线感知的斜率和持续性,以及政策利率工具发挥作用,而误设并非关于预期,而是关于美联储将简化形式菲利普斯曲线视为结构性的这一*政策内生性*问题——正如 {doc}`phillips_two_stories` 中所描述的“平反”故事那样,忽视了卢卡斯批判。 + +```{note} +正如 {cite}`SargentWilliams2025` 所指出的,漂移系数模型纯粹是一个描述性的“开普勒阶段”模型,而非结构性的“牛顿阶段”模型。原论文也承认了另一种解读方式,即 2020 年代的宽松政策起源于财政因素——参见其所引用的财政理论论述——这是对同一政策路径的一种截然不同的解释。 +``` + +## 练习 + +```{exercise-start} +:label: lc_ex1 +``` + +在损失函数 {eq}`lc_loss` 中的利率平滑权重 $\eta$,用原论文的话来说,是“最重要的参数之一”。 + +请针对 $\eta \in \{0.1, 0.5, 2.0\}$ 重新计算基准菲尔普斯建议利率,并将其与 2015-2025 年间的实际联邦基金利率进行对比绘图。 + +更大的平滑惩罚如何改变建议政策的特征? + +```{exercise-end} +``` + +```{solution-start} lc_ex1 +:class: dropdown +``` + +```{code-cell} ipython3 +def recommend(θ_path_fn, η_val): + global η + η_save = η + η = η_val + θ, R = np.array([0.5, 0.9, 0.05]), np.diag([1.0, 10.0, 5.0]) + out = [] + for t in range(1, n): + g_t = 0.0 if data.index[t].year in (2020, 2021) else gain + X = np.array([1.0, pi[t - 1], x[t]]) + R = R + g_t * (np.outer(X, X) - R) + θ = θ + g_t * np.linalg.solve(R, X * (pi[t] - X @ θ)) + out.append(phelps_rate(θ, np.array([1.0, pi[t], x[t], i_[t - 1]]))) + η = η_save + return pd.Series(out, index=data.index[1:]) + +fig, ax = plt.subplots(figsize=(10, 4.5)) +w = slice('2015', None) +for η_val in [0.1, 0.5, 2.0]: + ax.plot(recommend(None, η_val)[w], lw=1, label=rf'$\eta = {η_val}$') +ax.plot(data['i'][w], 'k:', lw=1.5, label='实际利率') +ax.set_xlabel('年份') +ax.set_ylabel('百分比') +ax.legend() +plt.show() +``` + +较小的 $\eta$ 会产生随着通货膨胀和产出缺口剧烈波动的利率;较大的 $\eta$ 会使建议利率紧贴滞后利率,从而更好地拟合观测到的平滑路径,但代价是可解释性降低。 + +中间取值取得了一种平衡——足够的平滑性使其类似于真实的美联储行为,但仍能识别出对经济状态的合理反应。 + +```{solution-end} +``` + +```{exercise-start} +:label: lc_ex2 +``` + +{prf:ref}`lc_prop1` 指出,激进的泰勒规则会降低通货膨胀*测量的*持续性。 + +通过结合本讲座的两个部分,追踪这一结论对美联储自身政策的影响:对于结构性激进程度 $\phi_\pi$ 的一个网格,计算测量的持续性 $\lambda(\phi_\pi)$,然后将具有该持续性的信念(保持斜率和截距不变)输入到某个代表性状态下的 `phelps_rate` 中,并报告所隐含的通货膨胀反应。 + +一个历史上*更加*激进的美联储,最终是否会*更不愿意*对新的通货膨胀冲击作出反应? + +```{exercise-end} +``` + +```{solution-start} lc_ex2 +:class: dropdown +``` + +```{code-cell} ipython3 +state = np.array([1.0, 4.0, 1.0, 2.0]) # π=4,x=1,i_{-1}=2:一次通货膨胀冲击 + +print(f"{'φ_π(历史)':>14} {'测量的 ρ':>12} {'建议利率 i':>15}") +for φ in [1.2, 1.6, 2.0, 2.6]: + ρ_meas = measured_persistence(φ) + i_rec = phelps_rate(np.array([0.3, ρ_meas, 0.05]), state) + print(f"{φ:>14} {ρ_meas:>12.2f} {i_rec:>15.2f}") +``` + +历史上更加激进的政策(更高的 $\phi_\pi$)会使美联储相信通货膨胀持续性更低(测量的 $\rho$ 更低),而根据 {prf:ref}`lc_prop1` 的逻辑,再结合菲尔普斯问题的比较静态分析,一个认为通货膨胀会自行消退的美联储,对新的冲击的反应会*更弱*。 + +成功滋生自满:正是那种征服了通货膨胀的激进态度,教会了美联储一个教训,而如果将这一教训视为结构性的,反而会使其在应对下一次飙升时缺乏防备。 + +```{solution-end} +``` From d7bb7bbb7e59e82b40ec2f6d89401b5426255bda Mon Sep 17 00:00:00 2001 From: Matt McKay Date: Fri, 24 Jul 2026 10:37:43 +1000 Subject: [PATCH 21/21] Fix the font path init hard-coded into phillips_lost_conquest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `translate init -f` injected `FONTPATH = "_fonts/SourceHanSerifSC-SemiBold.otf"`, but this edition keeps the font at `lectures/fonts/` — the other 103 lectures carrying font config all use `fonts/`. `addfont()` raises FileNotFoundError on a missing path, so this would have failed the build on the one lecture that needs the font most: it carries 14 translated plot labels. This is QuantEcon/action-translation#141's hard-coded font path, still live at v0.23.0. Also aligns `mpl.rcParams` to the `plt.rcParams` the rest of the edition uses; both mutate the same object, so that half is cosmetic. Worth recording for whoever reviews this PR: the font block is correct here and should not be removed. The AI review flagged it as a blocker ("unauthorized insertion ... out of scope for a translation task"), but the lecture's figures are labelled in Chinese and would render as tofu without it. The nine sibling lectures have no font block because the *sync* path applies no localisation at all — it also leaves their plot labels in English — which is a divergence between the sync and init paths rather than a defect in this file. --- lectures/phillips_lost_conquest.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lectures/phillips_lost_conquest.md b/lectures/phillips_lost_conquest.md index 7ada20d..274276b 100644 --- a/lectures/phillips_lost_conquest.md +++ b/lectures/phillips_lost_conquest.md @@ -79,9 +79,9 @@ translation: ```{code-cell} ipython3 import matplotlib.pyplot as plt import matplotlib as mpl # i18n -FONTPATH = "_fonts/SourceHanSerifSC-SemiBold.otf" # i18n +FONTPATH = "fonts/SourceHanSerifSC-SemiBold.otf" # i18n mpl.font_manager.fontManager.addfont(FONTPATH) # i18n -mpl.rcParams['font.family'] = ['Source Han Serif SC'] # i18n +plt.rcParams['font.family'] = ['Source Han Serif SC'] # i18n import numpy as np import pandas as pd import datetime