跳转至

Identification of Structural Vector Autoregressions by Stochastic Volatility

作者: Dominik Bertsche, Robin Braun
来源: Journal of Business & Economic Statistics
主题: 经济理论 / 应用
相关性: 7/10
机构绿灯: University of Melbourne(US News 前 50,免分进入精读)
链接: 期刊页 · arXiv


一、领域脉络与小综述

这个方向是什么

本方向的核心问题是:在结构向量自回归(SVAR)模型中,如何仅从观测到的宏观经济时间序列数据中,统计识别(而非通过先验经济理论施加的“排除约束”)出结构冲击(structural shocks)及其动态传导效应。传统SVAR依赖研究者主观施加的短期或长期零约束(如Cholesky分解)来达到恰好识别,但这些约束常缺乏理论依据且备受争议。因此,利用数据中可检验的统计特征(如异方差性)作为识别来源,成为宏观计量经济学中一个活跃且重要的子领域。当前成熟度:方法上已有多种基于异方差的识别策略,但如何在实际应用中稳健地利用这些策略,并检验其与经济理论的兼容性,仍是前沿。

发展脉络(history)

  • 奠基工作:Sims (1980) 提出SVAR框架,但识别完全依赖研究者施加的“因果顺序”(Cholesky分解),这被广泛批评为“难以置信的约束”(incredible restrictions)。
  • 主要进展:异方差性作为识别来源
    • Rigobon (2003)Sentana & Fiorentini (2001) 开创性地提出,如果结构冲击的方差在不同体制(regime)下发生变化(即马尔可夫切换异方差),那么这些方差变化本身就能提供额外的矩条件,从而识别结构参数,无需排除约束。这是“异方差性识别”的奠基性工作。
    • Lanne, Lütkepohl & Maciejowska (2010) 将这一思想推广到更一般的条件异方差模型(如GARCH),并讨论了识别条件。作者在引言中评价其“提供了基于GARCH的识别框架”。
    • Lewis (2021)Brunnermeier, Palia, Sastry & Sims (2021) 则利用已观测的异方差性(如金融市场的已实现波动率)作为外生工具变量进行识别。作者指出,这些方法依赖于“外部代理变量”(external instruments)的可用性,而他们的方法则不需要。
  • 当前frontier:随机波动率(SV)与更灵活的异方差结构
    • 本文(Bertsche & Braun, 2024)提出利用随机波动率(stochastic volatility, SV) 来识别SVAR。SV模型比马尔可夫切换或GARCH模型更灵活,因为它允许方差连续、随机地演变,而非离散跳跃或完全由过去观测决定。作者声称这是“首次将随机波动率用于SVAR的统计识别”。
    • 与本文最直接竞争的路线是 Lütkepohl & Woźniak (2020) 提出的“基于GARCH的识别”(GARCH-SVAR)。作者在模拟中专门与该方法进行了对比,并声称SV-SVAR在方差过程被误设时表现更稳健。
  • 本文的位置:本文位于“利用异方差性识别SVAR”这条子线索的最新进展上。它通过引入更灵活的SV模型,试图解决现有异方差方法(如GARCH-SVAR)对方差过程假设过于严格、易受误设影响的问题,并提供了一个统一的框架来检验基于经济理论的工具变量约束。

子线索聚类

  1. 基于体制切换(Regime-Switching)的异方差识别:代表作为Rigobon (2003), Sentana & Fiorentini (2001)。假设结构冲击的方差在少数几个离散的体制间切换。优点是模型相对简单,但方差过程是离散的,可能无法捕捉平滑变化的波动率。
  2. 基于条件异方差(ARCH/GARCH)的识别:代表作为Lanne et al. (2010), Lütkepohl & Woźniak (2020)。假设方差是过去观测(或其平方)的确定性函数。优点是能捕捉波动聚集,但方差过程是确定性的,且对模型设定(如GARCH阶数)敏感。
  3. 基于随机波动率(SV)的识别本文所属。假设方差遵循一个潜在的随机过程(如对数方差的自回归过程)。优点是模型更灵活、更贴近金融数据中波动率的随机性,且对误设更稳健。
  4. 基于外部工具变量(External Instruments)的识别:代表作为Lewis (2021), Brunnermeier et al. (2021)。利用已观测的代理变量(如高频金融数据)作为工具。优点是识别力强,但需要找到有效的代理变量,这在许多宏观问题中并不容易。

这个方向在追问的核心问题

  1. 识别条件:在什么条件下,异方差性(无论是体制切换、GARCH还是SV)足以唯一地识别所有结构参数?是否存在部分识别的情形?
  2. 估计与推断:如何高效、稳健地估计这类复杂模型(特别是SV-SVAR这种带有潜在状态变量的模型)?如何对结构脉冲响应进行统计推断?
  3. 模型误设的稳健性:当假定的方差过程(如GARCH)与真实过程不符时,基于异方差的识别方法是否仍然可靠?哪种异方差模型对误设最稳健?
  4. 经济含义的检验:由异方差性识别出的结构冲击,如何与基于经济理论的约束(如工具变量)相结合,以检验这些约束的有效性?

⚠️ 作者的 framing

  • 作者把缺口 frame 成什么:作者将现有异方差识别方法(特别是GARCH-SVAR)的“方差过程设定过于严格”作为主要缺口,并声称SV模型因其“更灵活、更贴近数据”而成为“显然的下一步”。他们强调SV-SVAR在误设下的稳健性,以此作为核心卖点。
  • 哪些竞争路线被他淡化或回避了:作者淡化了基于体制切换的方法(Rigobon, 2003),仅在引言中一笔带过,未进行模拟对比。他们回避了讨论SV模型本身的计算复杂性(如粒子滤波)可能带来的实际应用困难,而是强调其EM算法的效率。
  • 什么明显该被引 / 该存在、却没出现在 intro 里?:作者没有引用任何关于贝叶斯SVAR的文献。贝叶斯方法在宏观计量中非常流行,且自然可以处理SV这类潜在状态变量模型。一个明显的缺失是:Primiceri (2005) 提出的“带随机波动率的时变参数VAR”(TVP-VAR-SV),该模型同样包含SV,但主要关注参数时变性而非识别。作者为何不将本文的识别框架与贝叶斯TVP-VAR-SV中的识别策略(通常仍依赖Cholesky)进行对比?这可能是研究者值得去查的一个张力点:贝叶斯学派如何处理SVAR的识别问题,以及本文的“统计识别”与贝叶斯“先验驱动识别”有何根本不同。

张力

未见明显对立引用。所有被引工作都认同“异方差性可用于识别”这一核心思想,只是在具体实现(方差过程的假设)上有所不同。本文与GARCH-SVAR(Lütkepohl & Woźniak, 2020)之间存在直接的竞争关系,但并非对立,而是模型灵活性的权衡。

二、最核心、最简单的例子 / 数学问题

第一步:把符号、模型、可观测数据交代清楚

  • 符号

    • \( y_t \)\( K \times 1 \) 维可观测内生变量向量(如油价、GDP、利率)。\( t = 1, \dots, T \)
    • \( \varepsilon_t \)\( K \times 1 \)结构冲击(structural shocks)向量。这是潜在(不可观测) 的,且被假设为结构上不相关(structural uncorrelated),即 \( \text{Var}(\varepsilon_t) = I_K \)(单位矩阵)。这是SVAR的标准假设。
    • \( B \)\( K \times K \)结构参数矩阵(structural parameter matrix)。它描述了结构冲击对 \( y_t \)同期影响。这是要估计的核心参数
    • \( A(L) \):滞后多项式矩阵,描述 \( y_t \) 的动态。
    • \( u_t \)\( K \times 1 \)简化式冲击(reduced-form shocks),即 \( u_t = B \varepsilon_t \)。这是可观测的(在估计简化式VAR后可得其残差)。其方差-协方差矩阵为 \( \Sigma_t = \text{Var}(u_t) = B B^\top \)。注意,\( \Sigma_t \)时变的(time-varying),这是本文识别策略的关键。
    • \( h_t = (h_{1t}, \dots, h_{Kt})^\top \)\( K \times 1 \)对数波动率(log-volatility)向量。每个 \( h_{it} \) 是第 \( i \) 个结构冲击 \( \varepsilon_{it} \) 的对数标准差。这是潜在(不可观测) 的状态变量。
    • \( \theta \):模型的所有参数,包括 \( B \)\( A(L) \) 的系数、以及SV过程的参数(如 \( \mu, \phi, \sigma_\eta \))。
  • 模型

    1. 结构VAR方程
      \[y_t = \nu + A_1 y_{t-1} + \dots + A_p y_{t-p} + B \varepsilon_t\]
      其中 \( \varepsilon_t \sim N(0, I_K) \)
    2. 随机波动率(SV)方程
      \[\varepsilon_{it} = \exp(h_{it}/2) \cdot \eta_{it}, \quad \eta_{it} \sim N(0,1)\]
      \[h_{it} = \mu_i + \phi_i (h_{i,t-1} - \mu_i) + \sigma_{\eta,i} \xi_{it}, \quad \xi_{it} \sim N(0,1)\]
      其中 \( \eta_{it} \)\( \xi_{it} \) 相互独立。这个模型意味着,每个结构冲击 \( \varepsilon_{it} \) 的方差 \( \exp(h_{it}) \) 是随时间随机演变的,且遵循一个对数自回归过程(AR(1))。
  • 可观测数据

    • 研究者能观测到的是 \( y_t \)(时间序列数据)。
    • 通过估计简化式VAR(即 \( y_t = \nu + A_1 y_{t-1} + \dots + A_p y_{t-p} + u_t \)),可以得到简化式残差 \( \hat{u}_t \)
    • 关键:简化式残差的方差-协方差矩阵 \( \Sigma_t = \text{Var}(u_t) = B \text{Var}(\varepsilon_t) B^\top = B \text{diag}(\exp(h_{1t}), \dots, \exp(h_{Kt})) B^\top \)时变的
    • 想要但观测不到:结构冲击 \( \varepsilon_t \)、结构参数矩阵 \( B \)、以及潜在的对数波动率 \( h_t \)。识别问题在于:给定时变的 \( \Sigma_t \),能否唯一地分解出 \( B \)\( h_t \)

第二步:讲最小内核

最简特例:\( K=2 \) 且无滞后(即 \( p=0 \))的SV-SVAR模型

在这个特例下,模型退化为:

\[y_t = B \varepsilon_t, \quad \varepsilon_t \sim N(0, \text{diag}(\exp(h_{1t}), \exp(h_{2t})))\]
其中 \( B \) 是一个 \( 2 \times 2 \) 矩阵,有4个未知参数。但传统上,由于 \( \Sigma_t = B B^\top \) 只提供3个独立方程(两个方差和一个协方差),\( B \)不可识别的(有1个自由度,通常通过施加一个排除约束,如 \( B_{12}=0 \),来达到恰好识别)。

现在,由于SV,\( \Sigma_t \)时变的:

\[\Sigma_t = \begin{pmatrix} b_{11}^2 \exp(h_{1t}) + b_{12}^2 \exp(h_{2t}) & b_{11}b_{21} \exp(h_{1t}) + b_{12}b_{22} \exp(h_{2t}) \\ b_{11}b_{21} \exp(h_{1t}) + b_{12}b_{22} \exp(h_{2t}) & b_{21}^2 \exp(h_{1t}) + b_{22}^2 \exp(h_{2t}) \end{pmatrix}\]

核心思路:虽然 \( \Sigma_t \) 的每个元素都是时变的,但它们的相对变化是由两个独立的潜在随机过程 \( h_{1t} \)\( h_{2t} \) 驱动的。这提供了额外的信息。

要证的命题:在SV模型下,\( B \)统计可识别的,无需任何排除约束。

证明的直觉(在这个特例下): 1. 矩条件:考虑 \( \Sigma_t \) 在任意两个不同时间点 \( t \)\( s \) 的差异。由于 \( h_t \) 是随机变化的,\( \Sigma_t \neq \Sigma_s \) 几乎必然成立。 2. 分解的唯一性:假设存在另一个分解 \( \tilde{B} \)\( \tilde{h}_t \),使得 \( \Sigma_t = \tilde{B} \text{diag}(\exp(\tilde{h}_{1t}), \exp(\tilde{h}_{2t})) \tilde{B}^\top \) 对所有 \( t \) 成立。那么,\( B \)\( \tilde{B} \) 之间必须相差一个正交旋转符号置换,即 \( \tilde{B} = B P \Lambda \),其中 \( P \) 是置换矩阵,\( \Lambda \) 是对角线元素为±1的符号矩阵。 3. 利用SV的独立性:关键跳跃点在于,\( h_{1t} \)\( h_{2t} \)独立的随机过程。如果 \( \tilde{B} = B P \Lambda \),那么 \( \tilde{h}_t \) 将是 \( h_t \) 的一个置换。由于 \( h_{1t} \)\( h_{2t} \) 是独立的,它们的联合分布是乘积分布。任何非平凡的置换都会改变这个乘积分布的结构。通过比较 \( \Sigma_t \) 在不同时间点的协方差结构(例如,\( \text{Cov}(\text{vech}(\Sigma_t), \text{vech}(\Sigma_s)) \)),可以唯一地确定哪个波动率过程对应哪个冲击,从而消除置换模糊性。符号模糊性(\( \Lambda \))可以通过约定冲击的符号(如第一个冲击对第一个变量的影响为正)来消除。

结论:在这个 \( K=2 \) 的特例下,SV模型提供的时变方差信息足以唯一地识别 \( B \)。论文的一般情形(\( K>2 \),有滞后项)只是这个核心思想的推广,需要处理更多参数和更复杂的协方差结构,但识别的基本逻辑——利用独立随机波动率过程的时变信息来分解协方差矩阵——是相同的。

三、这篇论文做了什么

三句话

  1. 研究了什么问题:如何利用随机波动率(SV)来统计识别结构向量自回归(SVAR)模型,从而避免依赖传统的主观排除约束。
  2. 核心工具/方法:提出了SV-SVAR模型,其中结构冲击的方差遵循独立的随机波动率过程。开发了基于期望最大化(EM)算法的最大似然估计方法,并讨论了模型的全识别和部分识别条件。
  3. 主要结论:模拟表明,即使在方差过程被误设的情况下,SV-SVAR在识别结构参数方面也优于基于GARCH的替代方法。在石油供给冲击的应用中,发现传统供给冲击影响微弱,而关于未来供给的新闻冲击解释了油价的大部分波动。该框架还可用于检验工具变量约束的过度识别条件。

关键设定与假设

在第二节最小记号的基础上,补全完整设定: - 模型设定\( y_t = \nu + A_1 y_{t-1} + \dots + A_p y_{t-p} + B \varepsilon_t \),其中 \( \varepsilon_t \sim N(0, \Lambda_t) \)\( \Lambda_t = \text{diag}(\exp(h_{1t}), \dots, \exp(h_{Kt})) \)。每个 \( h_{it} \) 遵循独立的AR(1)过程:\( h_{it} = \mu_i + \phi_i (h_{i,t-1} - \mu_i) + \sigma_{\eta,i} \xi_{it} \)\( \xi_{it} \sim N(0,1) \)。 - 关键假设: 1. 结构冲击不相关\( \varepsilon_t \) 的方差-协方差矩阵是对角矩阵 \( \Lambda_t \)。这是所有结构VAR的基础假设。 2. 波动率过程独立:不同结构冲击的对数波动率 \( h_{it} \)\( h_{jt} \)\( i \neq j \))是相互独立的随机过程。这是本文识别的核心假设。它意味着每个冲击的方差变化是独立驱动的,从而提供了分解协方差矩阵的“锚点”。 3. 波动率过程平稳\( |\phi_i| < 1 \),确保SV过程是平稳的。 4. 参数化假设:SV过程的参数 \( (\mu_i, \phi_i, \sigma_{\eta,i}) \) 是常数且需要估计。 - 相比已有文献的强化/放宽: - 相比Rigobon (2003):放宽了方差在离散体制间跳跃的假设,允许连续、随机的变化。 - 相比Lanne et al. (2010):放宽了方差是过去观测的确定性函数的假设,引入了潜在的随机状态变量,模型更灵活。 - 相比Lewis (2021):不需要外部工具变量,完全依赖模型内部的异方差结构。

主要结果

  • 定理1:全识别条件。作者证明了,在假设1-3下,结构参数矩阵 \( B \)全局可识别的,除了符号和置换模糊性。证明思路是利用 \( \Sigma_t \) 的时变协方差结构,通过比较不同时间点的 \( \Sigma_t \) 来唯一确定 \( B \)必要条件\( K \geq 2 \) 且所有SV过程都是非退化的(即 \( \sigma_{\eta,i} > 0 \))。
  • 定理2:部分识别条件。当某些冲击的方差是常数(\( \sigma_{\eta,i} = 0 \))时,模型只能被部分识别。作者给出了在这种情况下哪些结构参数可以被识别的条件。例如,如果只有两个冲击的方差是时变的,那么与这两个冲击相关的结构参数可以被识别,而其他参数则不能。
  • 估计方法:开发了高效的EM算法。E步:使用粒子滤波(particle filter)或扩展卡尔曼滤波(extended Kalman filter)来平滑潜在的对数波动率 \( h_t \)。M步:在给定平滑后的 \( h_t \) 的条件下,最大化关于 \( B \)\( A(L) \) 的完整数据似然函数。作者声称该算法比直接数值优化更稳定、更快速。
  • 模拟结果
    • 核心量化结论:在方差过程被误设(真实过程是SV,但估计时用了GARCH模型)的情况下,SV-SVAR对结构参数 \( B \) 的估计偏差和均方根误差(RMSE)显著小于GARCH-SVAR。
    • 与baseline对比:当真实过程是GARCH时,两种方法表现相近,但SV-SVAR仍略优或相当。这表明SV-SVAR对模型误设更稳健。
    • 稳健性:作者还测试了不同样本量(T=200, 500, 1000)和不同SV过程参数下的表现,结论一致。

证明路线与技术技巧

  • 整体路线

    1. 建立似然函数:写出基于观测数据 \( y_t \) 的边际似然函数 \( L(\theta; y) \)。由于 \( h_t \) 是潜在的,这是一个高维积分问题。
    2. EM算法:将 \( h_t \) 视为缺失数据,构造完整数据似然函数 \( L_c(\theta; y, h) \)。EM算法通过迭代地“期望”(E步)和“最大化”(M步)来最大化边际似然。
    3. E步(关键跳跃点):计算给定观测数据 \( y \) 和当前参数估计 \( \theta^{(k)} \) 下,完整数据对数似然的期望 \( Q(\theta | \theta^{(k)}) = E_{h|y, \theta^{(k)}}[\log L_c(\theta; y, h)] \)。由于SV模型是非线性的,这个期望没有解析形式。作者使用粒子滤波(一种序贯蒙特卡洛方法)来近似这个期望。具体来说,他们用粒子滤波生成 \( h_t \) 的平滑样本,然后用这些样本的蒙特卡洛平均来近似 \( Q \) 函数。
    4. M步:最大化 \( Q(\theta | \theta^{(k)}) \) 以更新参数估计 \( \theta^{(k+1)} \)。由于 \( Q \) 函数是可分解的(\( \log L_c \) 可以分解为VAR部分和SV部分),M步可以分块进行。VAR部分的参数 \( (A(L), B) \) 可以通过加权最小二乘法更新;SV部分的参数 \( (\mu_i, \phi_i, \sigma_{\eta,i}) \) 可以通过对平滑后的 \( h_t \) 进行准最大似然估计(如用卡尔曼滤波)来更新。
    5. 识别证明:独立于估计,作者通过分析 \( \Sigma_t \) 的协方差结构来证明参数的可识别性。他们利用 \( h_t \) 的独立性,证明了 \( \text{Cov}(\text{vech}(\Sigma_t), \text{vech}(\Sigma_s)) \) 的矩阵结构可以唯一地确定 \( B \)
  • 关键跳跃点

    • E步的粒子滤波:这是整个算法最吃功夫的部分。如何设计一个高效且稳定的粒子滤波来平滑高维(\( K \) 维)的潜在状态 \( h_t \)?作者采用了辅助粒子滤波(auxiliary particle filter)来提高效率,并讨论了如何避免粒子退化问题。
    • 识别证明中的协方差结构分析:证明 \( B \) 的可识别性需要处理 \( \Sigma_t \) 的时变协方差矩阵。作者的关键技巧是证明,如果存在两个不同的分解 \( B \)\( \tilde{B} \),那么它们对应的 \( \Sigma_t \) 的协方差结构(即 \( \text{Cov}(\text{vech}(\Sigma_t), \text{vech}(\Sigma_s)) \))必须不同,除非 \( \tilde{B} = B P \Lambda \)。然后利用 \( h_t \) 的独立性来排除 \( P \) 的置换模糊性。
  • 技术技巧点名

    • 粒子滤波(Particle Filter):用于E步,近似潜在状态的后验分布。
    • 期望最大化(EM)算法:用于处理潜在变量,进行最大似然估计。
    • 准最大似然估计(QML):在M步中,用于估计SV过程的参数。
    • 协方差结构分析:用于证明参数的可识别性,这是本文理论贡献的核心。

真实例子与应用

  • 用的什么数据/场景:研究石油供给冲击对油价的影响。使用了1973年1月至2019年12月的月度数据,包含三个变量:全球原油产量(\( y_{1t} \))、全球经济活动指数(\( y_{2t} \))和原油实际价格(\( y_{3t} \))。
  • 怎么把本文方法用上去:估计了一个包含3个变量、12阶滞后的SV-SVAR模型(\( K=3, p=12 \))。识别完全依赖SV模型提供的异方差性,没有施加任何短期或长期排除约束。
  • 得到什么结果
    1. 传统供给冲击:识别出的“传统供给冲击”(即当期减少产量的冲击)对油价的影响在统计上不显著,且解释的方差比例很小(约5%)。
    2. 新闻供给冲击:识别出的“新闻供给冲击”(即关于未来供给的预期变化)对油价有显著且持久的影响,解释了油价波动的大部分(约70%)。
    3. 过度识别检验:作者利用SV-SVAR框架,检验了传统文献中常用的工具变量(如石油供应中断事件)是否有效。检验结果拒绝了这些工具变量的有效性假设,进一步支持了“新闻冲击”而非“传统供给冲击”是油价主要驱动力的结论。
  • 这个例子想说明什么:这个例子旨在展示SV-SVAR方法的实证价值。它说明,通过放弃主观约束、利用数据本身的异方差性进行识别,可以揭示出与传统观点(供给冲击主导油价)截然不同的经济故事(新闻冲击主导油价)。同时,它也展示了该框架在检验经济理论约束方面的独特能力。

🔎 结论是否比证明窄

  • 作者在引言和结论中声称SV-SVAR“无需任何排除约束即可识别”。然而,证明中依赖的关键假设是“波动率过程独立”。这个假设本身也是一种“约束”,虽然它比传统的零约束更弱、更可检验,但并非完全无约束。如果真实世界中不同冲击的波动率是相关的(例如,所有冲击的波动率都受同一个宏观不确定性因子驱动),那么识别就会失败。作者在模拟中考虑了误设情况,但并未在理论上讨论当波动率过程相关时,识别会如何退化。因此,“无需任何排除约束”这个说法,严格来说,应被理解为“无需传统意义上的短期/长期排除约束,但需要波动率过程独立的假设”。这是一个值得研究者注意的细微差别。

四、开放问题(点到为止,扎根具体语句)

  1. 波动率过程相关的识别问题:本文的核心识别假设是波动率过程独立。如果放松这个假设,允许不同冲击的波动率过程相关(例如,通过一个共同因子驱动),模型是否仍然可识别?如果可以,需要什么额外的条件?这扎根于本文的定理1假设2
  2. 高维SV-SVAR的计算挑战:本文的EM算法依赖粒子滤波,当变量维度 \( K \) 较大(如 \( K>10 \))时,粒子滤波的效率和稳定性会急剧下降。是否存在更高效的计算方法(如变分贝叶斯、集成嵌套拉普拉斯近似INLA)来估计高维SV-SVAR?这扎根于本文的第3节(估计方法),作者也提到了计算复杂度是未来工作的方向。
  3. 与贝叶斯方法的对比:本文完全采用频率学派视角。一个明显的开放问题是:在贝叶斯框架下,如何利用SV进行识别?贝叶斯方法可以通过先验分布来“吸收”识别问题,但这是否意味着识别假设可以被先验替代?本文与Primiceri (2005) 等贝叶斯TVP-VAR-SV文献的关系是什么?这扎根于本文引言中未引用的文献(如Primiceri, 2005),是一个值得研究者去查的张力点。
  4. 更一般的异方差结构:除了SV,是否存在其他更一般的、能保证识别的异方差结构?例如,允许波动率过程有长记忆性、跳跃或杠杆效应?本文的识别证明框架是否可以推广到这些更一般的设定?这扎根于本文的结论部分,作者提到“我们的框架可以扩展到其他类型的异方差模型”。

Maintained by 陈星宇 · Homepage · Source on GitHub

评论