A comprehensive econometrics skills set for empirical study, covering the complete workflow of empirical study.
Phase 8 Robustness, Heterogeneity & Mechanism Tests. Reads model-spec.md, diagnostic_report.md, and results-memo.md to build a personalised checklist, then runs method-specific robustness checks, heterogeneity analysis, and mechanism tests; generates code; and produces robustness-report.md.
# /robustness — 稳健性、异质性与机制检验
## 定位
`/robustness` 是实证研究工作流的**第八阶段**,承接 Phase 6(`/code`)的 `diagnostic_report.md` 和 Phase 7(`results-analysis` skill)的 `results-memo.md`,完成三类核心检验:
1. **稳健性检验(Robustness Checks)**:验证主要结论在不同规格、样本和推断方法下的稳定性
2. **异质性分析(Heterogeneity Analysis)**:识别处理效应在不同子群体中的差异
3. **机制检验(Mechanism Tests)**:提供因果机制的间接证据,区分竞争性解释
本阶段产出 `robustness-report.md`,直接供 Phase 9(`/write`)的实证结果和稳健性讨论节使用。
---
## Step 0:读取上游输出,构建个性化检验清单
> 📎 **参见 [`shared/context-reader.md`](../shared/context-reader.md)**
> 本阶段所需文件:`model-spec.md`(必需)、`diagnostic_report.md`(可选)、`results-memo.md`(可选)。
### 0.2 提取关键信息
从各文件中提取以下信息,构建**个性化稳健性检验清单**:
| 来源 | 提取内容 | 用途 |
|------|---------|------|
| `model-spec.md §1` | 识别策略类型 | 选择方法特异性检验菜单 |
| `model-spec.md §3` | 识别假设及诊断状态(✅/⚠️/❌) | ⚠️ 项自动转为稳健性检验 |
| `model-spec.md §8` | 预列的稳健性检验清单 | 直接纳入执行清单 |
| `diagnostic_report.md` | 第二层统计诊断 ⚠️ 项 | 对应的稳健性处理方式 |
| `results-memo.md §6` | Phase 7 建议的优先检验 | 调整执行优先级 |
### 0.3 输出启动确认
向用户输出Phase 8 启动摘要:
```
═══════════════════════════════════════════════════════
Phase 8 启动确认
═══════════════════════════════════════════════════════
识别策略:[策略类型]
主系数:β̂ = [值](p = [值])
识别可信度(Phase 7):[高/中/低]
【已继承的待检验项】(来自上游阶段)
model-spec.md §8:[N1] 项预列稳健性检验
diagnostic_report.md ⚠️ 项:[N2] 项统计诊断警告
results-memo.md §6 优先建议:[N3] 项
【本阶段将执行】
① 方法特异性稳健性检验(见 Step 2)
② 异质性分析(见 Step 3)
③ 机制检验(见 Step 4)
═══════════════════════════════════════════════════════
```
待用户确认后继续,或询问是否有额外的稳健性检验需求。
---
## Step 1:构建稳健性检验主清单
综合三个来源,生成本次执行的**完整稳健性检验清单**,按优先级排序:
```
稳健性检验主清单
─────────────────────────────────────────────────────
编号 | 来源 | 检验类型 | 执行优先级
─────────────────────────────────────────────────────
R1 | 方法通用 | [具体检验名称] | 高(必须执行)
R2 | model-spec §8 | [具体检验名称] | 高(预列)
R3 | diagnostic ⚠️ | Cook's D 高影响观测值 | 高(已标记)
R4 | results §6 | [建议检验名称] | 中(建议执行)
R5 | 主动设计 | [检验名称] | 中(主动发现)
...
─────────────────────────────────────────────────────
```
**主动性原则(Activeness)**:在继承上游清单基础上,主动识别用户未明确提出但**审稿人很可能质疑**的检验点,自动补充到清单并标注"主动设计"。
---
## Step 1.5:写入上下文 → 自动调用 Checker Agent(并行执行)
> **此步骤是 Steps 2–4 的替代入口**。完成检验清单后,将上下文序列化并委托 `checker` agent 并行执行三轨检验,而非在主线程中串行运行 Steps 2/3/4。
### 1.5.1 序列化检验上下文
将 Step 0–1 提取的信息写入 `phase8/context.json`:
```json
{
"data_path": "<来自 model-spec.md 的数据路径>",
"depvar": "<因变量>",
"treatment": "<处理变量>",
"controls": ["<控制变量列表>"],
"fe": ["<固定效应>"],
"cluster": "<聚类层级>",
"method": "<识别策略:OLS/IV/DID/RDD/Panel FE>",
"baseline_coef": <来自 results-memo.md 的基准系数>,
"baseline_se": <基准标准误>,
"N": <样本量>,
"checklist": {
"robustness": ["R1: ...", "R2: ...", "R3: ..."],
"heterogeneity": ["H1: ...", "H2: ..."],
"mechanism": ["M1: ...", "M2: ..."]
}
}
```
`checklist` 字段直接来自 Step 1 构建的个性化清单,供各 subagent 优先执行用户研究特定的检验。
### 1.5.2 读取 Checker Agent 规格
```
Read: agents/checker.md
```
### 1.5.3 按 Checker agent spec 执行并行派发
严格按照 `agents/checker.md` 的 **Step 3** 规定,在**单条消息**中同时发出三个 Agent tool call:
- **Agent A**:稳健性检验 → 写入 `phase8/robustness/`
- **Agent B**:异质性分析 → 写入 `phase8/heterogeneity/`
- **Agent C**:机制检验 → 写入 `phase8/mechanism/`
每个 subagent 的 prompt 应包含:
1. 指向 `phase8/context.json` 的读取指令
2. 来自 `checklist` 字段的个性化检验项(优先于 `agents/checker.md` 中的通用菜单)
3. 来自 Steps 2–4 技术规范的对应方法代码(按 `method` 字段选择对应小节)
### 1.5.4 等待汇总
三路 subagent 完成后,由 checker 执行其 Step 4(汇总 `phase8_report.md`)和 Step 5(呈现给用户确认)。
> **Steps 2–4 以下内容为各 subagent 可调用的技术规范库**,不在主线程中串行执行。
---
## Step 2:方法特异性稳健性检验
根据 `model-spec.md §1` 中的识别策略,执行对应检验菜单。**同一研究中可能同时适用多个策略的检验**(如 DiD + IV 组合设计)。
---
### 2.A OLS / 截面回归稳健性
适用于主方程为 OLS 的情形。
**1. 控制变量敏感性(Oster 2019 系数稳定性)**
逐步添加控制变量,并计算 Oster δ 统计量:
```python
# δ = (β_受控 - β_基准) / (β_受控 - 假设的 OVB 估计量)
# |δ| > 1 表示 OVB 解释全部效应所需的选择性相对可观测性失调程度 > 1,不合理
# 论文惯例:报告 β_受控 在 R² → R²_max = 1.3 × R²_全控 时对应的 δ
delta_oster = (beta_controlled - beta_baseline) / (beta_controlled - 0)
print(f"Oster δ = {delta_oster:.3f}(|δ| > 1 说明 OVB 不足以推翻结论)")
```
**2. 替代标准误**
并排报告 HC1、HC3 和聚类 SE:
```python
# Python — statsmodels
import statsmodels.formula.api as smf
m_ols = smf.ols(formula, data).fit()
m_hc1 = smf.ols(formula, data).fit(cov_type='HC1')
m_hc3 = smf.ols(formula, data).fit(cov_type='HC3')
m_clus = smf.ols(formula, data).fit(cov_type='cluster',
cov_kwds={'groups': data[cluster_var]})
```
**3. 异常值剔除**
- 剔除结果变量 Y 前后 1% 极端值
- 剔除 `diagnostic_report.md` 中 Cook's D 超阈值的高影响观测值
**4. 函数形式检验**
- RESET 检验(来自 Phase 6 诊断;若 ⚠️ 则此处测试对数变换规格)
- 对数变换:`log(Y)` 和 `log(D)`(若 Y/D 右偏分布)
- 二次项:在主方程中加入 $D^2$,检验非线性效应
**5. 子样本稳健性**
按关键维度分组估计,检验主效应是否由特定子样本驱动:
- 地理维度(如东/西部;高/低收入地区)
- 时间维度(前半段 vs. 后半段样本期)
- 规模维度(大/小企业;高/低收入群体)
---
### 2.B 双重差分(DiD / TWFE)稳健性
适用于主方程为 DiD 或交错 DiD 设计。
**1. 预趋势检验(最高优先级)**
事件研究图 + 预处理期系数联合 F 检验(此项若在 Phase 6 已通过仍须在报告中呈现):
```stata
* Stata — reghdfe + coefplot
reghdfe Y i.event_time##i.treated controls, ///
absorb(id year) cluster(id)
* 联合检验预处理期系数 = 0
test [event_time = -4].treated [event_time = -3].treated [event_time = -2].treated
```
**2. 安慰剂处理时点(Placebo in Time)**
将处理时点提前 1–2 年重新估计;安慰剂效应应不显著:
```python
# 将 post 变量提前 1 年(安慰剂)
df['post_placebo'] = (df[time_var] >= treatment_year - 1).astype(int)
df['treat_post_placebo'] = df['treated'] * df['post_placebo']
# 在原始处理时点前的样本中估计,效应应趋于零
```
**3. 替代控制组**
- 限制为处理时点前特征更相似的对照单元(倾向得分匹配后构建控制组)
- 剔除政策可能有溢出效应的相邻单元
**4. 交错 DiD 估计量比较(Staggered Adoption)**
若存在交错处理,对比 TWFE 与异质性稳健估计量:
```r
# R — 对比四种估计量
library(did); library(fixest); library(sunab)
# (1) TWFE(可能有负权重偏误)
m_twfe <- feols(Y ~ treat_post | id + year,
cluster = ~id, data = df)
# (2) Callaway-Sant'Anna
m_cs <- att_gt(yname="Y", tname="year", idname="id",
gname="first_treated", data=df)
m_cs_agg <- aggte(m_cs, type="simple")
# (3) Sun-Abraham
m_sa <- feols(Y ~ sunab(first_treated, year) | id + year,
cluster = ~id, data = df)
# (4) Bacon 分解 — 检查负权重比例
library(bacondecomp)
bacon_result <- bacon(Y ~ treat_post, data=df,
id_var="id", time_var="year")
```
结果比较标准:若 TWFE 与 C-S / S-A 主系数差异 > 20%,优先使用异质性稳健估计量,并在论文中解释。
**5. 推断方法稳健性**
- 若聚类数 < 30:报告 Wild Cluster Bootstrap p 值
```r
library(fwildclusterboot)
boot_res <- boottest(m_twfe, clustid = "id",
param = "treat_post", B = 9999)
print(boot_res)
```
---
### 2.C 工具变量(IV / 2SLS)稳健性
适用于主方程为 2SLS 设计。
**1. 工具变量强度诊断**
```stata
* Stata — ivreg2 完整诊断
ivreg2 Y controls (D = Z), robust ffirst
* 报告:第一阶段 F、Kleibergen-Paap rk Wald F、Cragg-Donald F
* Stock-Yogo (2005) 10% 偏误临界值:16.38(单一 IV)
* 弱工具变量稳健置信区间(Anderson-Rubin)
weakiv
```
**2. 2SLS vs. LIML vs. JIVE 对比**
弱工具变量时,LIML 比 2SLS 具有更好的小样本性质:
```stata
ivregress 2sls Y controls (D = Z), robust // 2SLS
ivregress liml Y controls (D = Z), robust // LIML
ivregress gmm Y controls (D = Z), wmatrix(robust) // GMM
```
**3. 排他性限制的间接检验(Reduced Form 对比)**
```stata
* 简约式(Reduced Form)应显著
reg Y Z controls, robust // 简约式
reg D Z controls, robust // 第一阶段
* IV 估计量 = 简约式系数 / 第一阶段系数
* 若简约式不显著但 IV 显著,说明工具变量可能无效
```
**4. 安慰剂工具变量**
使用一个理论上应无第一阶段效应的变量代替 Z,验证排他性:
- 若安慰剂 IV 估计量显著,说明主工具变量可能违反排他性
**5. 控制变量集合敏感性**
在第一阶段和第二阶段中分别增减控制变量,检验 IV 估计量的稳定性。
---
### 2.D 断点回归(RDD)稳健性
适用于 Sharp 或 Fuzzy RDD 设计。
**1. 带宽敏感性(最重要的稳健性检验)**
在 MSE 最优带宽的 50%、75%、100%、125%、150% 下并排报告:
```r
# R — rdrobust
library(rdrobust)
bw_opt <- rdbwselect(Y, X, c=cutoff)$bws["mserd","left"]
for (mult in c(0.5, 0.75, 1.0, 1.25, 1.5)) {
rdd_res <- rdrobust(Y, X, c=cutoff, h=bw_opt*mult)
cat(sprintf("h = %.2f×opt: β = %.4f (SE = %.4f, p = %.3f)\n",
mult, rdd_res$coef[1],
rdd_res$se[3], rdd_res$pv[3]))
}
```
**2. 多项式阶次敏感性**
对比局部线性(p=1)、局部二次(p=2)、局部三次(p=3):
```r
for (p in 1:3) {
rdd_res <- rdrobust(Y, X, c=cutoff, p=p)
cat(sprintf("p=%d: β = %.4f\n", p, rdd_res$coef[1]))
}
```
**3. 核函数敏感性**
三角核(triangular)、矩形核(uniform)、Epanechnikov 核结果对比。
**4. Donut-Hole 检验**
剔除阈值附近最近的 $\delta$ 个单位($\delta = 1, 2, 3$),检验精确操纵:
```r
# 检验是否有精确堆积在 cutoff 处(刚好等于阈值的观测值)
for (donut in c(1, 2, 3)) {
df_donut <- df[abs(df$X - cutoff) > donut, ]
rdd_donut <- rdrobust(df_donut$Y, df_donut$X, c=cutoff)
cat(sprintf("Donut Δ=%d: β = %.4f\n", donut, rdd_donut$coef[1]))
}
```
**5. 安慰剂截断点(Placebo Cutoffs)**
在真实阈值左右各取 25%、50% 分位点作为虚假阈值,效应应为零:
```r
placebo_cutoffs <- quantile(df$X[df$X < cutoff], c(0.25, 0.5, 0.75))
for (c_fake in placebo_cutoffs) {
rdd_p <- rdrobust(df$Y[df$X < cutoff],
df$X[df$X < cutoff], c=c_fake)
cat(sprintf("Placebo c=%.2f: β = %.4f (p = %.3f)\n",
c_fake, rdd_p$coef[1], rdd_p$pv[3]))
}
```
**6. 预定协变量平衡(Covariate Balance at Cutoff)**
对所有预处理协变量做 RDD,估计量应接近零:
- 若协变量不平衡,说明存在操纵或其他处理同时发生
---
### 2.E 面板固定效应稳健性
适用于面板 TWFE 主方程。
**1. 聚类层级比较**
并排报告不同聚类层级的标准误:
- 个体层级聚类 vs. 行业/省级聚类 vs. 双向聚类(个体 + 时间)
**2. 样本时间窗口敏感性**
缩短/延长样本期,检验是否由特定年份驱动:
- 逐年剔除(Jackknife by year)
**3. 逐单位 Jackknife**
逐个剔除个体单元,检验是否存在极端影响的单元:
```python
jackknife_coefs = []
for unit in df[id_var].unique():
df_jack = df[df[id_var] != unit]
model_j = run_model(df_jack) # 调用主方程估计函数
jackknife_coefs.append(model_j.params[D_var])
import numpy as np
print(f"Jackknife 系数范围:[{min(jackknife_coefs):.4f}, {max(jackknife_coefs):.4f}]")
print(f"Jackknife 均值:{np.mean(jackknife_coefs):.4f}(主系数:{beta_main:.4f})")
```
**4. 固定效应规格对比**
| 规格 | FE 层级 | β̂ | SE | N |
|------|---------|---|---|---|
| 仅个体 FE | $\alpha_i$ | ... | ... | ... |
| 双向 FE(主规格)| $\alpha_i + \lambda_t$ | ... | ... | ... |
| 个体 + 行业×年 FE | $\alpha_i + \delta_{j,t}$ | ... | ... | ... |
**5. 动态规格(加入滞后因变量)**
若主规格不含滞后因变量,加入 $Y_{i,t-1}$ 检验估计量稳定性(但注意 Nickell 偏误)。
---
### 2.F 合成控制稳健性
适用于合成控制(SCM)主方案。
**1. 供体池敏感性**
- 逐一剔除供体单元,检验合成控制估计是否对特定供体依赖过强(Leave-one-out)
- 扩大/缩小供体池条件(地理 / 经济相似性标准)
**2. 安慰剂检验(Permutation Test)**
对供体池每个单元重复合成控制,计算"虚假处理效应"分布,报告:
- p 值 = 处理单元 MSPE 比 ≥ 该值的供体比例
- 可视化:安慰剂效应路径图(灰色)+ 处理单元路径(黑色加粗)
```r
library(Synth)
placebos <- generate.placebos(synth_out, synth_data, strategy="multisession")
plot_placebos(placebos)
mspe_test(placebos) # 精确 p 值
```
**3. 预测变量权重矩阵(V 矩阵)敏感性**
分别使用:等权重、主成分确定权重、PCA 降维后的权重,对比合成路径拟合质量(pre-RMSPE)和处理效应。
---
## Step 3:异质性分析(Heterogeneity Analysis)
**异质性分析是 Top-5 期刊近年日益强调的内容**,要求从理论假设出发设计分组,而非事后数据挖掘。
### 3.1 异质性分析设计原则
设计异质性检验前,必须在 `robustness-report.md` 中**先写出理论预测**:
```
异质性分析设计记录
─────────────────────────────────────────────────────
分组变量:[变量名]
理论预测:[为什么该变量应调节处理效应大小或方向?]
预期模式:[预期哪个子组效应更大/更小/方向相反?]
检验方式:[交互项 / 子组分别估计]
─────────────────────────────────────────────────────
```
**无理论支撑的事后分组分析不得纳入论文正文**;若需报告,只能放入附录并标注为"探索性"。
### 3.2 子组分组估计
根据研究背景和理论,选择 2–3 个最重要的分组维度:
```python
# Python — 子组分别估计
heterogeneity_vars = ['group_A', 'group_B', 'group_C'] # 替换为实际分组变量
subgroup_results = {}
for var in heterogeneity_vars:
for val in df[var].unique():
df_sub = df[df[var] == val]
res_sub = run_main_model(df_sub)
subgroup_results[f"{var}={val}"] = {
'coef': res_sub.params[D_var],
'se': res_sub.bse[D_var],
'n': len(df_sub)
}
```
```stata
* Stata — 分组估计 + 系数对比(附交互项显著性检验)
* 高组
reghdfe Y D controls if group == 1, absorb(id year) cluster(id)
estimates store m_high
* 低组
reghdfe Y D controls if group == 0, absorb(id year) cluster(id)
estimates store m_low
* 交互项检验(形式上等价的 Wald 检验)
reghdfe Y c.D##i.group controls, absorb(id year) cluster(id)
test c.D#1.group // 交互项是否显著
```
### 3.3 交互项规格(首选方法)
**推荐做法**:在主方程中加入 $D \times \text{Moderator}$ 交互项,而非单独分组估计,以正式检验异质性的统计显著性。
```latex
% 含调节变量的主方程扩展
\begin{equation}\label{eq:heterogeneity}
Y_{it} = \alpha_i + \lambda_t
+ \beta_1 D_{it}
+ \beta_2 D_{it} \times M_{it}
+ \beta_3 M_{it}
+ \mathbf{X}_{it}'\boldsymbol{\gamma}
+ \varepsilon_{it}
\end{equation}
% M_{it}:调节变量(分组变量)
% \beta_2:异质性处理效应估计量(审稿人重点关注此系数)
% 若 M 为虚拟变量,\beta_1 为 M=0 时的效应;\beta_1+\beta_2 为 M=1 时的效应
```
### 3.4 常见异质性维度(按识别策略推荐)
| 识别策略 | 建议分组维度 |
|---------|-----------|
| DiD(政策评估)| 政策合规强度高/低;处理密度强/弱;首次处理 vs. 后续处理(SUTVA 测试)|
| RDD | 阈值附近更靠近处理区 vs. 控制区(连续度量);人口密度;城乡差异 |
| IV | Compliers 子群体特征(低/高 first-stage 值);工具变量强度的空间分布 |
| Panel FE | 行业周期敏感度;企业规模;地区市场化程度 |
---
## Step 4:机制检验(Mechanism Tests)
机制检验的目标是**提供支持特定因果渠道的间接证据**,而非直接证明机制(通常不可能)。
### 4.1 机制检验设计框架
在执行机制检验前,先写出竞争性机制的逻辑链:
```
机制假设分析
═══════════════════════════════════════════════════════
主要机制假设:
D → [中间变量 M] → Y
理论基础:[经济学/制度学解释]
可观测预测:[若此机制成立,应观察到什么额外规律?]
竞争性机制(需要排除):
D → Y(直接效应,绕过 M)
D → [其他中间变量 M'] → Y
排除方法:[如何区分?]
═══════════════════════════════════════════════════════
```
### 4.2 中介变量分析(Mediation Analysis)
**注意**:社会科学中的"中介分析"通常仅为描述性,因为中介变量本身往往是内生的。应明确声明局限性。
```python
# 三方程中介框架(Baron-Kenny 1986;在论文中标注局限性)
# 方程 1:D → Y(总效应)
total_effect = run_model(Y ~ D + controls)
# 方程 2:D → M(D 对中介变量的影响)
first_stage_M = run_model(M ~ D + controls)
# 方程 3:D + M → Y(条件效应)
direct_effect = run_model(Y ~ D + M + controls)
# 若 β_D 在方程 3 中减小(衰减),说明 M 部分中介 D→Y
# 注意:此处需明确说明中介变量 M 本身的内生性问题
print(f"总效应:{total_effect.params[D_var]:.4f}")
print(f"直接效应(控制M后):{direct_effect.params[D_var]:.4f}")
print(f"间接效应(近似):{total_effect.params[D_var] - direct_effect.params[D_var]:.4f}")
```
### 4.3 排除竞争性解释
对每个竞争性机制,设计一个直接检验加以排除:
| 竞争性解释 | 排除检验 | 预期结果(若此解释不成立)|
|----------|---------|----------------------|
| [解释 A] | [检验方法] | [效应应为零/方向相反] |
| [解释 B] | [检验方法] | [效应应为零] |
### 4.4 机制检验的合规性判断
**关键原则**:若中间变量 M 位于 D→Y 的因果路径上(即 M 是处理的结果),**绝对不能**在主回归中控制 M,否则引入中介偏误(Over-control Bias)。机制检验应以独立的回归方程形式呈现。
```
合规性检查
□ 中介变量 M 是否在主回归中被控制?
→ 若是,立即移除!M 在主方程中是碰撞变量或中介变量
□ 机制分析是否声明"描述性证据"局限?
□ 机制回归是否使用与主方程一致的标准误策略?
```
---
## Step 5:代码生成与执行
### 5.1 软件确认
稳健性检验代码与 Phase 6 使用相同软件。若上游文件中未记录,向用户确认:
> *"请确认稳健性检验代码的软件:*
> *A. Python(自动执行)/ B. R(本地运行)/ C. Stata(本地运行)"*
### 5.2 代码文件结构
```
code/
├── 05_robustness.[py|R|do] # 方法特异性稳健性检验
├── 06_heterogeneity.[py|R|do] # 异质性分析
└── 07_mechanism.[py|R|do] # 机制检验
```
每个脚本头部使用与 Phase 6 一致的文件头格式:
```python
# ============================================================
# Project: [研究问题一句话]
# Phase: 8 — Robustness, Heterogeneity & Mechanism
# Script: 05_robustness.py / 06_heterogeneity.py / 07_mechanism.py
# Strategy: [识别策略]
# Date: [YYYY-MM-DD]
# Input: data/clean/[文件名],tables/table_main.csv
# Output: tables/table_robustness.tex/.csv
# tables/table_heterogeneity.tex/.csv
# tables/table_mechanism.tex/.csv
# figures/fig_robustness_coefplot.png
# ============================================================
```
### 5.3 执行规范
**Python(自动执行)**:
```bash
pip install pyfixest linearmodels rdrobust fwildclusterboot doubleml --quiet
python code/05_robustness.py
python code/06_heterogeneity.py
python code/07_mechanism.py
```
**R / Stata(用户本地执行)**:
生成脚本至 `code/` 目录,提示用户在本地运行后上传结果。
### 5.4 稳健性结果验证清单
```
=== Phase 8 验证清单 ===
□ 主系数在稳健性检验中是否保持显著且符号一致?
□ 若某规格下系数发生实质性变化,是否已明确解释原因?
□ 异质性交互项是否有理论支撑(避免数据挖掘)?
□ 机制分析中是否避免控制了中介变量?
□ 稳健性表格是否同时有 .tex 和 .csv 输出?
□ 系数比较图(coefplot)是否已生成?
```
---
## Step 6:产出稳健性汇总表(LaTeX)
### 6.1 稳健性结果表格规范
稳健性表格通常较宽,**使用横向排版(landscape)**,规格为行、数字列(β̂、SE、N)为列:
```latex
\begin{landscape}
\begin{table}[ht]
\centering
\caption{\textbf{Robustness Checks}}
\label{tab:robustness}
\begin{threeparttable}
{\footnotesize\setlength{\tabcolsep}{5pt}
\begin{tabular}{l p{5.5cm} c c c c c}
\toprule
& & \multicolumn{5}{c}{Dependent Variable: \textit{[Y]}} \\
\cmidrule(lr){3-7}
Spec. & Description & $\hat{\beta}$ & SE & $p$-val & $N$ & $R^2$ \\
\midrule
\textbf{(1)} & \textbf{Main specification} & & & & & \\
\midrule
\multicolumn{7}{l}{\textit{Panel A: Standard Error Alternatives}} \\
(2) & HC3 robust SE & & & & & \\
(3) & Two-way clustered SE & & & & & \\
\midrule
\multicolumn{7}{l}{\textit{Panel B: Sample Restrictions}} \\
(4) & Exclude top/bottom 1\% of $Y$ & & & & & \\
(5) & Exclude high Cook's $D$ obs. & & & & & \\
\midrule
\multicolumn{7}{l}{\textit{Panel C: Alternative Specifications}} \\
(6) & Log transformation of $Y$ & & & & & \\
(7) & Add quadratic $D^2$ & & & & & \\
\midrule
\multicolumn{7}{l}{\textit{Oster (2019) Coefficient Stability}} \\
\quad $\delta$ &
\multicolumn{6}{l}{$\delta = [VALUE]$;\quad
$|\delta| \gg 1$ implies OVB implausibly large to explain result.} \\
\bottomrule
\end{tabular}}
\begin{tablenotes}[flushleft]\small
\item \textit{Notes}: [样本描述]. SE clustered at [level] unless stated.
$^{***}p<0.01$, $^{**}p<0.05$, $^{*}p<0.10$.
\end{tablenotes}
\end{threeparttable}
\end{table}
\end{landscape}
```
**Oster δ 格式规范**(延续已有设计):
若 δ 文本超过一行,移入 tablenotes 节,正文单元格只放数值:
```latex
\quad $\delta$ & \multicolumn{6}{l}{$\delta = [VALUE]$} \\
% tablenotes 中:
\item Oster (2019) $\delta$: ratio of selection on unobservables to observables
needed to fully explain the result with omitted variable bias.
$|\delta| \gg 1$ implies the result is robust to OVB.
```
### 6.2 异质性结果表格
异质性表格的标准格式:主效应 + 分组效应 + 交互项列:
```latex
% 异质性表格列结构(示例)
\begin{tabular}{lccc}
\toprule
& Full Sample & High [M] & Low [M] \\
\midrule
$D$ (treatment) & [β̂] & [β̂_H] & [β̂_L] \\
& ([SE]) & ([SE]) & ([SE]) \\
$D \times$ High [M] & & [β̂_int]$^{**}$ & \\
& & ([SE]) & \\
\midrule
$N$ & [N] & [N_H] & [N_L] \\
\bottomrule
\end{tabular}
```
### 6.3 系数比较图(Coefplot)
生成稳健性检验主系数及 95% CI 的并排系数图:
```python
# Python — 稳健性系数比较图
import matplotlib.pyplot as plt
import numpy as np
specs = ["Main", "HC3 SE", "Clustered SE", "No Outliers", "Log Y", ...]
coefs = [beta_main, beta_hc3, beta_clus, beta_noout, beta_log, ...]
ci_lo = [ci_lo_main, ...]
ci_hi = [ci_hi_main, ...]
fig, ax = plt.subplots(figsize=(8, 5))
y_pos = np.arange(len(specs))
for i, (spec, coef, lo, hi) in enumerate(zip(specs, coefs, ci_lo, ci_hi)):
ax.errorbar(coef, i, xerr=[[coef-lo], [hi-coef]],
fmt='o', ms=6, capsize=4,
color='#C0392B' if i==0 else '#2C3E50')
ax.axvline(0, color='gray', ls='--', lw=1)
ax.set_yticks(y_pos); ax.set_yticklabels(specs)
ax.set_xlabel("Coefficient (95% CI)")
ax.set_title("Robustness Checks: Main Coefficient")
plt.tight_layout()
plt.savefig("figures/fig_robustness_coefplot.png", dpi=150)
```
```stata
* Stata — coefplot
coefplot (m_main, label("Main")) ///
(m_hc3, label("HC3 SE")) ///
(m_clus, label("Clustered SE")) ///
(m_nout, label("No Outliers")) ///
, keep(D_var) xline(0) ///
title("Robustness Checks: Main Coefficient") ///
graphregion(color(white))
graph export "figures/fig_robustness_coefplot.png", replace
```
---
## Step 7:产出 `robustness-report.md`
整合本阶段所有结果,写入工作目录:
```
Write: [workspace]/robustness-report.md
```
**文档结构:**
```markdown
# Robustness Report
**项目:** [研究问题一句话]
**版本:** v1.0
**日期:** [YYYY-MM-DD]
**主系数(Phase 6):** β̂ = [值](SE = [值],p = [值])
---
## 1. 稳健性检验汇总
### 1.1 检验清单完成情况
| 编号 | 检验类型 | 来源 | 结果 | 结论 |
|------|---------|------|------|------|
| R1 | [检验名] | 方法通用 | β̂=[值], p=[值] | ✅ 稳健 / ⚠️ 有变化 / ❌ 不稳健 |
| ... | | | | |
### 1.2 主要结论
[2–3句话:哪些规格下结论稳健?哪些规格下系数有变化及其经济学解释]
**主系数稳健性判断:**
- 符号一致性:[在所有/绝大多数/部分规格下符号一致]
- 量级稳定性:[系数范围 X 至 Y,主规格为 Z]
- 统计显著性:[在所有/绝大多数规格下在 X% 水平显著]
---
## 2. 异质性分析结果
### 2.1 [分组维度 1]
**理论预测:** [预设的异质性方向]
**结果:** [β̂_高 = X vs. β̂_低 = Y;交互项 p = Z]
**解释:** [与理论预测是否一致?如不一致,给出经济学解释]
### 2.2 [分组维度 2]
[同上格式]
---
## 3. 机制检验结果
### 3.1 主要因果渠道
**机制假设:** D → [M] → Y
**支持证据:**
- D 对 M 的效应:β̂_{D→M} = [值](p = [值])[✅ 显著 / ❌ 不显著]
- 控制 M 后 D 对 Y 的效应:β̂_{直接} = [值](原始效应:[主系数值])
- 间接效应(近似):[值],占总效应的 [%]%
**注意事项:** [中介分析的内生性局限性]
### 3.2 竞争性解释排除
| 竞争性解释 | 排除检验 | 结果 | 结论 |
|----------|---------|------|------|
| [解释 A] | [检验] | p = [值] | ✅ 已排除 / ⚠️ 部分支持 |
---
## 4. 产出文件清单
- `tables/table_robustness.tex` / `.csv`
- `tables/table_heterogeneity.tex` / `.csv`
- `tables/table_mechanism.tex` / `.csv` (如适用)
- `figures/fig_robustness_coefplot.png`
- `code/05_robustness.[ext]`
- `code/06_heterogeneity.[ext]`
- `code/07_mechanism.[ext]`(如适用)
---
## 5. Phase 9 写作建议
根据本阶段结果,给出论文 Robustness Section 的写作建议:
- **稳健性结论一句话概括**(可直接用于论文):
"[主系数] 在各种稳健性检验中保持稳定,系数范围为 [X, Y],均在 [Z]% 水平显著(表 X)。"
- **需要重点解释的偏差**:[若某规格系数变化较大,建议在论文中主动解释]
- **异质性发现的定位**:[异质性分析应进主结果节还是附录?]
- **机制讨论的语言强度建议**:[直接机制证据 / 间接相容证据 / 排除竞争解释]
```
---
## Step 8:阶段确认与移交
向用户呈现阶段摘要:
> **Phase 8 产出摘要**
>
> ✅ 稳健性检验代码:`code/05_robustness.[ext]`
> ✅ 异质性分析代码:`code/06_heterogeneity.[ext]`
> ✅ 机制检验代码:`code/07_mechanism.[ext]`(如适用)
> ✅ 稳健性结果表:`tables/table_robustness.tex` + `.csv`
> ✅ 异质性结果表:`tables/table_heterogeneity.tex` + `.csv`
> ✅ 系数比较图:`figures/fig_robustness_coefplot.png`
> ✅ 稳健性报告:`robustness-report.md`
>
> ---
>
> **Phase 8 结论摘要:**
>
> - 稳健性结论:[主系数在 X/Y 项检验中保持一致,符号稳定,量级范围 ...]
> - 最重要的异质性发现:[...]
> - 机制证据:[支持 / 不支持 / 无结论性证据]
>
> 待您确认稳健性结论后,进入 **Phase 9(全文写作)**,运行 `/write` 指令。
---
## 常见问题处理
**Q:某稳健性检验下主系数不再显著,怎么办?**
按以下优先级判断和处理:
1. 先检查规格变化是否引入了经济上合理的不同识别(如带宽缩窄导致样本代表性变化)
2. 若系数量级变化不大但 SE 增大(如小样本子组),诚实汇报而非选择性不报
3. 若系数量级实质缩小,在论文中主动讨论该规格反映了什么不同假设
4. **不得选择性只报告显著结果**(p-hacking),所有预设检验均须报告
**Q:异质性分析发现了意外的差异模式,但缺乏理论支撑,该怎么处理?**
意外的异质性发现有两种处理方式:
1. 若能事后提供合理的经济学机制解释,可纳入论文但必须明确标注"探索性发现"
2. 若无法提供合理解释,建议只在附录中报告,正文不作过度解读
**Q:机制分析中的中介变量本身是内生的,还有意义吗?**
有意义,但需在论文中清晰声明局限性。标准做法是:
1. 说明中介分析仅提供"与机制一致的描述性证据"
2. 若中介变量有外生变异来源,可进一步使用 IV 或 DiD 验证中介路径
3. 若无法解决中介变量内生性,重新定位该检验为"排除竞争性解释"(检验 D→M 是否显著)而非完整中介分析
---
## 与其他指令/技能的衔接
- **上游**:`/code`(Phase 6,产出 `diagnostic_report.md`)→ `results-analysis` skill(Phase 7,产出 `results-memo.md`)
- **本阶段调用的技能**:
- `did-analysis` — 交错 DiD 估计量比较(Callaway-Sant'Anna、Sun-Abraham)
- `iv-estimation` — IV 稳健性(弱工具变量检验、LIML、Anderson-Rubin CI)
- `rdd-analysis` — RDD 稳健性(带宽敏感性、安慰剂截断点)
- `panel-data` — 面板稳健性(聚类层级比较、Jackknife)
- `ml-causal` — 异质性处理效应的机器学习估计(可选)
- **下游**:`/write`(Phase 9,读取 `robustness-report.md` 写作稳健性节)Phase 9 Full Paper Writing. Reads all upstream outputs (model-spec.md, results-memo.md, robustness-report.md, literature-review-report.md) and drafts any section or the complete paper to Top-5 economics journal standards following a narrative-driven structure; assembles LaTeX, compiles to PDF, and exports DOCX via pandoc, producing a final paper/ directory.
# /write — 全文写作
## 定位
`/write` 是实证研究工作流的**第九阶段**,承接前八个阶段的全部产出,将研究从"有结果"推进到"有论文"。核心职责:
1. 读取所有上游输出文件,提取可直接嵌入论文的数字、表格引用和写作建议
2. 按 Top-5 期刊(AER/QJE/JPE/REStud/Econometrica)的写作规范,以**叙事推进逻辑**分节起草论文
3. 正文图表与附录图表按重要性分流;横向宽表独占横排页面
4. 组装完整 LaTeX 全文,编译验证,产出 `paper/paper.pdf`;并用 pandoc 导出 `paper/paper.docx`
---
## Step 0:读取上游输出
> 📎 **参见 [`shared/context-reader.md`](../shared/context-reader.md)**
> 本阶段所需文件:`model-spec.md`(必需)、`results-memo.md`(必需)。可选文件:`research-question.md`、`literature-review-report.md`、`identification-memo.md`、`data-report.md`、`robustness-report.md`、`tables/table_main.csv`。
### 0.2 提取写作关键信息
从各文件中提取以下内容,构建**写作信息底稿**,后续各节直接调用:
| 来源 | 提取内容 | 用于哪节 |
|------|---------|---------|
| `research-question.md` | 研究问题一句话、政策背景 | 摘要、引言 |
| `literature-review-report.md` | 文献综述主线、本文贡献定位、近年引用 | 引言、文献综述 |
| `identification-memo.md` | 识别策略逻辑(三层辩护)、核心假设 | 实证策略节 |
| `model-spec.md §2` | 主方程 LaTeX、符号说明 | 实证策略节 |
| `model-spec.md §4` | 标准误策略及理由 | 实证策略节 |
| `data-report.md §2–3` | 样本量 N、时间跨度、变量定义 | 数据节 |
| `results-memo.md §1` | 主系数 β̂、SE、p 值、95% CI | 摘要、引言、结果节 |
| `results-memo.md §2` | 经济显著性(σ单位效应量、相对均值%) | 结果节 |
| `results-memo.md §4` | 识别可信度及语言强度建议 | 全文因果语言 |
| `results-memo.md §5` | 外部有效性局限性 | 讨论节、结论节 |
| `robustness-report.md §1` | 稳健性一句话结论(范围 + 显著性) | 摘要、稳健性节 |
| `robustness-report.md §2` | 异质性结论(分组 + 交互项显著性)| 异质性/讨论节 |
| `robustness-report.md §3` | 机制证据及语言强度 | 机制/讨论节 |
| `robustness-report.md §5` | Phase 9 写作建议(直接使用)| 所有节 |
提取完成后向用户输出写作信息底稿确认:
```
═══════════════════════════════════════════════════════
Phase 9 写作信息底稿
═══════════════════════════════════════════════════════
研究问题:[X 对 Y 的影响]
识别策略:[策略名称]
目标参数:[ATE / ATT / LATE]
主系数:β̂ = [值](SE = [值],p = [值])
因果语言强度:[因果语言 / 审慎因果 / 相关性语言]
稳健性结论:[一句话]
异质性关键发现:[有/无,一句话]
机制证据:[有直接证据 / 间接相容证据 / 无]
═══════════════════════════════════════════════════════
```
---
## Step 1:写作任务确认
### 1.1 节次选择
向用户确认写作范围:
> *"请选择写作目标:*
>
> - **A. 完整论文**(推荐):按顺序起草所有节,组装 LaTeX 全文并编译
> - **B. 指定节次**:选择一个或多个节次单独起草
>
> 可用节次:*
> ① 摘要(Abstract)*
> ② 引言(Introduction)*
> ③ 文献综述(Literature Review)*
> ④ 数据节(Data)*
> ⑤ 实证策略节(Empirical Strategy)*
> ⑥ 结果节(Results)*
> ⑦ 稳健性节(Robustness)*
> ⑧ 异质性与机制节(Heterogeneity & Mechanisms)*
> ⑨ 讨论节(Discussion)*
> ⑩ 结论节(Conclusion)"*
### 1.2 语言确认
> *"论文语言:中文 / 英文?(默认:英文,符合国际期刊投稿惯例)"*
### 1.3 目标期刊(可选)
若用户指定目标期刊,按该期刊的格式要求调整:
| 期刊 | 字数上限 | 表格位置 | 引注格式 | 特殊要求 |
|------|---------|---------|---------|---------|
| AER | ~12,000 词 | 文末 | Author (Year) | 贡献宣示简洁,不宜超过 3 条 |
| QJE | 无硬性上限 | 文末 | Author (Year) | Introduction 要求极高,通常 4–6 页 |
| JPE | ~12,000 词 | 文末 | Author (Year) | 偏好简洁,讨论节可与结果节合并 |
| REStud | ~12,000 词 | 文末 | Author (Year) | 理论/方法结合型论文偏多 |
| Econometrica | 无硬性上限 | 文末 | Author (Year) | 数学严谨性要求最高 |
---
## Step 1.5:叙事推进原则(写作前必读)
**经济学实证论文本质上是一个因果故事**,读者从第一段开始就应该被带着走完整个研究旅程。写作时必须遵循以下原则,而非生成孤立段落的堆砌。
### 核心叙事弧
```
引言(提问)
→ 文献(已知边界)
→ 数据(研究舞台)
→ 识别策略(解题思路)
→ 主要结果(答案 + 量级)
→ 稳健性(为什么可信)
→ 机制/异质性(为什么如此)
→ 结论(So what)
```
每一节都应以**承接上一节的一句话**开篇,并以**预告下一节的一句话**结尾,形成连贯的叙事链条。
### 图表叙事配合规则
每一张引用的表格或图形,正文中必须做到三件事:
| 步骤 | 说明 | 示例 |
|------|------|------|
| **① 预告**(在引用前) | 告诉读者即将看到什么 | *"Table 2 presents our main results."* |
| **② 解读**(与引用同段)| 从表/图中提炼一句核心结论,包含具体数字 | *"The coefficient on D is 0.12 (s.e. = 0.04), implying..."* |
| **③ 评价**(引用后) | 说明这个结果对研究故事意味着什么 | *"This is consistent with our identification assumption."* |
**禁止**只写 *"See Table X."* 或 *"Figure Y shows the results."* 而不给出数字和解读。
### 正文 vs. 附录的图表分流规则
**放正文的图表**(直接支撑主叙事的发现):
| 类型 | 条件 |
|------|------|
| 描述性统计表(Table 1)| 必须在正文 |
| 主回归表(通常为 Table 2)| 必须在正文 |
| 核心识别图(事件研究图、RDD 断点图、IV 一阶段图)| 必须在正文 |
| 主要异质性结果表(若构成核心贡献之一)| 在正文 |
**放附录的图表**(支撑性或补充性发现):
| 类型 | 理由 |
|------|------|
| 稳健性检验表(多列规格对比)| 验证性,不是新发现 |
| 平衡性检验表(DiD/IV 的 balance table)| 技术性,编辑通常接受 |
| 变量定义表 | 参考性 |
| 额外的异质性分组 | 超出核心贡献的延伸 |
| 数据清洗流程表(样本筛选漏斗)| 技术性 |
| 补充机制检验图 | 探索性 |
### 横向宽表(景观页)规则
**判断标准**:回归表超过 **5 列**,或在标准页面宽度(`\textwidth`)内会产生 `Overfull \hbox > 5pt` 时,**必须**独占一页横向排版:
```latex
\begin{landscape}
\begin{table}[p] % [p] = 独占浮动页
\caption{[表格标题]}
\label{tab:xxx}
\footnotesize % 稍小字号
\begin{tabular}{...}
...
\end{tabular}
\end{table}
\end{landscape}
```
适用场景:主稳健性表(多规格对比)、异质性分组表(多子组)、平行趋势前后期分列表。
---
## Step 2:各节写作规范
> 📎 **输出格式规范参见 [`shared/output-standards.md`](../shared/output-standards.md)**
**分工说明**:本步骤定义的是**内容规范**——每节该写什么、从哪个上游文件取数据、禁止哪些表达。**LaTeX 模板结构**(preamble、各节骨架、编译流程)由 `paper-writing` skill 提供,执行写作时同时参照两者。
调用 `paper-writing` skill 并传入以下上下文(Mode A,跳过 skill 内部 Q&A):
- 研究类型:实证
- 目标期刊:`[来自 Step 1.3]`
- 论文语言:`[来自 Step 1.2]`
- 写作范围:`[来自 Step 1.1]`
- 因果语言强度:`[来自 results-memo.md §4]`
各节内容规范如下,这是 Top-5 期刊区别于一般期刊的核心要求:
---
### 2.1 摘要(Abstract)
**格式**:150–200 词,5–6 句话,结构固定:
```
句1:研究问题(What question)
句2–3:方法与数据(How + Where)
句4–5:主要发现,必须包含具体数字(What we find)
句6:贡献/政策含义(So what)
```
**必填项**:
- 必须含主系数量级(绝对值或相对均值百分比)
- 必须含识别策略名称("exploiting..."/"using a difference-in-differences design...")
- 不得仅报告统计显著性而不报告量级
**模板**:
```latex
\begin{abstract}
\noindent
[RESEARCH QUESTION IN ONE SENTENCE].
Using [DATA SOURCE] covering [N] [UNITS] over [PERIOD],
we exploit [IDENTIFICATION STRATEGY] to identify
the causal effect of [D] on [Y].
We find that [MAIN FINDING WITH COEFFICIENT]:
[D] [increases/decreases] [Y] by [MAGNITUDE]
[UNITS/PERCENT/SD],
[SIGNIFICANCE STATEMENT].
This effect is [heterogeneous/concentrated in/robust to],
with [KEY HETEROGENEITY OR ROBUSTNESS FINDING].
Our results [CONTRIBUTION: inform/challenge/extend]
[POLICY/THEORY IMPLICATION].
\end{abstract}
```
---
### 2.2 引言(Introduction)
Top-5 期刊的 Introduction 通常为 4–6 页(约 1,500–2,000 词),严格遵循以下**五段结构**:
**第一段:研究问题 + 主要发现(数字必须出现)**
> 要求:第一段结束前,读者必须知道(1)研究的问题是什么;(2)主要发现是什么;(3)效应的量级是多少。这是 AER/QJE 的不成文规范。
```latex
% 第一段模板
[HOOK SENTENCE — 一个引发政策或理论关注的事实/数字].
[RESEARCH QUESTION]. This paper provides causal evidence that
[MAIN FINDING]: [D] [causes/is associated with] a
[MAGNITUDE] [increase/decrease] in [Y],
[SIGNIFICANCE — e.g., "statistically significant at the 1\% level"].
```
**第二段:为什么这个问题难回答(内生性威胁)**
> 说明 OLS 的偏误方向和来源,为识别策略做铺垫。
```latex
% 第二段模板
Estimating the causal effect of [D] on [Y] is challenging
for three reasons. First, [OVB THREAT]. Second,
[REVERSE CAUSALITY THREAT]. Third, [MEASUREMENT ERROR/SELECTION].
Prior work using [OLS/cross-section] is likely to
[overstate/understate] the true effect because [DIRECTION OF BIAS].
```
**第三段:本文的识别策略与数据**
> 清晰描述外生变异来源,让读者理解为什么这里的估计是可信的。
**第四段:主要发现汇总(含异质性 + 稳健性一句话)**
> 量级、方向、主要异质性维度、稳健性结论。
**第五段:贡献定位 + 路线图**
> 对应 `literature-review-report.md` 的文献定位,明确说明与最近相关论文的区别;最后一句是路线图。
**引言写作禁忌**:
```
❌ 第一句话是 "This paper examines..."(太弱,直接陈述发现)
❌ 只报告统计显著性,不报告量级("我们发现显著正效应")
❌ 贡献宣示超过 4 条(审稿人会认为过度宣传)
❌ 路线图段超过 5 句话(简洁:一节一句)
❌ 在引言中出现数学公式或技术细节
```
---
### 2.3 文献综述节(Literature Review / Related Work)
**结构**:按研究主题组织,**不按时间顺序**。通常 2–4 个子主题,每个主题 1–3 段。
**必须包含**:
1. **与本文最相关的 3–5 篇论文**:说明它们做了什么、发现了什么、本文如何不同
2. **识别策略的先例**:哪些论文用过类似方法研究类似问题
3. **明确的贡献定位**:用 "Unlike [PAPER], we..." 句式结束每个子主题
**来源**:直接使用 `literature-review-report.md` 的结构,不重新检索。
---
### 2.4 数据节(Data)
**结构**:
```
§ 数据来源与样本构建
§ 核心变量定义
§ 描述性统计(Table 1,引用 tables/table1_descriptive.tex)
[§ 平衡性检验,若 DiD/IV,引用 tables/table2_balance.tex]
```
**规范**:
- 样本量、时间跨度、地域范围必须用具体数字(来自 `data-report.md §2`)
- 变量定义精确,与 `model-spec.md §2` 的符号保持一致
- 异常值处理方式需在此节说明(来自 `data-report.md §4`)
- Table 1 必须覆盖 Y、D、Z 及主要控制变量,格式:N、均值、标准差、p25、p75
**Table 1 引用格式**:
```latex
Table~\ref{tab:sumstats} reports summary statistics for our
main analysis sample. The average [Y] is [MEAN] ([SD]),
and [D PERCENT]\% of [UNITS] are [TREATED].
[KEY OBSERVATION ABOUT THE DATA — e.g., variation, distribution].
```
---
### 2.5 实证策略节(Empirical Strategy)
**这是审稿人审查最仔细的节**,必须覆盖:
1. **主方程**:直接使用 `model-spec.md §2` 的 LaTeX 方程,不重新推导
2. **识别假设**:正式表述每个假设(来自 `identification-memo.md §4`)
3. **识别假设的可检验性**:说明如何检验并预告结果("In Section X, we show...")
4. **标准误策略**:类型 + 聚类层级 + 经济学理由(来自 `model-spec.md §4`)
**识别假设陈述模板**(以平行趋势为例):
```latex
% 识别假设正式陈述
The key identifying assumption is that, in the absence of treatment,
treated and control units would have followed parallel trends:
\begin{equation*}
E[Y_{it}(0) - Y_{it'}(0) \mid D_i = 1]
= E[Y_{it}(0) - Y_{it'}(0) \mid D_i = 0], \quad \forall\, t \neq t'.
\end{equation*}
This assumption would be violated if [SPECIFIC THREAT].
We provide evidence supporting this assumption
in Section~\ref{sec:robustness}, where [BRIEF PREVIEW OF TEST RESULT].
```
**语言强度规范**:
| 识别可信度(来自 results-memo.md §4)| 识别假设表述 | 结果表述 |
|--------------------------------------|------------|---------|
| 高(所有假设 ✅)| "The causal effect of D on Y..." | "causes", "increases", "reduces" |
| 中(含 ⚠️)| "The effect of D on Y, as estimated by [STRATEGY]..." | "is associated with", "predicts" |
| 低(含 ❌)| "We document a correlation between D and Y..." | "is correlated with", "we observe" |
---
### 2.6 结果节(Results)
**Lead with numbers**(Top-5 期刊的核心规范):
> 结果节第一句话必须包含主系数数值。不得写"Table 2 shows our main results"而不给出具体数字。
**节内结构**:
```
§ 主要结果(引用 Table 2 主回归表)
- 第一句:β̂ = [值],显著性,量级解读
- 逐列介绍:Baseline → +控制变量 → +FE → 首选规格
- 经济显著性讨论(必须!)
[§ 事件研究 / 动态效应(若 DiD,引用 Fig. 1 事件研究图)]
[§ 主要异质性发现(若重要,引用 Table 3 异质性表)]
```
**经济显著性讨论格式**(来自 `results-memo.md §2`):
```latex
% 经济显著性段落模板
To assess economic significance, note that the sample mean of
[Y] is [MEAN]. Our estimate of [COEFFICIENT] implies that
[D] is associated with a [MAGNITUDE PERCENT]\% [increase/decrease]
in [Y] relative to the mean, or approximately [SD-UNIT] standard deviations.
[COMPARISON TO LITERATURE: This is [larger/smaller] than the estimate
of \citet{CLOSEST PAPER}, who find [THEIR ESTIMATE] using [THEIR METHOD].]
```
**逐列介绍规范**:
```latex
% 逐列介绍模板
Column (1) presents the baseline specification without controls.
The coefficient on [D] is [β̂_1] (s.e. = [SE_1]),
suggesting [DIRECTION] of [Y]. Adding [CONTROL SET] in column (2)
[leaves the estimate stable / reduces the estimate to [β̂_2]],
consistent with [INTERPRETATION OF CHANGE].
Our preferred specification in column ([N]) includes [FULL CONTROLS]
and yields [FINAL ESTIMATE] ([SE], [SIGNIFICANCE]).
```
---
### 2.7 稳健性节(Robustness)
**节内结构**:
```
§ 开篇结论句(先给结论,再展示细节)
§ Panel A:推断方法稳健性(替代标准误)
§ Panel B:样本稳健性(子样本、异常值剔除)
§ Panel C:规格稳健性(函数形式、控制变量集合)
§ Panel D:识别假设检验(安慰剂、预趋势等,策略特异性)
[§ Oster δ 系数稳定性]
```
**开篇结论句**(直接使用 `robustness-report.md §5` 的建议语言):
```latex
% 稳健性节开篇句模板
Table~\ref{tab:robustness} reports a battery of robustness checks.
Our main finding is robust: [MAIN COEFFICIENT RANGE — e.g.,
"the coefficient on [D] ranges from [MIN] to [MAX] across specifications,
remaining statistically significant at the [X]\% level in all cases"].
```
**对任何系数发生实质性变化的规格**,必须主动解释(不得只呈现表格):
```latex
% 系数变化的解释模板
In column ([N]), [WHAT CHANGES — e.g., "we restrict the sample to..."].
The estimate [increases/decreases] to [NEW ESTIMATE], reflecting
[ECONOMIC INTERPRETATION — e.g., "the composition of the subgroup"].
This change is consistent with [MECHANISM/THEORY], and does not
challenge our main conclusion because [REASON].
```
---
### 2.8 异质性与机制节(Heterogeneity and Mechanisms)
此节在很多 Top-5 论文中与 Results 节合并,也可单独成节。按以下顺序叙述:
**异质性分析(来自 `robustness-report.md §2`)**:
1. 先陈述理论预测(为什么预期存在异质性)
2. 再呈现表格结果(引用 `tables/table_heterogeneity.tex`)
3. 结论需回应理论预测(是否符合预期,如不符合需解释)
**机制分析(来自 `robustness-report.md §3`)**:
语言强度按 `robustness-report.md §5` 建议:
- "直接机制证据"(有外生识别)→ "provides direct evidence for"
- "间接相容证据"(仅描述性)→ "is consistent with" / "provides suggestive evidence"
- 排除竞争性解释 → "rules out" / "cannot be explained by"
---
### 2.9 结论节(Conclusion)
**Top-5 期刊的结论节通常只有 1–2 页**,结构:
```
① 复述问题 + 方法(1句)
② 主要发现(2–3句,含量级)
③ 稳健性摘要(1句)
④ 政策含义或理论贡献(2–3句)
⑤ 局限性(1–2句,诚实但简洁)
⑥ 未来研究方向(1–2句)
```
**结论禁忌**:
```
❌ 引入任何在正文中未出现的新结果
❌ 重复复述整个论文(读者已经读了)
❌ 只说"我们做了X发现了Y"不谈 So what
❌ 结论超过 2 页(审稿人会注意到)
```
---
## Step 3:LaTeX 全文组装
### 3.1 文件目录结构
```
paper/
├── paper.tex # 主文件(\input 各节)
├── sections/
│ ├── abstract.tex
│ ├── introduction.tex
│ ├── literature.tex
│ ├── data.tex
│ ├── strategy.tex
│ ├── results.tex
│ ├── robustness.tex
│ ├── heterogeneity.tex # 异质性与机制节
│ ├── discussion.tex
│ ├── conclusion.tex
│ └── appendix.tex # 附录(附录图表统一放此处)
├── tables/ # 符号链接或复制自 ../tables/
├── figures/ # 符号链接或复制自 ../figures/
└── references.bib
```
**附录节(appendix.tex)的标准结构**(根据可用上游文件自动填充):
```latex
\appendix
\renewcommand{\thesection}{\Alph{section}} % 附录编号:A, B, C...
\renewcommand{\thetable}{A\arabic{table}} % 表编号:A1, A2...
\renewcommand{\thefigure}{A\arabic{figure}} % 图编号:A1, A2...
\setcounter{table}{0}
\setcounter{figure}{0}
\section{附加稳健性检验}
\label{sec:appendix_robustness}
% 来源:tables/table_robustness_*.tex
\section{平衡性检验}
\label{sec:appendix_balance}
% 来源:tables/table_balance.tex
\section{变量定义}
\label{sec:appendix_variables}
% 来源:data-report.md 中的变量定义表
\section{补充图形}
\label{sec:appendix_figures}
% 来源:figures/ 目录中非核心图形
```
> **附录图表引用规则**:正文中凡引用附录图表,需明确标注位置,例如:*"Appendix Table A1 reports the balance test results."* 或 *"(see Appendix Figure A1)"*。
### 3.2 主文件(paper.tex)
**LaTeX preamble 和前言页结构以 `paper-writing` skill 中的模板为准**(见该 skill 的"LaTeX Preamble (Authoritative)"节)。此处不再重复 preamble 代码,以 skill 为唯一来源,避免版本分歧。
组装时注意以下两点与内容规范直接相关:
1. **`\graphicspath{{../figures/}}`**:路径相对于 `paper/`,指向上级目录的 `figures/`,不要写成 `./figures/`(`paper/` 子目录下不存在 `figures/`)。
2. **`\input` 顺序**:依次为 introduction → literature → data → strategy → results → robustness → heterogeneity → discussion → conclusion,与 Step 3.1 目录结构一致。
### 3.3 参考文献(references.bib)
根据 `literature-review-report.md` 中引用的论文,生成标准 BibTeX 格式:
```bibtex
@article{Author2020,
author = {Author, First and Coauthor, Second},
title = {Title of the Paper},
journal = {American Economic Review},
year = {2020},
volume = {110},
number = {3},
pages = {101--130},
doi = {10.1257/aer.XXXXXXXX}
}
```
---
## Step 4:编译验证 + DOCX 导出
### 4.1 LaTeX → PDF 编译
```bash
cd [workspace]/paper/
pdflatex -interaction=nonstopmode paper.tex # 第1次:生成 .aux
bibtex paper # 处理参考文献
pdflatex -interaction=nonstopmode paper.tex # 第2次:嵌入书目
pdflatex -interaction=nonstopmode paper.tex # 第3次:确保交叉引用
# 检查常见错误
grep -i "overfull\|undefined\|missing\|error" paper.log
grep "Overfull .hbox" paper.log # > 10pt = 可见溢出,必须修复
grep "File.*not found" paper.log # 缺包
grep "Citation.*undefined" paper.log # 未定义引用
```
**常见错误自动修复**:
| 错误 | 原因 | 修复方式 |
|------|------|---------|
| `File 'siunitx.sty' not found` | 表格使用 `S` 列 | 改为 `c` 列或 `D{.}{.}{-1}` |
| `Unicode character U+XXXX` | Python 写入 `≥`、`→` | 替换为 `$\geq$`、`$\rightarrow$` |
| `Overfull \hbox (>10pt)` | 表格超出页宽 | 加 `\begin{landscape}` + `\footnotesize` |
| `Citation xxx undefined` | bib 条目缺失 | 补充到 `references.bib` 后重跑 bibtex |
### 4.2 LaTeX → DOCX 导出
PDF 编译成功后,使用 `pandoc` 将 LaTeX 转为 DOCX,供非 LaTeX 用户审阅和批注:
```bash
cd [workspace]/paper/
# 方式一:pandoc(推荐,保留公式和引用)
pandoc paper.tex \
--bibliography=references.bib \
--citeproc \
--reference-doc=../shared/docx_template.docx \ # 若存在自定义模板
-o paper.docx
# 若无自定义模板(通用方式)
pandoc paper.tex \
--bibliography=references.bib \
--citeproc \
-o paper.docx
echo "✅ DOCX 已导出:paper/paper.docx"
```
若 pandoc 不可用,回退方式:
```bash
# 方式二:LibreOffice headless(较低保真度,但不需要 pandoc)
libreoffice --headless --convert-to docx paper.pdf --outdir .
echo "✅ DOCX 已导出(via LibreOffice):paper/paper.docx"
```
安装 pandoc(若缺失):
```bash
# Ubuntu/Debian
apt-get install -y pandoc 2>/dev/null || true
# macOS
brew install pandoc 2>/dev/null || true
# 检查版本
pandoc --version | head -1
```
### 4.3 编译验证摘要
```
编译验证结果
─────────────────────────────────────────────────────
✅ pdflatex 编译成功(3 次,含 bibtex)
✅ 无 undefined references
✅ 无 missing citations
⚠️ Overfull \hbox (2.3pt) — 次要,可接受
─────────────────────────────────────────────────────
✅ DOCX 导出成功(pandoc / LibreOffice)
─────────────────────────────────────────────────────
输出文件:paper/paper.pdf([N] 页)
paper/paper.docx
```
---
## Step 5:产出文件清单
```
Write: [workspace]/paper/paper.tex
Write: [workspace]/paper/sections/abstract.tex
Write: [workspace]/paper/sections/introduction.tex
Write: [workspace]/paper/sections/literature.tex
Write: [workspace]/paper/sections/data.tex
Write: [workspace]/paper/sections/strategy.tex
Write: [workspace]/paper/sections/results.tex
Write: [workspace]/paper/sections/robustness.tex
Write: [workspace]/paper/sections/heterogeneity.tex
Write: [workspace]/paper/sections/discussion.tex
Write: [workspace]/paper/sections/conclusion.tex
Write: [workspace]/paper/sections/appendix.tex # 附录(附录图表)
Write: [workspace]/paper/references.bib
```
**版本管理**:每次修改后,在文件名中加版本号:
```
paper_v1.0_YYYYMMDD.tex # 初稿
paper_v1.1_YYYYMMDD.tex # 第一轮修改
paper_v2.0_YYYYMMDD.tex # 大幅修改
```
---
## Step 6:阶段确认与移交
向用户呈现阶段摘要:
> **Phase 9 产出摘要**
>
> ✅ 摘要:`paper/sections/abstract.tex`
> ✅ 引言:`paper/sections/introduction.tex`
> ✅ 文献综述:`paper/sections/literature.tex`
> ✅ 数据节:`paper/sections/data.tex`
> ✅ 实证策略节:`paper/sections/strategy.tex`
> ✅ 结果节:`paper/sections/results.tex`
> ✅ 稳健性节:`paper/sections/robustness.tex`
> ✅ 异质性与机制节:`paper/sections/heterogeneity.tex`
> ✅ 讨论节:`paper/sections/discussion.tex`
> ✅ 结论节:`paper/sections/conclusion.tex`
> ✅ 附录:`paper/sections/appendix.tex`(含附录图表)
> ✅ 主文件 + 参考文献:`paper/paper.tex` + `paper/references.bib`
> ✅ PDF:`paper/paper.pdf`([N] 页)
> ✅ DOCX:`paper/paper.docx`(供审阅批注)
>
> 完成初稿后,可运行 `/present` 将论文转化为学术报告幻灯片。Identification Strategy Analysis. Synthesizes research question and literature review to diagnose endogeneity threats, evaluate feasible identification strategies, select the optimal one, and produce an Identification Strategy Memo.
# /analyze — Identification Strategy Analysis
## Step 0:读取上游输出文件
> 📎 **参见 [`shared/context-reader.md`](../shared/context-reader.md)**
> 本阶段所需文件:`research-question.md`(必需)、`literature-review-report.md`(必需)。
读取完成后,输出研究背景确认:
```
═══════════════════════════════════════════════
Phase 3 研究背景信息
═══════════════════════════════════════════════
研究问题:[X 对 Y 的影响]
研究对象:[单位、时间、地域]
识别层级(Phase 1 初判):Level [A/B/C]
数据来源(初步):[数据集名称]
文献主流方法:[DiD / IV / OLS / ...]
代表性估计量:[e.g., 弹性约为 -0.1 至 -0.3]
已知内生性威胁:[OVB:景气周期;反向因果:...]
识别缺口:[现有研究均为 OLS,缺乏准实验证据]
═══════════════════════════════════════════════
```
待用户确认无误后,进入 Step 1。
---
## Step 1: 构建因果框架
### 1.1 定义潜在结果与处理变量
用**潜在结果框架**(Potential Outcomes Framework)明确写出因果问题:
```
目标参数:
- ATE(Average Treatment Effect):所有单位的平均处理效应
- ATT(Average Treatment Effect on the Treated):受处理单位的平均效应
- LATE(Local Average Treatment Effect):顺从者子群的效应(IV专用)
- ATU(Average Treatment Effect on Untreated):未受处理单位的平均效应
请问本研究最关心哪个参数?(若用户未指定,根据研究问题推断并说明理由)
处理变量:[D = 1 if treated, 0 otherwise; 或连续型处理变量]
结果变量:[Y]
核心假设:[Y(1) - Y(0) ≠ 0,即存在处理效应]
```
### 1.2 绘制有向无环图(DAG)
用**文字版 DAG** 描述关键变量之间的因果路径:
```
[说明格式]
→ 表示因果方向
↔ 表示相关(可能存在共同原因)
U 表示未观测混淆变量
示例(最低工资对就业的影响):
最低工资(D) → 就业率(Y)
经济景气(U) ↔ 最低工资(D) ← 混淆路径1(游说与经济周期)
经济景气(U) → 就业率(Y)
劳动需求(M) ← 最低工资(D) → 就业率(Y) ← 可能的中介机制
```
**要求:**
- 明确标出所有**已知混淆路径**(open backdoor paths)
- 明确标出**潜在中介变量**(如果研究机制,避免控制中介)
- 明确标出**碰撞变量**(colliders,控制它反而打开虚假路径)
---
## Step 2: 内生性威胁诊断
对每种已知内生性来源进行系统性检查。**必须覆盖以下三类,不得跳过:**
### 2.1 遗漏变量偏误(Omitted Variable Bias)
**检查清单:**
| 候选遗漏变量 | 与处理变量D的相关方向 | 与结果变量Y的相关方向 | 偏误方向(高估/低估) | 严重程度 |
|------------|---------------------|---------------------|---------------------|---------|
| [列出2–4个最可能的OVB来源] | + / - | + / - | 上偏/下偏 | 高/中/低 |
**严重程度判断标准:**
- **高**:有强理论或实证依据认为相关性大,且无法通过现有数据控制
- **中**:有一定相关性但部分可通过控制变量或面板FE吸收
- **低**:理论上存在但量级可能可忽略
### 2.2 反向因果(Reverse Causality)
明确回答:
> "Y 是否可能反过来影响 D?"
如果是,描述反向因果路径,并说明其对 OLS 估计量的偏误方向。
### 2.3 测量误差(Measurement Error)
检查关键变量(处理变量 D 和结果变量 Y)是否存在:
- **经典测量误差**(随机噪声):导致处理变量系数衰减偏误(attenuation bias)
- **非经典测量误差**:偏误方向不定,需具体分析
- **数据构建问题**:如行政数据中的系统性遗漏、自报数据中的社会期望偏误
### 2.4 样本选择偏误(Sample Selection Bias)
如果样本并非随机,检查:
- 是否存在 **Heckman 型选择**(只有选择参与的人才有结果可观测)
- 是否存在**失访偏误**(attrition)
- 结果变量的**分母定义问题**(如"就业率"的分母人群界定)
---
### 2.5 内生性威胁评估
产出一个内生性威胁评估报告:
```
内生性威胁报告
─────────────────────────────────────────────────────
主要威胁(必须解决):
1. [最严重的内生性来源,一句话描述机制与偏误方向]
2. [次严重...]
次要威胁(需控制或讨论):
3. [...]
可忽略威胁(简要说明为何可忽略):
4. [...]
─────────────────────────────────────────────────────
结论:本研究 OLS 估计量的净偏误方向预计为 [高估/低估/不确定]。
```
---
## Step 3: 识别策略评估矩阵
根据研究问题、内生性威胁、和已知的数据可及性,系统评估**所有可能的识别策略**。
### 3.1 候选策略筛查
| 策略 | 核心假设 | 所需数据条件 | 文献先例 | 可行性评分 |
|------|----------|------------|---------|-----------|
| **工具变量(IV/2SLS)** | 排除约束 + 相关性 | 有效工具变量 | 是/否/部分 | ★★★★☆ |
| **双重差分(DiD)** | 平行趋势假设 | 处理组+控制组,准实验变异 | 是/否/部分 | ★★★★☆ |
| **断点回归(RDD)** | 连续性假设 | 连续型分配变量+阈值规则 | 是/否/部分 | ★★★☆☆ |
| **合成控制(SCM)** | 预处理拟合 | 多个潜在控制单位+长面板 | 是/否/部分 | ★★★☆☆ |
| **面板固定效应(Panel FE)** | 严格外生性 | 个体面板数据 | 是/否/部分 | ★★★★☆ |
| **机器学习因果(DML/CF)** | 无混淆(条件独立) | 高维控制变量可观测 | 是/否/部分 | ★★☆☆☆ |
| **OLS + 丰富控制** | 无遗漏相关变量 | 截面或面板均可 | 是/否/部分 | ★★☆☆☆ |
**可行性评分标准(1–5星):**
- 5★:数据完全满足,假设有据可查,文献先例充分
- 4★:数据基本满足,假设可合理辩护,有类似先例
- 3★:数据部分满足,假设较强但有检验方案
- 2★:数据勉强可用,假设较弱,需大量辩护
- 1★:数据不满足或假设在本研究中不可信
### 3.2 深度评估前两名候选策略
对可行性评分最高的 **2 个策略**,分别展开:
**策略 A:[名称]**
```
适用条件:[为何此策略适合本研究]
核心假设:
假设1(可检验):[正式表述]
→ 检验方案:[具体检验方法]
假设2(不可检验但可讨论):[正式表述]
→ 佐证论点:[理论或间接证据支持]
数据要求:
- 必须有:[...]
- 理想情况下有:[...]
- 替代方案:[...]
主要弱点:
- [最大漏洞是什么?审稿人最可能攻击哪里?]
文献中的先例:
- [引用 Phase 2 文献综述中使用过该方法的论文]
估计的参数类型:[ATE / ATT / LATE]
```
**策略 B:[名称]**
(同上格式)
---
## Step 4: 策略选择与辩护
### 4.1 选定策略
基于 Step 3 的评估,选定最优策略并给出**三层辩护**:
**层次1 — 经济学理论辩护**
> "[选定策略] 之所以适合本研究,是因为 [X 的外生变异来源于...,满足...假设]。"
**层次2 — 文献规范辩护**
> "研究 [类似问题] 的文献普遍采用 [方法](如 Author, Year;Author, Year),本文遵循这一规范并在以下方面有所改进:[...]。"
**层次3 — 数据可及性辩护**
> "本研究数据的结构 [具体描述:如面板维度、政策时点、阈值规则] 满足该策略的核心数据要求。"
### 4.2 拒绝其他策略的理由
对每个被排除的候选策略,给出简短的排除理由(防止审稿人质疑):
| 被排除策略 | 排除理由 |
|----------|---------|
| [策略X] | [具体原因,如:缺乏有效工具变量 / 处理是自选择不满足RDD条件 / ...] |
---
## Step 5: 识别假设的正式化与可检验化
这是 Phase 3 最核心的输出。对选定策略的**每一个核心假设**:
### 5.1 格式要求
每个假设必须包含:
```
假设名称:[e.g., 平行趋势假设]
正式表述:[数学或逻辑形式]
E[Y₀(t) | D=1] - E[Y₀(t) | D=0] = 常数,∀ t < T(处理前各期)
直觉解释:[一句话非技术语言表述]
可检验性:可直接检验 / 间接支持 / 不可检验
检验方法:
- 主检验:[具体方法,如:事件研究图(event study plot),检验处理前各期系数是否联合显著为0]
- 辅助检验:[如:安慰剂检验、假控制组检验]
- 预期结果:[如果假设成立,应观察到什么图形或统计结果]
- 对应 skill:[调用哪个 skill 执行此检验,如 did-analysis / iv-estimation]
违反后果:[如果假设被拒绝,估计量的偏误方向是什么?]
```
### 5.2 各策略的标准假设列表
根据选定策略自动填充以下核心假设:
**若选择 DiD:**
1. 平行趋势假设(Parallel Trends)
2. 无预期效应(No Anticipation)
3. 稳定单元处理值假设(SUTVA)
4. 处理变异的外生性(政策非内生于结果)
**若选择 IV/2SLS:**
1. 相关性假设(Relevance):F 统计量 > 10(Stock-Yogo 临界值)
2. 排除约束(Exclusion Restriction):工具变量仅通过处理变量影响结果
3. 独立性假设(Independence):工具变量与未观测混淆变量无关
4. 单调性(Monotonicity):适用于 LATE 估计
**若选择 RDD:**
1. 连续性假设(Continuity at Cutoff)
2. 无精确操纵(No Precise Manipulation):McCrary 密度检验
3. 无复合处理(No Compound Treatment):阈值处不存在其他不连续
4. 局部线性平滑(Local Linearity)
**若选择 合成控制:**
1. 预处理期拟合优度(Pre-treatment Fit)
2. 无溢出效应(No Spillovers)到控制单位
3. 因子结构稳定性(Factor Model Stability)
**若选择 Panel FE:**
1. 严格外生性(Strict Exogeneity):处理变量与过去和未来的误差项无关
2. 个体固定效应足以控制时不变混淆
3. 无动态面板偏误(若 T 较小)
---
## Step 6: 数据需求规格书
根据选定的识别策略,产出精确的数据需求,对接 Phase 4 的 `data-pipeline` skill:
```
数据需求规格书
══════════════════════════════════════════════════════
研究问题:[复述]
选定识别策略:[复述]
══════════════════════════════════════════════════════
【核心数据集】
数据集名称:[e.g., 中国工业企业数据库]
数据来源:[机构 / URL / 申请方式]
覆盖范围:[年份] × [地理单位] × [个体类型]
关键变量:
- 结果变量 Y:[精确变量名/定义]
- 处理变量 D:[精确变量名/定义]
- 识别变量 Z:[工具变量 / 断点变量 / 政策时点]
- 必须控制的协变量:[列表]
- 可选协变量(用于稳健性):[列表]
单元层级:[个体 / 企业 / 县 / 省 / 国家]
面板结构:是/否;T = [时间跨度]
【数据局限性预警】
- [已知问题1,如:某年份缺失 / 变量代理误差 / 样本代表性]
- [已知问题2]
【如有辅助数据集】
辅助数据集名称:[...]
用途:[用于工具变量构建 / 安慰剂检验 / 机制分析]
══════════════════════════════════════════════════════
```
---
## Step 7: 产出 Identification Strategy Memo
整合以上所有分析,生成`identification-memo.md`文档,保存到工作目录:
**Example Output Format:**
```markdown
# Identification Strategy Memo
**Research Question:**
**Version:** v1.0
**Date:** [YYYY-MM-DD]
---
## 1. 因果框架
### 1.1 目标参数
[ATE / ATT / LATE,附理由]
### 1.2 因果图(DAG)
[文字版 DAG]
---
## 2. 内生性威胁
### 2.1 主要威胁
[来自 Step 2 的威胁列表]
### 2.2 OLS 偏误方向预判
[高估 / 低估 / 不确定,附推理]
---
## 3. 识别策略
### 3.1 选定策略:[策略名称]
**策略概述**
[2–3句话,非技术语言描述识别逻辑]
**识别变异来源**
[具体描述:什么在外生变动?为什么可信?]
**三层辩护**
[来自 Step 4.1]
### 3.2 排除策略说明
[来自 Step 4.2 的表格]
---
## 4. 核心假设与检验计划
| 假设 | 正式表述 | 可检验性 | 检验方法 | 检验时机 |
|------|----------|---------|---------|---------|
| [假设1] | [...] | 可检验 | [...] | Phase 5 建模前 |
| [假设2] | [...] | 间接支持 | [...] | Phase 8 稳健性 |
[每个假设的详细展开,来自 Step 5]
---
## 5. 数据需求规格书
[来自 Step 6]
```
## Handoff
完成上述所有步骤后,提示用户识别策略分析已完成,可进入下一工作阶段:数据准备与探索性分析,是否继续?Phase 6 Code Generation & Execution. Reads identification-memo.md, data-report.md, and model-spec.md, asks user to select software (Python / R / Stata), dispatches to the appropriate estimation skill, generates a reproducible analysis script with main regression, diagnostics, and output export, then executes and verifies results.
# /code — 代码执行与复现
## 定位
`/code` 是实证研究工作流的**第六阶段**,承接 Phase 5(`/model`)的 `model-spec.md`,将形式化的计量模型转化为可执行、可复现的分析代码。核心流程:
1. 读取上游文档,提取估计所需的全部参数
2. 用户选择目标统计软件(Python / R / Stata)
3. 根据识别策略 × 软件,调用对应的**估计技能**生成代码
4. 代码执行 + 结果验证
5. 输出规范化的 `.py` / `.R` / `.do` 脚本至 `code/`,结果表格至 `tables/`
---
## Step 0:读取上游输出
> 📎 **参见 [`shared/context-reader.md`](../shared/context-reader.md)**
> 本阶段所需文件:`identification-memo.md`(必需)、`data-report.md`(必需)、`model-spec.md`(必需)。
提取以下信息用于代码生成:
| 来源 | 提取内容 |
|------|---------|
| `model-spec.md` | 识别策略类型、主方程(LaTeX 转为代码描述)、Y/D/Z/控制变量名称、FE 层级、SE 类型与聚类变量、目标参数 |
| `data-report.md` | 清洗后数据路径(`data/clean/[project_name]_clean.[dta\|parquet]`)、样本量、面板结构、数据质量预警 |
| `identification-memo.md` | 识别假设的可检验形式(决定生成哪些诊断代码) |
提取完成后向用户确认:
> **Phase 6 启动确认**
>
> 识别策略:**[策略]**
> 主方程:$[LaTeX 概述]$
> 数据路径:`data/clean/[文件名]`
> 标准误:**[类型,聚类变量]**
---
## Step 1:软件选择
向用户呈现软件选项:
> *"请选择生成代码所使用的统计软件:*
>
> - **A. Python** ⚡ 推荐 — 代码生成后**自动在沙箱中执行**,结果即时可见
> - **B. R** — 生成 `.R` 脚本,**需在本地安装 R 后手动运行**
> - **C. Stata** — 生成 `.do` 脚本,**需在本地安装 Stata 后手动运行**
>
等待用户确认后进入 Step 2。
> **注**:选择 B 或 C 时,代码文件生成至 `code/` 目录后,Claude 不会在沙箱中执行;请用户下载脚本后在本地环境运行,运行结果可再上传供后续分析。
---
## Step 2:策略 × 软件派发
根据 `identification_strategy` × 软件选择,**调用对应的估计技能**,并传入 Step 0 提取的完整上下文。
### 2.1 派发表
| 识别策略 | 调用的估计技能 | Python 核心包 | R 核心包 | Stata 核心命令 |
|---------|-------------|-------------|---------|--------------|
| DiD / TWFE | `did-analysis` | `linearmodels`, `pyfixest` | `fixest`, `did` | `reghdfe`, `eventstudyinteract` |
| Event Study(交错 DiD)| `did-analysis` | `pyfixest`, `doubleml` | `fixest`, `did`, `sunab` | `reghdfe`, `did_imputation`, `csdid` |
| Sharp / Fuzzy RDD | `rdd-analysis` | `rdrobust` | `rdrobust`, `rddensity` | `rdrobust`, `rddensity` |
| 2SLS / IV | `iv-estimation` | `linearmodels` (`IV2SLS`) | `ivreg`, `AER` | `ivregress`, `ivreg2`, `ranktest` |
| 面板固定效应 | `panel-data` | `linearmodels` (`PanelOLS`) | `fixest`, `plm` | `reghdfe`, `xtreg` |
| 合成控制 | `synthetic-control` | `pysynth`, `synth_runner` | `Synth`, `SCtools` | `synth`, `synth_runner` |
| OLS / 截面回归 | `ols-regression` | `statsmodels`, `linearmodels` | `lm`, `estimatr` | `regress`, `reghdfe` |
| 双重机器学习 | `ml-causal` | `doubleml`, `econml` | `DoubleML`(R 包)| 无原生支持,建议用 Python |
| 时间序列 / VAR | `time-series` | `statsmodels` | `vars`, `urca` | `var`, `vecm`, `arima` |
### 2.2 技能调用格式
> *"调用 `[估计技能名]`,生成 [软件名] 代码。传入参数:*
> - 策略:[识别策略]
> - 主方程:[文字描述]
> - 因变量:`[Y_var]`
> - 处理变量:`[D_var]`
> - 识别变量:`[Z_var(若有)]`
> - 控制变量:`[control_vars 列表]`
> - 个体/时间变量:`[id_var]` / `[time_var]`
> - FE 层级:[个体 + 时间 / 仅个体 / 省 × 年...]
> - SE 类型:[聚类层级]
> - 数据路径:`data/clean/[文件名]`"*
### 2.3 Stata 专项处理
选择 Stata 时,除调用策略对应的估计技能外,**同时调用 `stata` skill** 确保 do-file 格式符合最佳实践(标准文件头、全局路径宏、日志文件、`assert` 验证、版本声明)。
`stata` skill 负责提供:
- `00_master.do` 的标准结构
- `reghdfe` / `ivreg2` / `rdrobust` 的安装命令
- `estout` / `coefplot` 的结果导出代码
- Stata 版本兼容性注意事项
---
## Step 3:代码质量标准
无论选择哪种软件,生成的代码必须满足以下要求,缺一不可:
### 3.1 文件头(Header)
每个脚本顶部必须包含:
```python
# ============================================================
# Project: [研究问题一句话]
# Phase: 6 — Main Estimation
# Strategy: [识别策略]
# Software: Python [version] / R [version] / Stata [version]
# Author: [project_name]
# Date: [YYYY-MM-DD]
# Input: data/clean/[文件名]
# Output: tables/[结果表格], figures/[系数图]
# Model: [主方程的文字描述,对应 model-spec.md §2]
# ============================================================
```
### 3.2 路径与环境
```python
# Python
import os
from pathlib import Path
ROOT = Path(__file__).parent.parent # 项目根目录
DATA = ROOT / "data" / "clean"
OUT_TABLES = ROOT / "tables"
OUT_FIGURES = ROOT / "figures"
OUT_TABLES.mkdir(exist_ok=True)
OUT_FIGURES.mkdir(exist_ok=True)
data_path = DATA / "[project_name]_clean.parquet"
```
```r
# R
root <- here::here() # 需 here 包
data_path <- file.path(root, "data", "clean", "[project_name]_clean.rds")
out_tables <- file.path(root, "tables"); dir.create(out_tables, showWarnings=FALSE)
out_figures <- file.path(root, "figures"); dir.create(out_figures, showWarnings=FALSE)
```
```stata
* Stata
version 17
clear all
set more off
cap log close
global root "[workspace 绝对路径]"
global data "$root/data/clean"
global tables "$root/tables"
global figures "$root/figures"
cap mkdir "$tables"
cap mkdir "$figures"
log using "$root/logs/main_estimation_`c(current_date)'.log", replace
```
### 3.3 数据加载 + 样本确认
```python
# 加载并报告基本维度
df = pd.read_parquet(data_path)
print(f"样本:{len(df):,} 行 × {df.shape[1]} 列")
print(f"时间范围:{df[time_var].min()} – {df[time_var].max()}")
print(f"个体数:{df[id_var].nunique()}")
# 与 data-report.md 中的样本量核对
assert len(df) == EXPECTED_N, f"样本量不符:预期 {EXPECTED_N},实际 {len(df)}"
```
### 3.4 主回归(来自估计技能)
- 严格按照 `model-spec.md` §2 的方程规格,不擅自增减变量
- 使用 §4 指定的 SE 类型和聚类层级
- 代码注释中注明每个参数对应方程中的哪个符号(如 `# β: ATT estimate`)
### 3.5 诊断代码(执行 `model-spec.md §6` 的诊断计划)
诊断的**规格决策**(检验什么、通过标准、失败处理)已在 Phase 5(`/model` Step 3.5)中确定,写入 `model-spec.md §6`。本步骤的唯一职责是**按规格执行**:
1. 读取 `model-spec.md §6.1`(识别假设诊断规格)和 `§6.2`(统计假设诊断规格)
2. 生成 `code/02_diagnostics.[ext]`,严格按照 §6 指定的检验项目、通过标准和失败处理逻辑编写代码
3. 不得在代码阶段自行增减检验项目或修改通过标准
**代码生成规则:**
- §6.1 每一行 → 生成对应的识别诊断代码(`rddensity`、预趋势 F 检验、Hausman 等)
- §6.2 每一行 → 生成对应的统计诊断代码(VIF、BP、BG/Wooldridge、RESET、Cook's D)
- 若 §6 某行标注"失败则终止"→ 代码中加 `assert`(Python)/ `stop()`(R)/ `error`(Stata),失败时自动中断并打印返回建议
- 若 §6 某行标注"继续" → 代码记录 WARN 后继续执行,不中断
**各软件的诊断包对照:**
| 检验 | Python | R | Stata |
|------|--------|---|-------|
| VIF | `statsmodels.variance_inflation_factor` | `car::vif` | `estat vif` |
| 异方差 | `statsmodels.het_breuschpagan` | `lmtest::bptest` | `estat hettest` |
| 序列相关(截面)| `statsmodels.acorr_breusch_godfrey` | `lmtest::bgtest` | `estat bgodfrey` |
| 序列相关(面板)| `linearmodels` Wooldridge | `plm::pwartest` | `xtserial` |
| 截面相关 | `linearmodels` Pesaran CD | `plm::pcdtest` | `xtcsd` |
| RESET | `statsmodels.linear_reset` | `lmtest::resettest` | `estat ovtest` |
| Cook's D | `statsmodels.OLSInfluence` | `cooks.distance` | `predict cooksd` |
| McCrary | `rddensity` Python port | `rddensity::rddensity` | `rddensity` |
| 预趋势联合检验 | `pyfixest.wald_test` | `fixest::wald` | `test`(联合 F) |
| 第一阶段 F | `pyfixest` / `linearmodels` | `AER::ivreg` diagnostics | `estat firststage` |
| Hausman | `linearmodels.compare` | `plm::phtest` | `hausman` |
### 3.6 结果输出
> 📎 **输出格式规范参见 [`shared/output-standards.md`](../shared/output-standards.md)**
所有模型结果必须同时导出:
**回归系数表(`.tex` + `.csv`):**
```python
# Python:使用 pyfixest 或 statsmodels 的 summary_col
from pyfixest.summarize import etable
etable([model_main, model_control1, model_control2],
type="tex",
file=str(OUT_TABLES / "table_main.tex"))
```
```r
# R:使用 modelsummary 或 fixest 的 etable
library(modelsummary)
modelsummary(list("Baseline"=m1, "Controls"=m2, "Full"=m3),
stars=c("*"=0.1, "**"=0.05, "***"=0.01),
gof_omit="AIC|BIC|Log",
output=file.path(out_tables, "table_main.tex"))
```
```stata
* Stata:使用 esttab(estout 包)
esttab m1 m2 m3 using "$tables/table_main.tex", ///
b(3) se(3) star(* 0.10 ** 0.05 *** 0.01) ///
booktabs replace label ///
mtitles("Baseline" "Controls" "Full") ///
keep(`D_var') stats(N r2, fmt(0 3) labels("Obs." "R²"))
```
**系数图(`.png`):**
```python
# Python:matplotlib + 回归结果
fig, ax = plt.subplots(figsize=(7, 4))
coef = result.params[D_var]
ci_lo, ci_hi = result.conf_int().loc[D_var]
ax.errorbar(0, coef, yerr=[[coef - ci_lo], [ci_hi - coef]],
fmt="o", ms=8, capsize=5, color="#C0392B")
ax.axhline(0, ls="--", lw=1, color="gray")
ax.set_title(f"Main Estimate: Effect of {D_var} on {Y_var}")
plt.savefig(OUT_FIGURES / "coef_main.png", dpi=150, bbox_inches="tight")
```
```stata
* Stata:coefplot 包
coefplot m1 m2 m3, keep(`D_var') ///
xline(0) msymbol(D) ///
title("Main Estimates") ///
xtitle("Coefficient (95% CI)") ///
graphregion(color(white))
graph export "$figures/coef_main.png", replace
```
### 3.7 可复现性脚注
每个脚本末尾:
```python
# Python
import sys, platform
print(f"\n{'='*50}")
print(f"Python {sys.version}")
print(f"Platform: {platform.platform()}")
print(f"Date: {pd.Timestamp.now()}")
import importlib
for pkg in ["pandas", "numpy", "statsmodels", "linearmodels", "pyfixest"]:
try:
v = importlib.import_module(pkg).__version__
print(f" {pkg}: {v}")
except Exception:
pass
```
```r
# R
sessionInfo()
```
```stata
* Stata
which reghdfe
which rdrobust
di "Stata version: `c(stata_version)'"
di "Date: `c(current_date)'"
log close
```
---
## Step 4:代码文件结构
所有代码文件保存至 `code/` 目录,按编号命名,保持可单独运行:
```
code/
├── 00_master.[py|R|do] # 主运行脚本:依次调用 01–04
├── 01_main_estimation.[py|R|do] # 主回归(对应 model-spec.md §2 主方程)
├── 02_diagnostics.[py|R|do] # 识别假设诊断(§3.5 列出的全部检验)
├── 03_event_study.[py|R|do] # 事件研究 / 动态效应(DiD/RDD 专用)
└── 04_output_tables.[py|R|do] # 结果表格与系数图生成
```
> **说明**:若主回归、诊断和输出逻辑可在 100 行内完成,允许合并为单文件 `01_main_estimation.[py|R|do]`;复杂设计(交错 DiD、Fuzzy RDD、多种稳健性)应拆分文件。
**`00_master` 模板:**
```python
# 00_master.py — 按顺序运行全部分析脚本
import subprocess, sys
scripts = [
"code/01_main_estimation.py",
"code/02_diagnostics.py",
"code/03_event_study.py",
"code/04_output_tables.py",
]
for s in scripts:
print(f"\n{'='*50}\n运行:{s}\n{'='*50}")
result = subprocess.run([sys.executable, s], check=True)
```
```stata
* 00_master.do
do "$root/code/01_main_estimation.do"
do "$root/code/02_diagnostics.do"
do "$root/code/03_event_study.do"
do "$root/code/04_output_tables.do"
```
---
## Step 5:执行与验证
### 5.1 执行代码
**Python — 沙箱自动执行**
代码生成后,Claude 直接在沙箱中安装依赖并运行,无需用户任何操作:
```bash
pip install pyfixest linearmodels rdrobust doubleml pyreadstat --quiet
python code/00_master.py
```
执行完成后,结果表格(`tables/`)和图形(`figures/`)即时可见,Claude 将在对话中呈现关键数值并进行核查。
---
**R — 生成脚本,用户本地运行**
Claude 生成 `.R` 脚本至 `code/` 目录,**不在沙箱中执行**。用户下载后在本地 R 环境运行:
```r
# 本地 R 中:先安装依赖包(仅首次需要)
install.packages(c("fixest", "rdrobust", "ivreg", "modelsummary",
"here", "AER", "did", "Synth"),
repos = "https://cloud.r-project.org")
# 运行主脚本
source("[workspace]/code/00_master.R")
```
> *"R 脚本已生成至 `code/` 目录。请在本地 R(≥ 4.1)环境中运行 `00_master.R`。如需将运行结果(表格 / 图形)上传,我可继续协助核查和解读。"*
---
**Stata — 生成脚本,用户本地运行**
Claude 生成 `.do` 脚本至 `code/` 目录,**不在沙箱中执行**。用户下载后在本地 Stata 中运行:
> *"Stata do-file 已生成至 `code/` 目录。请在本地 Stata(≥ 15)中运行:*
> ```stata
> do "[workspace]/code/00_master.do"
> ```
> *首次运行前请先安装所需包(联网状态下在 Stata 命令窗口执行):*
> ```stata
> ssc install reghdfe
> ssc install ftools
> ssc install ivreg2 // IV 策略
> ssc install rdrobust // RDD 策略
> ssc install synth // 合成控制
> ssc install eventstudyinteract // Event Study
> ssc install csdid // Callaway-Sant'Anna
> ssc install estout // 结果导出
> ssc install coefplot // 系数图
> ```
> *如需将运行结果(日志 / 表格 / 图形)上传,我可继续协助核查和解读。"*
### 5.2 诊断报告生成与结果验证
代码执行后,汇总两层诊断结果,生成结构化报告并验证关键数值。
**生成 `diagnostic_report.md`(保存至项目根目录):**
```
═══════════════════════════════════════════════════════
MODEL DIAGNOSTIC REPORT
═══════════════════════════════════════════════════════
Project: [project_name]
Strategy: [识别策略]
Model: [Y_var] = f([D_var], [controls]) + [FE 层级]
N: [样本量]
Date: [YYYY-MM-DD]
═══════════════════════════════════════════════════════
【第一层:识别假设诊断】
────────────────────────────────────────────────────────
检验 统计量 结论
────────────────────────────────────────────────────────
[策略对应的识别检验] [值] ✅ PASS / ⚠️ WARN / ❌ FAIL
────────────────────────────────────────────────────────
【第二层:统计假设诊断】
────────────────────────────────────────────────────────
VIF(最大值) [值] ✅ / ❌
Breusch-Pagan p = [值] ✅ / ⚠️(已用稳健 SE)
Breusch-Godfrey p = [值] ✅ / ❌
RESET p = [值] ✅ / ❌
Cook's D(最大值) [值] ✅ / ⚠️
────────────────────────────────────────────────────────
【诊断结论与建议】
────────────────────────────────────────────────────────
❌ 识别假设失败
→ 立即终止,返回 Phase [4/5] 修正:[具体说明]
⚠️ 异方差(已用聚类 SE,可接受)
✅ 无多重共线性问题
✅ 无序列相关
⚠️ Cook's D 超阈值([N 个]高影响观测值)
→ 已纳入 Phase 8 稳健性检验:去除高影响值后重估
════════════════════════════════════════════════════════
```
**结果验证清单(逐项确认):**
```
=== Phase 6 验证清单 ===
□ 主系数方向与 EDA 阶段的方向一致?
□ 样本量与 data-report.md 记录的 N 一致?
□ 标准误类型与 model-spec.md §4 一致(聚类层级正确)?
□ 【第一层识别诊断全部通过?】
□ DiD:预趋势系数联合检验 p > 0.1
□ RDD:McCrary 检验 p > 0.1;协变量无显著跳跃
□ IV:一阶段 F > 10;J-test p > 0.05(过识别时)
□ FE:Hausman 检验支持 FE 选择
□ SC:处理单位预处理期 RMSPE 在捐赠者分布中居中
□ 【第二层统计诊断无阻断性问题?】
□ VIF < 10(所有控制变量)
□ 异方差:若 BP 失败,确认已使用稳健/聚类 SE
□ RESET:p > 0.05,或有经济理论支持当前函数形式
□ Cook's D:高影响值已列出并纳入稳健性
□ 结果表格已导出至 tables/(.tex + .csv)?
□ 系数图已导出至 figures/(.pdf + .png)?
□ diagnostic_report.md 已保存至项目根目录?
```
**若识别假设失败(❌)**:立即停止,不进入 Phase 7,明确告知用户返回哪个阶段修正,原因是什么。
**若统计假设存在 ⚠️**:继续流程,但将问题自动写入 diagnostic_report.md 的"建议"节,Phase 8 的 `/robustness` 命令读取该报告时将自动纳入对应的稳健性检验。
---
## Step 6:阶段确认与移交
向用户呈现阶段摘要:
> **Phase 6 产出摘要**
>
> ✅ 主回归代码:`code/01_main_estimation.[ext]`
> ✅ 诊断代码:`code/02_diagnostics.[ext]`
> ✅ 事件研究代码:`code/03_event_study.[ext]`(如适用)
> ✅ 输出脚本:`code/04_output_tables.[ext]`
> ✅ 主运行脚本:`code/00_master.[ext]`
> ✅ 主回归结果表:`tables/table_main.tex` + `.csv`
> ✅ 系数图:`figures/coef_main.png`
>
> ---
>
> **关键结果摘要:**
> - 主系数 $\hat{\beta}$ = [值](SE = [值],p = [值])
> - 识别假设诊断:[通过 / 存疑,具体说明]
> - 样本量:N = [值]
>
> 代码与结果验证通过后,自动调用 `results-analysis` skill,进入 **Phase 7(结果分析与解释)**,产出 `results-memo.md`。Phase 4 Data Preparation Pipeline. Data fetch, data clean and exploratory analysis. Produce a data report in the end.
# /data — 数据准备与探索性分析
## 定位
`/data` 是实证研究工作流的第四阶段,承接 Phase 3(`/analyze`)产出的 `identification-memo.md`,完成从数据获取到探索性分析的完整流水线,产出 `data-report.md`,为后续计量模型的构建提供分析就绪的数据集。
---
## Step 0: 读取 Phase 3 输出
读取工作目录中的 `identification-memo.md`:
```text
Read: [workspace]/identification-memo.md
```
如文件不存在,立即停止并提示:
> *"未找到 `identification-memo.md`。请先完成 Phase 3,确认识别策略和数据需求规格后再运行 `/data`。"*
如文件存在,从中提取并整理以下信息:
| 信息 | 用途 |
| ----------------------------------- | ---------------------------- |
| 研究问题 | 生成数据报告抬头与样本定义 |
| 选定识别策略 | 决定变量构造与 EDA 检查重点 |
| 目标参数(ATE / ATT / LATE 等) | 决定样本定义与变量解释口径 |
| 核心数据集 | 形成主数据获取任务 |
| 结果变量 Y | 关键变量审计 |
| 处理变量 D | 关键变量审计 |
| 识别变量 Z / cutoff / policy timing | 识别变量构造 |
| 必须控制的协变量 | 变量到位检查 |
| 面板结构 | 单元层级、时间范围、地域范围 |
| 已知数据局限性预警 | Phase 4 风险排查重点 |
提取完成后向用户确认:
> *"已读取 `identification-memo.md`。数据需求规格如下:*
> *核心数据集:[数据集名称]*
> *识别策略:[策略名称]*
> *关键变量:Y=[结果变量],D=[处理变量],Z=[识别变量]*
> *请确认无误,或告知是否有调整。"*
---
## Step 1: 数据获取
### 1.0:数据来源确认(多选)
根据 Step 0 中提取的数据集名称,向用户确认数据来源构成。**支持同时选择多个来源。**
向用户呈现以下确认请求:
> *"根据识别策略分析,本研究需要以下数据集:[从 identification-memo.md 提取的数据集列表]*
>
> 请确认每个数据集的获取方式(可多选):
>
> - **[ ] A. 公开数据**:可通过 API 或网络免费下载(如 FRED、World Bank)
> - **[ ] B. 商业数据库**:需机构订阅账号(如 CSMAR、WIND、Compustat、WRDS)
> - **[ ] C. 自备数据**:已持有文件(调查数据、行政数据、手工整理数据等)
>
> 请告知哪些数据集走哪个渠道,或直接说明来源情况。"*
收到用户回复后:
1. 整理所有数据来源任务清单(每个数据集 → 对应分支标记)
2. 若涉及多个来源,告知用户处理顺序:**先 A(自动获取),再 B(引导下载),再 C(读取自备)**,最后在 Step 2 统一合并
3. 逐一执行各分支,每个分支完成后记录至 `data/raw/data_log.md`
---
### 分支 A:公开数据——API 自动获取
**判断条件:** 数据集可通过公开 API 或网络直接下载,无付费墙。
常见公开数据源包括但不限于:
| 数据源 | 类型 | 获取方式 |
|--------|------|---------|
| FRED | 美国宏观时间序列 | `fredapi` Python 包 |
| World Bank | 跨国发展指标 | `wbdata` Python 包 |
| OECD | 跨国统计 | OECD SDMX API |
| IMF | 国际金融统计 | `imf-reader` Python 包 |
| Yahoo Finance | 金融资产价格 | `yfinance` Python 包 |
| 国家统计局 | 中国宏观数据 | NBS API / EPS 数据平台 |
| CEIC | 宏观时间序列 | WebFetch(需检查访问权限) |
**执行流程:**
1. 调用 `data-pipeline` skill,传入目标数据集名称、变量清单、时间范围
2. 由 `data-pipeline` skill 负责 API Key 检查、代码生成与执行
3. 原始数据保存至 `data/raw/[source_name]_[YYYYMMDD].[csv|dta]`
4. 在 `data/raw/data_log.md` 中追加本次获取记录:
```markdown
## [数据集名称] 获取记录(分支 A)
- 获取日期:[YYYY-MM-DD]
- 数据版本/vintage:[如适用]
- 来源 URL / API endpoint:[...]
- 原始文件路径:data/raw/[文件名]
- 变量数:[K],观测数:[N]
- 合并键(用于多源合并):[如 country_code + year]
```
5. 报告数据维度,继续执行下一个待处理来源(若有),否则进入 Step 1.1。
---
### 分支 B:商业数据库——指引用户自行获取
**判断条件:** 数据集需付费订阅或机构账号,存在付费墙,无法自动下载。
常见需要机构账号的数据库:
| 数据库 | 主要内容 | 典型用途 |
|--------|---------|---------|
| CSMAR(国泰安) | 中国上市公司财务、股票 | 企业金融、公司治理 |
| WIND(万得) | 中国金融市场全品类 | 宏观、债券、股票 |
| CNRDS | 中国研究数据服务平台 | 社会科学微观数据 |
| RESSET | 中国金融数据 | 资产定价 |
| 中国工业企业数据库 | 规模以上工业企业 | 产业经济、贸易 |
| 中国海关数据库 | 进出口交易记录 | 国际贸易 |
| IPUMS | 美国及国际人口普查微观数据 | 劳动经济、人口 |
| Compustat | 全球上市公司财务 | 企业金融 |
| WRDS 系列 | 金融研究综合平台 | 资产定价、金融 |
**执行流程:**
向用户给出具体操作指引:
> *"**[数据库名称]** 需要机构订阅账号,无法自动下载。请按以下步骤获取数据:*
>
> **① 登录数据库**
> [数据库官网或机构访问入口 URL]
>
> **② 下载以下变量**(根据 `identification-memo.md` 的数据需求规格书):
> - 结果变量:[Y 的精确变量名/字段名]
> - 处理变量:[D 的精确变量名/字段名]
> - 识别变量:[Z 的精确变量名/字段名]
> - 控制变量:[协变量列表]
> - 时间范围:[起止年份]
> - 地理范围:[省/行业/国家等]
> - **合并键**:[用于与其他数据集合并的标识变量,如股票代码 stkcd + 年份 year]
>
> **③ 保存文件至 `data/raw/`**:
> ```
> [workspace]/data/raw/[your_filename].[dta|csv|xlsx]
> ```
>
> **④ 完成后告知我**,我将继续处理其余数据来源。"*
等待用户确认数据已放入 `data/raw/` 后,在 `data_log.md` 中追加记录,继续执行下一个待处理来源(若有),否则进入 Step 1.1。
---
### 分支 C:用户自备数据——直接读取
**判断条件:** 用户已持有数据文件(调查数据、行政数据、手工整理数据等),无需获取。
**执行流程:**
提示用户将数据放入指定位置:
> *"请将您的数据文件放入工作目录的 `data/raw/` 文件夹:*
> ```
> [workspace]/data/raw/[your_filename].[dta|csv|xlsx|parquet]
> ```
> *支持格式:`.dta`(Stata)、`.csv`、`.xlsx`、`.parquet`。放好后告知我文件名,我将自动读取。"*
用户确认文件已就位后:
1. 用 `Read` 或 `Bash` 读取文件,报告基本维度(N × K)和变量列表
2. 对照 `identification-memo.md` 中的变量清单,检查**关键变量是否齐全**:
```
变量到位检查
──────────────────────────────────────
✅ 结果变量 Y:[变量名] — 找到
✅ 处理变量 D:[变量名] — 找到
⚠️ 识别变量 Z:[变量名] — 未找到,需在清洗阶段从 [变量X] 构建
✅ 协变量:[列表] — 找到 [N/M] 个
──────────────────────────────────────
```
3. 在 `data_log.md` 中追加记录,继续执行下一个待处理来源(若有),否则进入 Step 1.1。
---
### 1.1:多源数据合并规划(当存在两个及以上数据来源时触发)
所有数据来源处理完毕后,在进入 Step 2 前,明确合并方案:
> *"所有数据来源已就位,共 [N] 个数据文件:*
> *- `[文件1]`:[来源类型],[N1] 行,合并键:[key1]*
> *- `[文件2]`:[来源类型],[N2] 行,合并键:[key2]*
> *...*
>
> *计划合并方案:*
> *1. 以 `[主数据文件]` 为主体(left join / inner join)*
> *2. 依次合并 `[辅助数据1]`(合并键:[key],预期匹配率:[估计])*
> *3. 依次合并 `[辅助数据2]`(合并键:[key],预期匹配率:[估计])*
>
> *请确认合并逻辑,或告知是否需要调整。"*
用户确认后进入 Step 2,在 `data-pipeline` skill 中执行实际合并操作。
---
## Step 2: 数据清洗
调用 `data-pipeline` skill。传入以下上下文,确保清洗不是通用操作而是面向具体识别策略:
- 识别策略类型(来自 Step 0)
- 结果变量、处理变量、识别变量的名称(来自 Step 0)
- 面板结构(个体变量名、时间变量名)
`data-pipeline` skill 负责执行:
**通用清洗**
- 重复观测检测与处理
- 缺失值编码(识别 -99、-88 等缺失码)与处理方式决策
- 变量类型修正与命名规范化(snake_case)
- 异常值检测(1st/99th 百分位 Winsorize,需经济学判断)
- 变量标签与值标签
**识别策略专属变量构建**(根据 Step 0 的策略类型自动触发):
| 识别策略 | 必须构建的变量 |
|--------|--------------|
| DiD | `treated`(处理组虚拟变量)、`post`(政策后虚拟变量)、`treated_post`(交互项)、`event_time`(相对处理时间) |
| RDD | `running_var_centered`(以阈值中心化的分配变量)、`above_cutoff`(阈值上方虚拟变量)、带宽内样本筛选标记 |
| IV | 工具变量 Z(若需从原始变量构建,如地理距离、历史数据匹配) |
| Panel FE | 确认 `id` 和 `time` 变量唯一标识,生成平衡性标记 |
| 合成控制 | 预处理期与后处理期分组标记,结果变量的长格式重塑 |
**面板结构验证**(若适用):
```stata
* 强/弱平衡性检查
xtset id year
xtdescribe
* 唯一标识符验证
isid id year
* 时间维度连续性检查
tab year
```
清洗完成后保存至:`data/clean/[project_name]_clean.[dta|parquet]`
生成清洗日志 `data/clean/cleaning_log.md`,记录每项转换操作、处理前后的样本量变化、关键变量的缺失率变化。
---
## Step 3: 探索性分析
调用 `results-analysis` skill,生成以下统计输出。所有表格同时存储为 `.tex`(用于论文)和 `.csv`(用于核查):
**Table 1 — 描述性统计**
全样本:N、均值、标准差、p25、中位数、p75、min、max。必须覆盖 Y、D、Z 及主要协变量。
保存至:`tables/table1_descriptive.tex` + `.csv`
**Table 2 — 处理组/控制组平衡性检验**(若存在处理变量)
处理组均值、控制组均值、差值、标准误、p 值。重点检验**预处理期协变量**的组间平衡性,不平衡的变量需在 Step 2 中重新检查。
保存至:`tables/table2_balance.tex` + `.csv`
**识别变量分布检查**(根据识别策略自动触发):
| 识别策略 | 检查内容 |
|--------|---------|
| DiD | 处理时点前后的结果变量趋势图(初步目测平行趋势) |
| RDD | 分配变量在阈值附近的分布直方图;McCrary 密度检验的初步目视 |
| IV | 工具变量与处理变量的散点图及初步相关系数 |
| Panel FE | 个体内(within)与个体间(between)方差分解 |
保存至:`figures/eda_[strategy_name].png`
**缺失值报告**
缺失率 > 5% 的变量列表,标注 MCAR / MAR / MNAR 的初步判断依据。
---
## Step 4: 产出 `data-report.md`
整合以上三个步骤,生成阶段交付文档,保存至工作目录:
```
Write: [workspace]/data-report.md
```
**文档结构:**
```markdown
# Data Report
**项目:** [研究问题一句话]
**版本:** v1.0
**日期:** [YYYY-MM-DD]
---
## 1. 数据来源与获取
- **数据集:** [名称]
- **获取方式:** [API 自动 / 商业数据库 / 用户自备]
- **获取日期:** [日期](如适用)
- **原始数据路径:** `data/raw/[文件名]`
- **已清洗数据路径:** `data/clean/[文件名]`
## 2. 样本描述
- **分析单元:** [个体/企业/县/省…]
- **时间跨度:** [起止年份]
- **原始样本量:** [N]
- **清洗后样本量:** [N](删减原因:[缺失值/异常值/样本限制])
- **面板结构:** [强/弱平衡;个体数 × 时间期数](如适用)
## 3. 关键变量状态
| 变量 | 角色 | 变量名 | 缺失率 | 均值 | 标准差 | 备注 |
|------|------|--------|--------|------|--------|------|
| [Y] | 结果变量 | ... | ...% | ... | ... | ... |
| [D] | 处理变量 | ... | ...% | ... | ... | ... |
| [Z] | 识别变量 | ... | ...% | ... | ... | ... |
## 4. 数据质量问题与处理方式
[逐条列出发现的数据问题及处理决策,说明经济学依据]
## 5. 探索性分析关键发现
[2–4条实质性发现,如:处理组与控制组在预处理期特征基本平衡;工具变量与处理变量相关系数为 0.XX;分配变量在阈值处分布无明显跳跃]
## 6. 待关注事项
[进入 Phase 5 前需注意的数据层面风险,如:某协变量平衡性较差,建议在主回归中加入;工具变量与 Y 的原始相关性偏弱,需关注一阶段 F 统计量]
```
---
## Step 5: 阶段确认与移交
向用户呈现阶段摘要:
> **Phase 4 产出摘要**
>
> ✅ 原始数据:`data/raw/[文件名]`([N] 行 × [K] 列)
> ✅ 清洗数据:`data/clean/[文件名]`([N'] 行 × [K'] 列)
> ✅ 描述性统计:`tables/table1_descriptive.tex`
> ✅ 平衡性检验:`tables/table2_balance.tex`(如适用)
> ✅ EDA 图:`figures/eda_[strategy].png`
> ✅ 数据报告:`data-report.md`
>
> ---
>
> 待您确认数据质量后,进入下一阶段 Phase 5 计量模型构建
>
---
## 常见问题处理
**Q:`identification-memo.md` 中列出的某个变量在数据中不存在怎么办?**
在 Step 1 分支 C 的变量检查环节标注 ⚠️,并提出两个选项:
1. **构建代理变量**:在 Step 2 中用现有变量合成近似指标,需说明测量误差方向
2. **降格识别层级**:返回 Phase 3,在 `identification-memo.md` 中更新策略,再重新执行 `/data`
**Q:数据量极大(>100 万行),清洗代码运行超时怎么办?**
在 Step 2 中生成分块处理代码(chunked processing),或建议用户在本地 Stata/Python 环境中运行,将清洗结果上传。Phase 5 Econometric Model Construction. Reads identification-memo.md and data-report.md, writes formal model specification with LaTeX equations, discusses identification assumptions and SE strategy, calls the appropriate estimation skill, and produces model-spec.md.
# /model — 计量模型构建
## 定位
`/model` 是实证研究工作流的**第五阶段**,承接 Phase 3(`/analyze`)的 `identification-memo.md` 和 Phase 4(`/data`)的 `data-report.md`,完成:
1. 根据识别策略**形式化写出计量模型**(含完整 LaTeX 公式)
2. 明确**识别假设的可检验形式**及其在数据中的诊断状态
3. 确定**标准误策略**(聚类层级、异方差处理方式等)
4. 调用对应的**估计技能**执行回归
5. 产出 `model-spec.md`,供 Phase 6(代码执行)和 Phase 9(论文写作)使用
---
## Step 0:读取上游输出
> 📎 **参见 [`shared/context-reader.md`](../shared/context-reader.md)**
> 本阶段所需文件:`identification-memo.md`(必需)、`data-report.md`(可选)。
读取完成后提取并整理以下关键信息:
| 来源 | 提取内容 |
|------|---------|
| `identification-memo.md` | 识别策略类型、结果变量 Y、处理变量 D、识别变量 Z、控制变量列表、面板结构(id/time)、目标参数(ATE/ATT/LATE) |
| `data-report.md` | 样本量 N、面板维度(个体数 × 时期数)、关键变量缺失率、EDA 预警(平衡性不足、弱工具变量等)、平衡性检验结果 |
提取完成后向用户确认:
> **Phase 5 启动确认**
>
> 识别策略:**[策略名称]**
> 目标参数:**[ATE / ATT / LATE / 平均处理效应...]**
> 结果变量 Y:`[变量名]`
> 处理变量 D:`[变量名]`
> 识别变量 Z / 运行变量:`[变量名(如适用)]`
> 样本:[N] 观测,[个体数] 个个体 × [时期数] 期
>
> 继续构建模型,或告知是否需要调整。
---
## Step 1:模型类型与规格讨论
在形式化写出方程前,与用户确认以下**建模决策**。每个决策点需给出推荐选项及经济学理由:
### 1.1 主方程类型
| 识别策略 | 推荐主方程类型 | 备选 |
|---------|--------------|------|
| DiD(2×2 或少期) | 双向固定效应 TWFE | 加权 DiD、有控制变量的 OLS |
| DiD(交错、多期) | Callaway–Sant'Anna / Sun–Abraham | TWFE(需诊断异质性处理效应偏误) |
| RDD(精确服从) | Sharp RDD,局部线性 | 高阶多项式(通常不推荐) |
| RDD(模糊服从) | Fuzzy RDD(2SLS at cutoff) | — |
| IV | 2SLS(线性第一阶段) | LIML(弱工具变量时稳健) |
| 面板固定效应 | TWFE(个体 + 时间) | 随机效应(需 Hausman 检验) |
| 合成控制 | 加权合成控制(Abadie 2003) | 合成 DiD(Arkhangelsky 2021) |
| 截面 OLS | OLS + 稳健 SE | — |
### 1.2 控制变量决策
参考 `identification-memo.md` 的协变量列表和 `data-report.md` 的平衡性检验结果:
- 平衡性检验标准化差异 > 0.25 的变量:**必须列为重点控制变量**
- 理论上影响 Y 但与 D 无关的变量:加入可提升精度(降低残差方差),建议加入
- 与 D 相关且位于处理路径上的中介变量:**不得控制**(会引入中介偏误)
### 1.3 固定效应层级
向用户说明各层级固定效应控制的内容:
| 固定效应 | 控制内容 | 代价 |
|---------|---------|------|
| 个体 FE($\alpha_i$) | 个体层面不随时间变化的遗漏变量 | 吸收所有个体层面截面变异 |
| 时间 FE($\lambda_t$) | 共同时间趋势(商业周期、通货膨胀等) | 吸收所有时期层面共同冲击 |
| 个体 × 时间组合 FE | 更细粒度的组别趋势 | 大幅降低自由度 |
| 省 × 年 FE | 控制省级层面年度时变混淆 | 需要足够跨省 within 变异 |
---
## Step 2:形式化模型写作(LaTeX)
根据 Step 1 确认的策略类型,**输出完整的 LaTeX 模型规格**。每个模型必须包含:
① 主方程
② 下标与符号说明
③ 关键假设的形式化表述
④ 目标参数的经济学解释
⑤ 识别条件
---
### 模型 A:双向固定效应 DiD(TWFE)
**适用**:二元处理、平行趋势假设成立、处理效应同质或近似同质。
```latex
% ── 主方程 ──────────────────────────────────────────
\begin{equation}\label{eq:twfe}
Y_{it} = \alpha_i + \lambda_t + \beta \, D_{it}
+ \mathbf{X}_{it}'\boldsymbol{\gamma} + \varepsilon_{it}
\end{equation}
% ── 符号说明 ─────────────────────────────────────────
% Y_{it} 结果变量(个体 i,时期 t)
% \alpha_i 个体固定效应(吸收不随时间变化的遗漏变量)
% \lambda_t 时间固定效应(吸收共同时间趋势)
% D_{it} 处理变量:= 1 若个体 i 在 t 期已受处理,否则 = 0
% \mathbf{X}_{it} 时变控制变量向量
% \varepsilon_{it} 误差项,假设 E[\varepsilon_{it} \mid \alpha_i, \lambda_t, D_{it}, \mathbf{X}_{it}] = 0
% ── 目标参数 ─────────────────────────────────────────
% \hat{\beta} 估计处理组的平均处理效应(ATT)
```
**平行趋势假设(Parallel Trends Assumption)的形式化表述:**
```latex
\begin{assumption}[Parallel Trends]
E[Y_{it}(0) - Y_{it'}(0) \mid D_i = 1]
= E[Y_{it}(0) - Y_{it'}(0) \mid D_i = 0],
\quad \forall\, t \neq t'
\end{assumption}
% 含义:在反事实意义上,若处理组未受处理,
% 其结果变量的时间趋势与控制组相同。
```
---
### 模型 A':事件研究(Event Study)
**适用**:检验平行趋势假设;展示处理效应的动态路径(预期效应、短期冲击、长期效应)。
```latex
% ── 事件研究方程 ─────────────────────────────────────
\begin{equation}\label{eq:eventstudy}
Y_{it} = \alpha_i + \lambda_t
+ \sum_{\substack{k = k_{\min} \\ k \neq -1}}^{k_{\max}}
\beta_k \cdot \mathbf{1}[\text{EventTime}_{it} = k]
+ \mathbf{X}_{it}'\boldsymbol{\gamma} + \varepsilon_{it}
\end{equation}
% EventTime_{it} = t - T_i^*:相对于个体 i 首次受处理时间 T_i^* 的事件时间
% k = -1(处理前一期)设为基准组,其系数归一化为零
% k_{\min} < 0 的系数:检验预趋势(应联合不显著于零)
% k \geq 0 的系数:处理效应的动态路径
%
% 平行趋势的可检验形式:
% H_0: \beta_k = 0 \text{ for all } k < 0
```
---
### 模型 B:Sharp RDD(精确断点回归)
**适用**:处理分配完全由连续型分配变量(Running Variable)是否超过阈值 $c$ 决定。
```latex
% ── Sharp RDD 主方程 ─────────────────────────────────
\begin{equation}\label{eq:rdd_sharp}
Y_i = \tau \cdot D_i + f(X_i - c) + \varepsilon_i
\end{equation}
% 其中:
% D_i = \mathbf{1}[X_i \geq c] \quad \text{(处理变量,精确服从)}
% f(\cdot) \quad \text{(分配变量的灵活函数,通常为局部线性)}
% c \quad \text{(阈值,对应 X_i - c = 0)}
%
% 局部线性规格(推荐):
\begin{equation}\label{eq:rdd_ll}
Y_i = \alpha_0 + \tau \cdot D_i
+ \beta_1 (X_i - c)
+ \beta_2 (X_i - c) \cdot D_i
+ \varepsilon_i, \quad |X_i - c| \leq h
\end{equation}
% 带宽 h 由 \texttt{rdbwselect}(MSE 最优或 CER 最优)选择
% 参数 \tau 估计阈值处的局部平均处理效应(LATE at cutoff)
% ── 连续性假设 ────────────────────────────────────────
\begin{assumption}[Continuity at Cutoff]
E[Y_i(0) \mid X_i = x] \text{ 和 } E[Y_i(1) \mid X_i = x]
\text{ 在 } x = c \text{ 处连续}
\end{assumption}
% 等价于:分配变量在阈值处的密度无跳跃(McCrary 检验)
```
---
### 模型 B':Fuzzy RDD(模糊断点回归)
**适用**:超过阈值显著提高处理概率,但非完全服从(部分个体跨越阈值但未受处理,或未跨越阈值但受处理)。
```latex
% ── 两阶段规格 ───────────────────────────────────────
% 第一阶段:
\begin{equation}\label{eq:rdd_fuzzy_fs}
D_i = \pi_0 + \pi_1 \cdot \mathbf{1}[X_i \geq c]
+ g(X_i - c) + \nu_i, \quad |X_i - c| \leq h
\end{equation}
% 第二阶段(2SLS):
\begin{equation}\label{eq:rdd_fuzzy_ss}
Y_i = \alpha + \tau_{\text{FRD}} \cdot \hat{D}_i
+ f(X_i - c) + \varepsilon_i, \quad |X_i - c| \leq h
\end{equation}
% \tau_{\text{FRD}} = \frac{\lim_{x \to c^+} E[Y_i \mid X_i=x] - \lim_{x \to c^-} E[Y_i \mid X_i=x]}
% {\lim_{x \to c^+} E[D_i \mid X_i=x] - \lim_{x \to c^-} E[D_i \mid X_i=x]}
% 估计 Compliers 的局部平均处理效应(LATE)
```
---
### 模型 C:工具变量(2SLS)
**适用**:处理变量 D 内生,存在有效工具变量 Z(相关性 + 排他性限制)。
```latex
% ── 第一阶段 ─────────────────────────────────────────
\begin{equation}\label{eq:iv_first}
D_i = \pi_0 + \pi_1 Z_i + \mathbf{X}_i'\boldsymbol{\delta} + \nu_i
\end{equation}
% ── 第二阶段 ─────────────────────────────────────────
\begin{equation}\label{eq:iv_second}
Y_i = \beta_0 + \beta_1 \hat{D}_i + \mathbf{X}_i'\boldsymbol{\gamma} + \varepsilon_i
\end{equation}
% \hat{D}_i = \hat{\pi}_0 + \hat{\pi}_1 Z_i + \mathbf{X}_i'\hat{\boldsymbol{\delta}}
% \quad \text{(第一阶段拟合值)}
%
% IV 有效性的三个条件:
% 1. 相关性(Relevance): \pi_1 \neq 0,经验检验:F_{\text{first stage}} > 10
% 2. 排他性(Exclusion): Z_i \perp \varepsilon_i \mid \mathbf{X}_i
% (Z 仅通过 D 影响 Y,不可直接检验,需理论论证)
% 3. 单调性(Monotonicity):Z_i = 1 \Rightarrow D_i(1) \geq D_i(0)
% (无"Defiers",LATE 解释的前提)
%
% \beta_1 \text{ 估计 Compliers 的 LATE(本地平均处理效应)}
% ── 简约式(Reduced Form) ────────────────────────────
\begin{equation}\label{eq:iv_rf}
Y_i = \rho_0 + \rho_1 Z_i + \mathbf{X}_i'\boldsymbol{\phi} + \eta_i
\end{equation}
% \hat{\beta}_1^{\text{IV}} = \hat{\rho}_1 / \hat{\pi}_1
% 简约式应在论文中单独汇报,供读者核实
```
---
### 模型 D:面板固定效应(Panel FE)
**适用**:处理变量在个体内存在时变,个体固定效应足以控制截面异质性,无显著内生性(或已排除)。
```latex
% ── TWFE 主方程 ──────────────────────────────────────
\begin{equation}\label{eq:pfe}
Y_{it} = \alpha_i + \lambda_t
+ \boldsymbol{\beta}' \mathbf{D}_{it}
+ \mathbf{X}_{it}'\boldsymbol{\gamma}
+ \varepsilon_{it}
\end{equation}
% \alpha_i:个体固定效应(消除个体层面遗漏变量偏误)
% \lambda_t:时间固定效应(控制共同时间趋势)
% \mathbf{D}_{it}:关键解释变量向量(可为多个政策变量)
% \mathbf{X}_{it}:时变控制变量
%
% 外生性假设(严格外生性):
\begin{assumption}[Strict Exogeneity]
E[\varepsilon_{it} \mid \mathbf{D}_{i1}, \ldots, \mathbf{D}_{iT},
\mathbf{X}_{i1}, \ldots, \mathbf{X}_{iT}, \alpha_i] = 0
\end{assumption}
% 若严格外生性不满足(如 D 受滞后 Y 影响),需考虑 Arellano-Bond GMM
% ── Hausman 检验(FE vs RE) ──────────────────────────
% H_0: \text{随机效应模型一致}(\alpha_i \perp \mathbf{D}_{it})
% H_1: \text{固定效应模型必要}(\alpha_i \text{ 与 } \mathbf{D}_{it} 相关)
% 若拒绝 H_0,使用 FE;否则 RE 更有效率
```
---
### 模型 E:合成控制(Synthetic Control)
**适用**:单一处理单元(或少数处理单元)、较长预处理期、处理组与任何单一控制单元匹配不理想。
```latex
% ── 合成控制估计量 ────────────────────────────────────
% 构造控制组合权重 w_j^* 使得合成控制单元与处理单元在预处理期最相似:
\begin{equation}\label{eq:synth_weights}
(w_2^*, \ldots, w_{J+1}^*) = \arg\min_{\mathbf{w}}
\left\| \mathbf{X}_1 - \mathbf{X}_0 \mathbf{w} \right\|_V
\end{equation}
% \mathbf{X}_1:处理单元的预处理期结果和预测变量向量
% \mathbf{X}_0:控制池中各供体单元的对应向量
% \mathbf{V}:对预测变量的重要性加权矩阵(由外层优化确定)
% 约束:w_j \geq 0,\sum_j w_j = 1
% ── 处理效应估计 ──────────────────────────────────────
\begin{equation}\label{eq:synth_effect}
\hat{\alpha}_{1t} = Y_{1t} - \hat{Y}_{1t}^N
= Y_{1t} - \sum_{j=2}^{J+1} w_j^* Y_{jt},
\quad t > T_0
\end{equation}
% Y_{1t} 处理单元在 t 期的实际结果
% \hat{Y}_{1t}^N 合成控制(反事实)结果
% \hat{\alpha}_{1t} t 期的处理效应估计(可展示随时间变化的动态路径)
% ── 推断(排列检验) ─────────────────────────────────
% 对控制池中每个供体单元重复合成控制过程("安慰剂"),
% p 值 = 处理单元的 MSPE 比 ≥ 该比值的供体单元比例
```
---
## Step 3:标准误策略
根据数据结构和识别策略,明确推荐标准误类型,并给出理由:
| 数据结构 | 推荐 SE 类型 | 关键考量 |
|---------|------------|---------|
| 纯截面,同质方差 | OLS SE | 需通过 Breusch-Pagan 检验 |
| 纯截面,异方差 | HC3 稳健 SE | 几乎始终优于 OLS SE |
| 面板,DiD/TWFE | 双向聚类 SE(个体 + 时间) | 控制个体内序列相关和时间截面相关 |
| 面板,处理变量在组内不变 | 按处理分配单元聚类 | 如政策以省为单位,则按省聚类 |
| RDD,带宽内样本 | 稳健 bias-corrected SE(rdrobust) | 标准 SE 低估 bias;Calonico 等 2014 |
| IV / 2SLS | 与主回归一致的聚类 SE | 两阶段需保持聚类层级一致 |
| 少量聚类(< 30) | Wild Bootstrap(cgmwildboot / boottest) | 聚类数不足时 t 近似失效 |
```latex
% 在论文中标准误说明的规范写法(放在表格 Notes 中):
% "Standard errors clustered at the [province / firm / county] level
% are reported in parentheses. *, **, *** denote significance
% at the 10\%, 5\%, and 1\% levels, respectively."
```
---
## Step 3.5:诊断规格(Diagnostic Plan)
在进入代码执行之前,必须在模型规格阶段明确**要检验什么、为什么要检验、通过标准是什么、失败如何处理**。这些决策属于建模决策,不是执行细节。
诊断规格写入 `model-spec.md §6`,供 Phase 6(`/code`)直接读取执行,无需在代码阶段重新判断。
### 第一层:识别假设诊断规格
根据 Step 1 确认的策略,从以下表格中选取对应行,填入通过 / 失败时的具体数值标准:
| 策略 | 识别假设 | 诊断检验 | 通过标准 | 失败时处理 |
|------|---------|---------|---------|----------|
| DiD / TWFE | 平行趋势 | 事件研究图 + 预趋势系数联合 F 检验 | 联合检验 p > 0.1 | 返回 Phase 3,更换对照组或时间窗口 |
| 交错 DiD | 处理效应同质性 | Bacon 分解;C-S vs TWFE 系数对比 | TWFE / C-S 主系数差 < 20% | 改用 Callaway-Sant'Anna 估计量 |
| Sharp RDD | 分配变量连续性 | McCrary 密度检验(`rddensity`) | p > 0.1 | 返回 Phase 3,质疑 RDD 设计有效性 |
| Sharp / Fuzzy RDD | 预定变量平衡 | 对协变量做 RDD | 所有协变量 p > 0.05 | 加入协变量控制;检查数据清洗步骤 |
| Fuzzy RDD | 工具变量相关性 | 第一阶段 F;Anderson-Rubin CI | F > 10;AR CI 含 0 则无效 | 质疑 RDD 断点是否有效处理力度 |
| IV / 2SLS | 工具变量相关性 | 第一阶段 F(Stock-Yogo 临界值 16.38) | F > 10 | 寻找更强工具变量或改用 LIML |
| IV / 2SLS | 过识别约束(多 IV)| Sargan / Hansen J 检验 | p > 0.05 | 讨论哪个工具变量可能违反排他性 |
| 面板 FE | FE vs RE 选择 | Hausman 检验 | p < 0.05 → 选 FE | 若 p > 0.05,报告两种估计量并讨论 |
| 面板 FE | 严格外生性 | Wooldridge 序列相关检验 | p > 0.05 | 加滞后因变量;考虑 AB-GMM |
| 合成控制 | 预处理期拟合 | 预处理期 RMSPE 相对于供体分布 | 处理单位 RMSPE < 供体中位数 × 2 | 调整供体池;重新选择预测变量权重 |
### 第二层:统计假设诊断规格
以下检验对所有策略通用,无论识别策略如何均须执行。**注意:失败不等于终止流程——取决于失败项与 SE 策略的配合情况。**
| 检验 | 检验内容 | 通过标准 | 失败时处理 | 是否终止流程 |
|------|---------|---------|----------|------------|
| VIF(最大值)| 多重共线性 | VIF < 10 | 删除或合并共线变量,更新 §5 控制变量列表 | ⚠️ 视情况 |
| Breusch-Pagan | 异方差 | p > 0.05 | 已指定稳健/聚类 SE → 标记 WARN,继续 | 否(若已用稳健 SE)|
| Breusch-Godfrey | 序列相关(截面)| p > 0.05 | 加滞后因变量或使用 Newey-West SE | ⚠️ 视情况 |
| Wooldridge | 序列相关(面板)| p > 0.05 | 双向聚类 SE 或 AR(1) 误差 | 否(若已双向聚类)|
| RESET | 函数形式误设 | p > 0.05 | 尝试对数变换或加二次项;写入稳健性清单 | 否 |
| Cook's D(最大)| 强影响观测值 | < 4/N | 列出高影响观测值;纳入 Phase 8 稳健性 | 否 |
**关键原则:**
- **识别假设失败(第一层)→ 立即终止,返回对应阶段**:识别失败意味着因果解释无效,后续结果无意义
- **统计假设警告(第二层)→ 记录于 `model-spec.md §6`,继续**:统计问题通常可通过 SE 策略或稳健性检验应对
---
## Step 4:调用估计技能
根据 Step 1 确认的策略类型,调用对应的专属估计 skill:
| 策略 | 调用的 skill | 传入上下文 |
|------|------------|----------|
| DiD / TWFE / Event Study | `did-analysis` | 主方程规格、FE 层级、SE 聚类层级、事件窗口 |
| Sharp / Fuzzy RDD | `rdd-analysis` | 运行变量名、阈值值、带宽选择方法、局部多项式阶次 |
| 2SLS / IV | `iv-estimation` | 工具变量名、第一/第二阶段规格、SE 策略 |
| Panel FE | `panel-data` | FE 层级、Hausman 检验、SE 策略 |
| 合成控制 | `synthetic-control` | 供体池列表、预处理期、预测变量权重矩阵 |
| OLS + FE | `ols-regression` | 主方程规格、控制变量、SE 类型 |
调用格式:
> *"现在调用 `[skill 名称]`,执行 [识别策略名称] 估计。传入以下参数:*
> *主方程:[LaTeX 公式中文概述]*
> *标准误:[聚类层级]*
> *数据路径:`data/clean/[project_name]_clean.[dta|parquet]`"*
---
## Step 5:产出 `model-spec.md`
估计 skill 完成后,将本阶段所有决策整合为阶段交付文档:
```
Write: [workspace]/model-spec.md
```
**文档结构:**
```markdown
# Model Specification
**项目:** [研究问题一句话]
**版本:** v1.0
**日期:** [YYYY-MM-DD]
---
## 1. 识别策略
- **策略类型:** [DiD / RDD / IV / Panel FE / Synthetic Control]
- **目标参数:** [ATE / ATT / LATE,含经济学含义]
- **识别变量:** [Z / 运行变量 / 政策时点]
## 2. 主方程
[LaTeX 方程,直接可粘贴至论文]
$$
[主方程 LaTeX]
$$
**参数说明:**
| 符号 | 含义 |
|------|------|
| $Y_{it}$ | [结果变量描述] |
| $\beta$ | [处理效应的经济学解释,含量级] |
| ... | ... |
## 3. 识别假设
| 假设 | 形式化表述 | 诊断状态 |
|------|-----------|---------|
| [假设名] | $[LaTeX]$ | ✅ 通过 / ⚠️ 存疑 / ❌ 不满足 |
诊断状态来源于 `data-report.md` 的 EDA 结果(平行趋势图、McCrary 检验等)。
## 4. 标准误策略
- **类型:** [聚类 SE / 稳健 SE / Wild Bootstrap]
- **聚类层级:** [省 / 企业 / 县]
- **理由:** [经济学依据]
## 5. 控制变量
[变量列表及加入理由;注明哪些变量因平衡性不足被强制加入]
## 6. 诊断计划(Diagnostic Plan)
> 本节由 `/model` Step 3.5 生成,供 `/code` Phase 6 直接读取执行。不得在代码阶段修改诊断逻辑。
### 6.1 第一层:识别假设诊断
| 假设 | 检验方法 | 通过标准 | 失败时处理 |
|------|---------|---------|----------|
| [填入该策略对应的识别假设] | [检验名称] | [具体数值标准] | [返回阶段 + 修正方向] |
### 6.2 第二层:统计假设诊断
| 检验 | 通过标准 | 失败时处理 | 是否终止 |
|------|---------|----------|--------|
| VIF(最大值)| < 10 | [处理方式] | ⚠️ |
| Breusch-Pagan | p > 0.05 | 已用 [SE类型] → WARN,继续 | 否 |
| Breusch-Godfrey / Wooldridge | p > 0.05 | [处理方式] | ⚠️ |
| RESET | p > 0.05 | [处理方式] | 否 |
| Cook's D | < 4/N | 纳入 Phase 8 稳健性 | 否 |
### 6.3 诊断输出
`/code` 执行后生成 `diagnostic_report.md`,汇总两层诊断结果(✅ / ⚠️ / ❌)。
⚠️ 项自动纳入 Phase 8 `/robustness` 检验清单;❌ 项触发流程终止并返回对应阶段。
## 7. 数据质量预警与应对
[来自 data-report.md 的预警事项,及在模型设计中的应对方式]
## 8. 待执行的稳健性检验
[进入 Phase 8 前预先列出的稳健性检验清单,如:
- 替换控制变量集合
- 更换带宽(RDD)
- 安慰剂检验
- 剔除特殊样本]
```
---
## Step 6:阶段确认与移交
向用户呈现阶段摘要:
> **Phase 5 产出摘要**
>
> ✅ 主方程(LaTeX):`model-spec.md` §2
> ✅ 识别假设形式化:`model-spec.md` §3
> ✅ 标准误策略:`model-spec.md` §4
> ✅ 估计代码:由 `[skill 名称]` 生成,见 `code/`
> ✅ 模型规格文档:`model-spec.md`
>
> ---
>
> 待您确认模型规格后,进入 Phase 6(代码执行与复现)Publication Polish. Runs after results-analysis (Phase 7). Audits all tables and figures produced in Phases 4–7, upgrades them to top-journal standards by calling the table and figure skills.
# /plot — 表格和图表可视化
## 定位
`/plot` 是 Phase 7(`results-analysis`)与 Phase 9(`/write`)之间的**图表可视化阶段**。将 Phase 4–7 产出的所有功能性表格和图形,统一升级为符合 Top5 顶刊排版标准的最终版本,并检查是否有识别策略要求的标准图形尚未生成。
完成后产出**输出清单 `output-manifest.md`**,供 `/write`(Phase 9)直接引用,不再需要手动查找文件路径。
---
## Step 0:读取上下文
```
Read: [workspace]/results-memo.md # Phase 7 产出:识别策略、主要结果、建议图表
Read: [workspace]/model-spec.md # 识别策略类型(决定标准图形集合)
Read: [workspace]/data-report.md # 变量名、样本定义
```
同时扫描已有的输出目录:
```python
import os
from pathlib import Path
tables = sorted(Path("tables").glob("*"))
figures = sorted(Path("figures").glob("*"))
print("=== 现有表格 ===")
for f in tables: print(f" {f.name}")
print("\n=== 现有图形 ===")
for f in figures: print(f" {f.name}")
```
根据识别策略,对照**标准输出清单**(见 Step 1)检查缺漏,输出审计报告:
```
=== 输出审计 ===
策略:[识别策略]
表格
✅ table1_descriptive.tex — 已有,待精修
✅ table2_balance.tex — 已有,待精修
✅ table_main.tex — 已有,待精修
❌ table_event_study.tex — 缺失,需生成
图形
✅ eda_did_trend.png — 已有,待升级为 PDF
❌ figure_event_study.pdf — 缺失,需生成(DiD 标准图)
✅ coef_main.png — 已有,待升级
```
---
## Step 1:按识别策略确定标准输出集合
> 📎 **输出格式规范参见 [`shared/output-standards.md`](../shared/output-standards.md)**
不同识别策略有约定俗成的"必备图表",缺少会影响审稿通过率:
### 标准表格集合(所有策略共用)
| 编号 | 文件名 | 内容 | 来源阶段 |
|------|--------|------|---------|
| Table 1 | `table1_descriptive.tex` | 描述性统计 | Phase 4 `results-analysis` |
| Table 2 | `table2_balance.tex` | 平衡性检验(若有处理变量)| Phase 4 `results-analysis` |
| Table 3 | `table_main.tex` | 主回归结果(多列规格)| Phase 6 `/code` |
| Table A1 | `table_robustness.tex` | 稳健性检验汇总 | Phase 8 `/robustness`(待生成)|
### 标准图形集合(按识别策略)
#### DiD / TWFE
| 编号 | 文件名 | 内容 | 优先级 |
|------|--------|------|--------|
| Figure 1 | `figure_event_study.pdf` | 事件研究系数图(动态处理效应)| **必须** |
| Figure 2 | `figure_parallel_trends.pdf` | 处理组 vs 控制组时间趋势 | **必须** |
| Figure A1 | `figure_bacon_decomp.pdf` | Bacon 分解(交错 DiD)| 若为交错设计 |
#### RDD
| 编号 | 文件名 | 内容 | 优先级 |
|------|--------|------|--------|
| Figure 1 | `figure_rdd_main.pdf` | RDD 主图:散点 + 两侧拟合线 + 跳跃 | **必须** |
| Figure 2 | `figure_mccrary.pdf` | McCrary 密度检验图 | **必须** |
| Figure A1 | `figure_rdd_bandwidth.pdf` | 带宽敏感性图 | 推荐 |
#### IV / 2SLS
| 编号 | 文件名 | 内容 | 优先级 |
|------|--------|------|--------|
| Figure 1 | `figure_iv_first_stage.pdf` | 第一阶段:Z vs D 散点 + 拟合线 | **必须** |
| Figure 2 | `figure_iv_reduced_form.pdf` | 简约式:Z vs Y 散点 + 拟合线 | **必须** |
#### Panel FE
| 编号 | 文件名 | 内容 | 优先级 |
|------|--------|------|--------|
| Figure 1 | `figure_coef_main.pdf` | 主系数图(多规格并列)| **必须** |
| Figure 2 | `figure_fe_variance.pdf` | Within/Between 方差分解 | 推荐 |
#### 合成控制
| 编号 | 文件名 | 内容 | 优先级 |
|------|--------|------|--------|
| Figure 1 | `figure_sc_gap.pdf` | Gap 图:处理单元 vs 合成控制 | **必须** |
| Figure 2 | `figure_sc_placebo.pdf` | In-space 安慰剂检验图 | **必须** |
| Figure 3 | `figure_sc_weights.pdf` | 供体权重条形图 | 推荐 |
---
## Step 2:表格精修(调用 `table` skill)
对 Step 0 审计中标注"✅ 待精修"的所有 `.tex` 表格,调用 `table` skill 执行以下标准化操作:
**调用格式:**
> *"调用 `table` skill,精修 `[文件名]`。要求:*
> - *格式标准:booktabs(`\toprule` / `\midrule` / `\bottomrule`),无竖线*
> - *多列对齐:系数列居中,标准误括号行与系数行紧邻*
> - *显著性标注:\*, \*\*, \*\*\*(10%/5%/1%),置于系数右上角*
> - *Notes 行:说明标准误类型、聚类层级、样本限制*
> - *宽度:`\textwidth` 自适应或指定 `tabular` 列格式*
> - *输出:覆盖原文件,同时保存 `_final` 后缀版本备份"*
---
## Step 3:图形精修与生成(调用 `figure` skill)
对审计中"✅ 待升级"的图形执行精修,对"❌ 缺失"的标准图形从头生成。
**调用格式:**
> *"调用 `figure` skill,[精修/生成] `[图形名称]`。要求:*
> - *期刊标准:AER/QJE 风格(无顶框/右框,浅灰网格)*
> - *尺寸:单栏 3.5 in × 2.8 in / 双栏 7 in × 4 in*
> - *字体大小:轴标签 10pt,标题 11pt,图注 9pt*
> - *颜色:灰度优先,彩色图须灰度可读(无红绿对)*
> - *置信区间:阴影带(`fill_between`)或误差棒,透明度 0.2*
> - *输出格式:PDF(矢量,投稿用)+ PNG 300 DPI(草稿用)*
> - *文件名:`figures/[figure_name].pdf` + `.png`"*
各策略核心图形的具体实现代码(DiD 事件研究图、RDD 主图、合成控制 Gap 图、多规格系数图)统一维护在 **`skills/figure/SKILL.md`**。调用 `figure` skill 时传入图形名称和识别策略,由该 skill 负责选择对应模板并执行。
---
## Step 4:产出 `output-manifest.md`
精修完成后,生成完整的输出清单,供 `/write` 直接引用:
```
Write: [workspace]/output-manifest.md
```
**文档结构:**
```markdown
# Output Manifest
**项目:** [研究问题一句话]
**生成日期:** [YYYY-MM-DD]
**精修标准:** AER / QJE / JPE
---
## 表格
| 论文编号 | 文件路径 | 内容 | LaTeX 标签 | 状态 |
|---------|---------|------|-----------|------|
| Table 1 | `tables/table1_descriptive.tex` | 描述性统计 | `\ref{tab:descriptive}` | ✅ 精修完成 |
| Table 2 | `tables/table2_balance.tex` | 平衡性检验 | `\ref{tab:balance}` | ✅ 精修完成 |
| Table 3 | `tables/table_main.tex` | 主回归结果 | `\ref{tab:main}` | ✅ 精修完成 |
| Table A1 | `tables/table_robustness.tex` | 稳健性检验 | `\ref{tab:robustness}` | ⏳ Phase 8 后生成 |
## 图形
| 论文编号 | 文件路径(PDF) | 内容 | LaTeX 标签 | 状态 |
|---------|--------------|------|-----------|------|
| Figure 1 | `figures/figure_event_study.pdf` | 事件研究图 | `\ref{fig:eventstudy}` | ✅ 精修完成 |
| Figure 2 | `figures/figure_parallel_trends.pdf` | 平行趋势图 | `\ref{fig:trends}` | ✅ 精修完成 |
| Figure A1 | `figures/figure_bacon_decomp.pdf` | Bacon 分解 | `\ref{fig:bacon}` | ⏳ Phase 8 后生成 |
## /write 引用说明
在论文中插入表格:
```latex
\input{tables/table_main.tex}
```
在论文中插入图形:
```latex
\begin{figure}[htbp]
\centering
\includegraphics[width=\textwidth]{figures/figure_event_study.pdf}
\caption{Dynamic Treatment Effects}
\label{fig:eventstudy}
\end{figure}
```
```
---
## Step 5:阶段确认与移交
向用户呈现精修摘要:
> **Phase 7 产出摘要**
>
> ✅ 精修表格:[N] 个(`.tex`,booktabs 规范)
> ✅ 精修图形:[N] 个(`.pdf` 矢量 + `.png` 300 DPI)
> ⏳ 待 Phase 8 补充:稳健性检验表格、异质性图形
> ✅ 输出清单:`output-manifest.md`(含 LaTeX 引用代码)
>
> ---
>
> **下一步选择:**
> - 进入 **Phase 8**(`/robustness`)—— 稳健性、异质性与机制检验
> - 或直接进入 **Phase 9**(`/write`)—— 若稳健性检验已在 `/code` 阶段完成
---
## 常见问题处理
**Q:图形中文字用中文还是英文?**
论文图形一律用**英文**(变量名、轴标签、图注),以备直接投稿。描述性文字和分析讨论用中文或英文均可,但图形本身须为英文。
**Q:PDF 与 PNG 都需要吗?**
投稿期刊用 **PDF**(矢量,无限缩放),Word 稿件或 Overleaf 草稿用 **PNG**(300 DPI 足够屏幕和打印)。两者同步生成,按需取用。
**Q:表格宽度超出单栏怎么办?**
若变量多、列数多,调用 `table` skill 使用 `\resizebox{\textwidth}{!}{...}` 或 `landscape` 环境;或将控制变量行改为"Yes/No"标记,折叠系数展示。
**Q:Phase 8 的稳健性图表如何纳入?**
`output-manifest.md` 中已为 Phase 8 输出预留 ⏳ 占位符。`/robustness` 完成后,再次调用 `/plot` 将新图表加入精修流程,并更新 `output-manifest.md`。Phase 10 (optional) Beamer-Style PPTX Generation. Reads all upstream outputs and paper/sections/, maps research content to a presentation-type-specific slide outline, calls beamer-ppt skill to generate a Beamer-style .pptx file (navy-blue Metropolis theme, publication-quality), and produces slides/ directory.
# /present — 学术报告幻灯片生成
## 定位
`/present` 是实证研究工作流的**可选阶段**,通常在 Phase 9(`/write`)完成后运行,也可在初稿完成前并行进行。核心职责:
1. 读取所有上游输出,提取幻灯片所需的关键内容
2. 根据演示类型(会议报告 / 学术讲座 / 求职报告)确定幻灯片数量和深度
3. 调用 `beamer-ppt` skill,用 python-pptx 生成 **Beamer 学术风格的 `.pptx` 文件**(海军蓝配色、16:9 宽屏、标题栏+进度条)
4. 验证幻灯片结构并输出文件
---
## Step 0:读取上游输出
### 0.1 读取文件
```
Read: [workspace]/research-question.md
Read: [workspace]/results-memo.md
Read: [workspace]/robustness-report.md
Read: [workspace]/model-spec.md
Read: [workspace]/data-report.md
```
若 `paper/sections/` 目录存在,同时读取:
```
Read: [workspace]/paper/sections/introduction.tex # 提取贡献定位
Read: [workspace]/paper/sections/results.tex # 提取主要发现措辞
```
**若 `results-memo.md` 不存在**,立即停止:
> *"未找到 `results-memo.md`。幻灯片的核心内容(主系数、量级解读、识别可信度)来自 Phase 7 产出。请先完成 Phase 7(`results-analysis` skill),再运行 `/present`。"*
### 0.2 提取幻灯片关键信息
从各文件中提取以下内容,作为幻灯片**内容素材库**:
| 来源 | 提取内容 | 用于哪页幻灯片 |
|------|---------|--------------|
| `research-question.md` | 研究问题一句话、政策背景数字 | Motivation、This Paper |
| `model-spec.md §1–2` | 识别策略名称、主方程(简化版)| Identification Strategy |
| `model-spec.md §3` | 识别假设(可检验形式)| Identification Strategy |
| `data-report.md §2` | 样本量 N、时间跨度、数据来源 | Data slide |
| `results-memo.md §1` | 主系数 β̂、SE、p 值 | Main Results |
| `results-memo.md §2` | 经济显著性(量级换算)| Main Results(Takeaway) |
| `results-memo.md §4` | 识别可信度 + 因果语言建议 | 全程语言控制 |
| `robustness-report.md §1` | 稳健性一句话结论 | Robustness slide |
| `robustness-report.md §2` | 关键异质性发现 | Heterogeneity slide |
| `robustness-report.md §3` | 机制证据 | Mechanism slide(若有)|
---
## Step 1:演示参数确认
### 1.1 演示类型
向用户确认:
> *"请选择演示类型(决定幻灯片数量和深度):*
>
> **A. 15–20 分钟 会议报告**(≤ 15 张幻灯片)
> — NBER/AEA 分会场报告;时间有限,直奔主题
>
> **B. 45–60 分钟 学术讲座/研讨班**(≤ 30 张幻灯片)
> — 院系 seminar;受众深度参与,需完整展示方法细节
>
> **C. 求职报告(Job Market Talk)**(≤ 20 张幻灯片)
> — 求职季使用;精炼呈现贡献、方法和主要结果"*
### 1.2 受众确认
> *"目标受众的领域背景:*
> *A. 同领域经济学家(可用技术语言和方程)*
> *B. 跨领域经济学家(需简化技术细节,强调直觉)*
> *C. 政策制定者 / 非经济学家(需要去专业化,强调政策含义)"*
### 1.3 主题风格
> *"幻灯片主题(或接受推荐):*
> *A. Metropolis(推荐)— 简洁现代,当前学术界最流行*
> *B. 极简自定义(海军蓝 + 白色)— 稳重,适合求职和顶刊作者*
> *C. Madrid — 传统学术风格,适合保守场合*"*
---
## Step 2:幻灯片大纲设计
根据 Step 1 确认的演示类型,生成**幻灯片大纲**并向用户确认后再生成 LaTeX。
### 标准大纲(各类型幻灯片数量对照)
| 幻灯片板块 | A(15 min,≤15)| B(45 min,≤30)| C(求职,≤20)|
|----------|----------------|----------------|--------------|
| 标题页 | 1 | 1 | 1 |
| Motivation | 1–2 | 2–3 | 2–3 |
| This Paper(贡献预告)| 1 | 1 | 1 |
| Related Literature | — | 1–2 | 1–2 |
| Data | 1 | 2 | 2 |
| Identification Strategy | 2 | 3–4 | 3 |
| Main Results | 3 | 5–7 | 4–5 |
| Robustness | 1 | 2–3 | 2 |
| Heterogeneity & Mechanism | — | 2–3 | 1–2 |
| Conclusion / Takeaways | 1 | 1 | 1 |
| **合计上限** | **≤ 15** | **≤ 30** | **≤ 20** |
向用户呈现大纲并确认:
```
═══════════════════════════════════════════════════
演示大纲([类型],共 [N] 张,上限 [L] 张)
═══════════════════════════════════════════════════
[1] Title
[2] Motivation: [研究问题背景]
[3] This Paper: [一句话问题 + 一句话发现]
[4] Data & Sample
[5] Identification Strategy
[6] Validity Check: [策略对应的诊断图/检验]
[7] Main Results(表格)
[8] Main Results(图形/事件研究)
[9] Economic Magnitude
[10] Robustness
[11] Takeaways
═══════════════════════════════════════════════════
```
待用户确认或修改大纲后,进入 Step 3 确认各页内容规范,再到 Step 4 生成 PPTX 文件。
---
## Step 3:各类幻灯片内容规范
> 📎 **输出格式规范参见 [`shared/output-standards.md`](../shared/output-standards.md)**
以下规范是经济学学术报告的约定俗成,逐条实施于每张幻灯片的内容生成。
---
### 3.1 标题页(Title Slide)
```latex
\begin{frame}[plain]
\titlepage
\end{frame}
```
标题格式要求:
- 论文标题:冒号后接副标题,副标题描述识别策略或数据
- 好标题:"The Effect of [X] on [Y]: Evidence from [Natural Experiment]"
- 差标题:"An Empirical Study of X and Y"(过于笼统)
- 作者行:姓名、机构(单位两行以内)
- 日期行:会议/研讨班名称 + 年月
---
### 3.2 Motivation(动机幻灯片,1–2 张)
**第 1 张:为什么关心这个问题**
每个条目不超过一行,用数字锚定重要性:
```latex
\begin{frame}{Why Does [TOPIC] Matter?}
\begin{itemize}
\item<1-> \textbf{[政策/社会重要性]:} [一句话 + 具体数字]
\item<2-> \textbf{[经济学理论相关性]:} [一句话]
\item<3-> \textbf{[识别缺口]:} Existing work relies on [OLS/cross-section]
— likely [overstates/understates] true effect
\end{itemize}
\vspace{1em}
\only<4>{
\begin{alertblock}{This paper's question}
Does [D] causally affect [Y]?
\end{alertblock}
}
\end{frame}
```
**禁忌**:
- ❌ 超过 5 个条目
- ❌ 只有文字没有数字("很多研究关注这个问题")
- ❌ 第一张就放方程
---
### 3.3 This Paper(核心预告幻灯片,1 张,必须)
**这是经济学幻灯片中最重要的一张**,通常是第 2–3 张,让听众在 5 分钟内知道这场报告值不值得继续听。
必须包含:
1. 研究问题(一句话)
2. 识别策略(一句话,直觉层面)
3. 主要发现(一句话,含量级数字)
4. 贡献定位(1–2 条,简洁)
```latex
\begin{frame}{This Paper}
\textbf{Question:} Does [D] causally affect [Y]?
\vspace{0.8em}
\textbf{What we do:} Exploit [NATURAL EXPERIMENT / INSTRUMENT / CUTOFF]
to isolate exogenous variation in [D].
\quad $\Rightarrow$ [DATA SOURCE], [N] [UNITS], [YEARS]
\vspace{0.8em}
\textbf{Main finding:} [D] [increases/decreases] [Y] by
\alert{[MAGNITUDE] [UNITS/\%]},
[significant at X\% level].
\vspace{0.8em}
\textbf{Contribution:}
\begin{enumerate}
\item First causal evidence on [TOPIC] using [METHOD]
\item [SECOND CONTRIBUTION, if any — be brief]
\end{enumerate}
\end{frame}
```
---
### 3.4 Data(数据幻灯片,1–2 张)
**第 1 张:数据来源与样本(来自 `data-report.md §2`)**
```latex
\begin{frame}{Data}
\begin{columns}
\begin{column}{0.5\textwidth}
\textbf{Data Sources:}
\begin{itemize}
\item [数据集1]:[描述,年份]
\item [数据集2]:[描述,链接方式]
\end{itemize}
\vspace{0.5em}
\textbf{Sample:}
\begin{itemize}
\item Unit: [个体/企业/县/省]
\item Period: [起止年份]
\item N = [样本量,加逗号分隔]
\end{itemize}
\end{column}
\begin{column}{0.5\textwidth}
\begin{table}
\caption{Summary Statistics}
\tiny
\begin{tabular}{lcc}
\toprule
Variable & Mean & SD \\
\midrule
[Y var] & [值] & [值] \\
[D var] & [值] & [值] \\
[Control 1] & [值] & [值] \\
\bottomrule
\end{tabular}
\end{table}
\end{column}
\end{columns}
\end{frame}
```
---
### 3.5 Identification Strategy(识别策略,2–3 张)
**第 1 张:直觉层面的识别逻辑(非技术)**
先给直觉,再给方程——不要一上来就放方程:
```latex
\begin{frame}{Identification Challenge}
\textbf{Problem:} [D] is endogenous because...
\begin{itemize}
\item \textbf{OVB:} [一句话描述混淆路径]
\item \textbf{Reverse causality:} [若适用]
\end{itemize}
\vspace{0.8em}
\textbf{Our solution:} Exploit [外生变异来源]
\begin{center}
\begin{tikzpicture}[node distance=2cm, auto]
% 简洁 DAG:D → Y,Z → D,Z ⊥ Y|D
\node (Z) {$Z$};
\node (D) [right of=Z] {$D$};
\node (Y) [right of=D] {$Y$};
\node (U) [above of=D] {$U$ (unobserved)};
\draw[->] (Z) -- (D) node[midway,below]{\tiny First stage};
\draw[->] (D) -- (Y);
\draw[->, dashed] (U) -- (D);
\draw[->, dashed] (U) -- (Y);
\draw[->, red, thick] (Z) to[bend left=40]
node[above]{\tiny \textcolor{red}{Excluded}} (Y);
\end{tikzpicture}
\end{center}
\end{frame}
```
**第 2 张:识别假设 + 主方程**
```latex
\begin{frame}{Empirical Specification}
\textbf{Key assumption:} [识别假设一句话直觉表述]
\vspace{0.5em}
\begin{block}{Main Equation}
\begin{equation*}
[主方程 LaTeX — 来自 model-spec.md §2,简化版]
\end{equation*}
\end{block}
\vspace{0.5em}
\begin{itemize}
\item $[β]$: [系数的经济学含义]
\item SE clustered at [聚类层级]
\item [FE 说明]
\end{itemize}
\vspace{0.5em}
\textbf{Evidence for assumption:} $\Rightarrow$ [下一张幻灯片]
\end{frame}
```
**第 3 张:识别假设检验(策略特异性)**
| 识别策略 | 专属视觉化幻灯片 | 图形文件 |
|---------|---------------|---------|
| DiD / 交错 DiD | 事件研究图(Event Study Plot)| `figures/fig*_event_study.pdf` |
| RDD | 断点处散点图(Binscatter at Cutoff)| `figures/fig*_rdd_binscatter.pdf` |
| IV / 2SLS | 第一阶段散点图(First Stage Scatter)| `figures/fig*_iv_scatter.pdf` |
| 面板 FE | 平行趋势目视图 | `figures/fig*_parallel_trends.pdf` |
| 合成控制 | 预处理期拟合图 | `figures/fig*_sc_gap.pdf` |
```latex
% DiD 事件研究图幻灯片示例
\begin{frame}{Parallel Trends: Event Study}
\begin{center}
\includegraphics[width=0.85\textwidth]{figures/fig01_event_study.pdf}
\end{center}
\vspace{-0.5em}
{\small \textit{Notes:} Coefficients from Eq.~(\ref{eq:eventstudy}).
95\% CI. Pre-period joint F-test: $p = [值]$ (cannot reject $H_0$: all pre-period coefficients $= 0$).}
\end{frame}
```
---
### 3.6 Main Results(主要结果,2–3 张)
**原则:用图而不是表,如果必须用表则精简到极致。**
**第 1 张:主结果表(精简版)**
幻灯片中的回归表**必须精简**,规则:
- 最多 3–4 列(不要把完整的 6 列表格搬上来)
- 只保留主系数行 + SE + N + FE 指示器
- 用 `\alert{}` 或加粗突出首选规格的主系数
- 字号:`\footnotesize` 或 `\scriptsize`
```latex
\begin{frame}{Main Results}
\begin{table}
\centering
\footnotesize
\begin{tabular}{lccc}
\toprule
& (1) & (2) & \textbf{(3)} \\
& Baseline & + Controls & \textbf{Preferred} \\
\midrule
[D var] & [β̂_1]*** & [β̂_2]*** & \alert{[β̂_3]***} \\
& ([SE_1]) & ([SE_2]) & \alert{([SE_3])} \\
\midrule
FE & No & No & Yes \\
$N$ & [N1] & [N2] & [N3] \\
\bottomrule
\multicolumn{4}{l}{\tiny SE clustered at [level]. *p<0.1 **p<0.05 ***p<0.01}
\end{tabular}
\end{table}
\vspace{0.3em}
\textbf{Takeaway:} [D] [increases/decreases] [Y] by
\alert{[COEFFICIENT] [UNITS]}.
\end{frame}
```
**第 2 张:经济量级(Economic Magnitude)**
单独一张幻灯片专门讲量级——这是听众最想要的信息:
```latex
\begin{frame}{Economic Magnitude}
\begin{center}
\Large
\textbf{[D] [increases/decreases] [Y] by \alert{[MAGNITUDE]}}
\end{center}
\vspace{1em}
\begin{itemize}
\item Relative to mean [Y] of [MEAN]: \alert{[PCT]\% change}
\item In SD units: \alert{[SD-COEF] $\sigma_{Y}$}
([小/中/大] effect by Cohen's benchmark)
\item[vs.] Closest prior estimate ([AUTHOR Year]):
[他们的系数]
— our estimate is [larger/smaller] because [识别策略差异]
\end{itemize}
\vspace{0.5em}
{\small \textit{Policy implication:} [一句话政策含义]}
\end{frame}
```
**第 3 张(若 DiD):动态效应图(Event Study)**
直接引用 `figures/fig*_event_study.pdf`,比静态系数更有说服力:
```latex
\begin{frame}{Dynamic Effects}
\begin{center}
\includegraphics[width=0.85\textwidth]{figures/fig01_event_study.pdf}
\end{center}
\vspace{-0.5em}
{\small \textbf{Takeaway:} No pre-trend. Effect appears [immediately/gradually]
after treatment. [Long-run/Short-run] effect: [β̂_long] ([SE], [sig]).}
\end{frame}
```
---
### 3.7 Robustness(稳健性,1–3 张)
**原则:结论先行,不要把所有检验逐条念一遍。**
```latex
\begin{frame}{Robustness}
\textbf{Main finding is robust to:}
\begin{columns}[t]
\begin{column}{0.5\textwidth}
\textbf{Inference:}
\begin{itemize}
\item[\checkmark] HC3 robust SE
\item[\checkmark] Two-way clustered SE
\item[\checkmark] Wild bootstrap (if < 30 clusters)
\end{itemize}
\vspace{0.5em}
\textbf{Sample:}
\begin{itemize}
\item[\checkmark] Exclude top/bottom 1\% of $Y$
\item[\checkmark] Drop high-influence observations
\end{itemize}
\end{column}
\begin{column}{0.5\textwidth}
\textbf{Specification:}
\begin{itemize}
\item[\checkmark] Log transformation
\item[\checkmark] Alternative control sets
\item[\checkmark] Oster $\delta = [值] \gg 1$
\end{itemize}
\vspace{0.5em}
\textbf{Identification:}
\begin{itemize}
\item[\checkmark] Placebo [treatment/cutoff/instrument]
\item[\checkmark] [策略特异性检验]
\end{itemize}
\end{column}
\end{columns}
\vspace{0.3em}
\small Coefficients range from [MIN] to [MAX] across all specifications.
\end{frame}
```
---
### 3.8 Takeaways(结论幻灯片,1 张)
**经济学报告的最后一张幻灯片绝对不能是 "Thank you / Questions?"**,必须是内容幻灯片,让听众带着结论离开。
```latex
\begin{frame}{Takeaways}
\begin{enumerate}
\item \textbf{Causal evidence:}
[D] [causes] [Y] to [increase/decrease] by
\alert{[MAGNITUDE]}.
[量级的直觉类比]
\item \textbf{Why it matters:}
[政策含义 / 理论贡献,一句话]
\item \textbf{Mechanism:}
[机制证据一句话(若有)]
\end{enumerate}
\vspace{1.5em}
\begin{center}
\normalsize [Author Name] \quad \texttt{[email]}
\end{center}
\end{frame}
```
---
## Step 4:PPTX 文件生成(Beamer 学术风格)
调用 `beamer-ppt` skill,使用 **python-pptx** 按 Step 3 的内容规范逐张生成幻灯片,输出 `.pptx` 文件。
### 4.1 配色主题方案
按 Step 1.3 用户选定的主题使用以下 RGB 配色:
| 主题 | 标题栏背景 | 强调色 | 正文背景 |
|------|-----------|--------|---------|
| **A. Metropolis(推荐)** | 海军蓝 `(0, 35, 82)` | 强调红 `(180, 30, 30)` | 浅灰 `(245, 245, 245)` |
| **B. 极简自定义** | 海军蓝 `(0, 35, 82)` | 海军蓝 `(0, 35, 82)` | 白色 `(255, 255, 255)` |
| **C. Madrid(传统)** | 深蓝 `(31, 73, 125)` | 金色 `(189, 152, 44)` | 白色 `(255, 255, 255)` |
### 4.2 幻灯片母版基础设置
```python
from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN
from pptx.enum.shapes import MSO_SHAPE_TYPE
# 16:9 宽屏(对应 Beamer aspectratio=169)
prs = Presentation()
prs.slide_width = Inches(13.33)
prs.slide_height = Inches(7.5)
# 配色(以 Metropolis 主题为例)
NAVY = RGBColor(0, 35, 82)
RED = RGBColor(180, 30, 30)
LGRAY = RGBColor(245, 245, 245)
WHITE = RGBColor(255, 255, 255)
BLACK = RGBColor(30, 30, 30)
MGRAY = RGBColor(100, 100, 100)
```
### 4.3 标题栏辅助函数(Frame Title)
每张内容幻灯片必须有海军蓝标题栏(高 1.1 英寸,白色加粗 24pt),模拟 Beamer `\frametitle`:
```python
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
def add_slide_bg(slide, prs, color):
"""全屏背景色块"""
bg = slide.shapes.add_shape(
1, 0, 0, prs.slide_width, prs.slide_height)
bg.fill.solid()
bg.fill.fore_color.rgb = color
bg.line.fill.background()
return bg
def add_frame_title(slide, prs, title_text, bg_color=None, fg_color=None):
"""Beamer 风格标题栏:海军蓝背景 + 白色粗体标题"""
bg_color = bg_color or RGBColor(0, 35, 82)
fg_color = fg_color or RGBColor(255, 255, 255)
bar = slide.shapes.add_shape(
1, 0, 0, prs.slide_width, Inches(1.1))
bar.fill.solid()
bar.fill.fore_color.rgb = bg_color
bar.line.fill.background()
tf = bar.text_frame
tf.word_wrap = False
p = tf.paragraphs[0]
p.text = title_text
p.font.bold = True
p.font.size = Pt(24)
p.font.color.rgb = fg_color
p.alignment = PP_ALIGN.LEFT
# 左边距
from pptx.util import Inches
tf.margin_left = Inches(0.3)
tf.margin_top = Inches(0.2)
```
### 4.4 底部进度条(Metropolis 风格)
```python
def add_progress_bar(slide, prs, current, total):
"""Metropolis 风格底部进度条(可选)"""
bar_h = Inches(0.06)
bar_top = prs.slide_height - bar_h
# 灰色底条
bg_bar = slide.shapes.add_shape(
1, 0, bar_top, prs.slide_width, bar_h)
bg_bar.fill.solid()
bg_bar.fill.fore_color.rgb = RGBColor(200, 200, 200)
bg_bar.line.fill.background()
# 海军蓝进度条
prog_w = int(prs.slide_width * current / total)
prog = slide.shapes.add_shape(1, 0, bar_top, prog_w, bar_h)
prog.fill.solid()
prog.fill.fore_color.rgb = RGBColor(0, 35, 82)
prog.line.fill.background()
```
### 4.5 逐类幻灯片生成
按 Step 2 大纲依次生成,每张幻灯片内容来自 Step 0.2 的**内容素材库**。
#### 标题页(深色背景全屏)
```python
def make_title_slide(prs, title, subtitle, author, institute, date):
slide = prs.slides.add_slide(prs.slide_layouts[6]) # blank
add_slide_bg(slide, prs, NAVY)
# 论文标题(白色,36pt,加粗,居中)
tb = slide.shapes.add_textbox(Inches(1), Inches(1.8), Inches(11.33), Inches(2))
tf = tb.text_frame; tf.word_wrap = True
p = tf.paragraphs[0]
p.text = title; p.font.bold = True
p.font.size = Pt(36); p.font.color.rgb = WHITE
p.alignment = PP_ALIGN.CENTER
# 副标题(浅灰,22pt)
p2 = tf.add_paragraph()
p2.text = subtitle; p2.font.size = Pt(22)
p2.font.color.rgb = LGRAY; p2.alignment = PP_ALIGN.CENTER
# 作者 + 机构(白色,18pt)
tb2 = slide.shapes.add_textbox(Inches(1), Inches(4.5), Inches(11.33), Inches(1.2))
tf2 = tb2.text_frame
tf2.paragraphs[0].text = author
tf2.paragraphs[0].font.size = Pt(18); tf2.paragraphs[0].font.color.rgb = WHITE
tf2.paragraphs[0].alignment = PP_ALIGN.CENTER
p3 = tf2.add_paragraph()
p3.text = institute; p3.font.size = Pt(16); p3.font.color.rgb = LGRAY
p3.alignment = PP_ALIGN.CENTER
# 日期/会议(浅灰,14pt)
tb3 = slide.shapes.add_textbox(Inches(1), Inches(6.2), Inches(11.33), Inches(0.8))
tf3 = tb3.text_frame
tf3.paragraphs[0].text = date
tf3.paragraphs[0].font.size = Pt(14); tf3.paragraphs[0].font.color.rgb = LGRAY
tf3.paragraphs[0].alignment = PP_ALIGN.CENTER
return slide
```
#### 通用内容幻灯片(条目列表)
```python
def make_content_slide(prs, title, bullets, current=None, total=None):
"""标题栏 + 条目列表正文"""
slide = prs.slides.add_slide(prs.slide_layouts[6])
add_slide_bg(slide, prs, LGRAY)
add_frame_title(slide, prs, title)
# 正文区
tb = slide.shapes.add_textbox(
Inches(0.5), Inches(1.3), Inches(12.33), Inches(5.8))
tf = tb.text_frame; tf.word_wrap = True
for i, (lvl, text) in enumerate(bullets):
p = tf.paragraphs[i] if i == 0 else tf.add_paragraph()
p.text = text; p.level = lvl
p.font.size = Pt(20 if lvl == 0 else 17)
p.font.color.rgb = BLACK
p.space_before = Pt(6 if lvl == 0 else 3)
if current and total:
add_progress_bar(slide, prs, current, total)
return slide
```
#### 图形幻灯片
```python
def make_figure_slide(prs, title, img_path, caption="", current=None, total=None):
"""标题栏 + 居中图形 + 图注"""
slide = prs.slides.add_slide(prs.slide_layouts[6])
add_slide_bg(slide, prs, LGRAY)
add_frame_title(slide, prs, title)
slide.shapes.add_picture(
img_path, Inches(1.17), Inches(1.3), Inches(11), Inches(5.2))
if caption:
cap = slide.shapes.add_textbox(
Inches(0.5), Inches(6.6), Inches(12.33), Inches(0.7))
cap.text_frame.paragraphs[0].text = caption
cap.text_frame.paragraphs[0].font.size = Pt(11)
cap.text_frame.paragraphs[0].font.color.rgb = MGRAY
if current and total:
add_progress_bar(slide, prs, current, total)
return slide
```
#### 回归表幻灯片
```python
def make_table_slide(prs, title, headers, rows, footnote="",
highlight_col=-1, current=None, total=None):
"""标题栏 + 精简回归表(≤4列)"""
slide = prs.slides.add_slide(prs.slide_layouts[6])
add_slide_bg(slide, prs, LGRAY)
add_frame_title(slide, prs, title)
nc = len(headers); nr = len(rows) + 1
tbl = slide.shapes.add_table(
nr, nc, Inches(0.5), Inches(1.4), Inches(12.33), Inches(4.5)).table
# 表头:海军蓝背景,白色字体
for j, h in enumerate(headers):
cell = tbl.cell(0, j)
cell.text = h
cell.text_frame.paragraphs[0].font.bold = True
cell.text_frame.paragraphs[0].font.size = Pt(14)
cell.text_frame.paragraphs[0].font.color.rgb = WHITE
cell.fill.solid(); cell.fill.fore_color.rgb = NAVY
# 数据行
for i, row in enumerate(rows):
for j, val in enumerate(row):
cell = tbl.cell(i + 1, j)
cell.text = str(val)
cell.text_frame.paragraphs[0].font.size = Pt(13)
if j == (nc + highlight_col) % nc: # 首选规格列加粗
cell.text_frame.paragraphs[0].font.bold = True
# 脚注
if footnote:
fn = slide.shapes.add_textbox(
Inches(0.5), Inches(6.0), Inches(12.33), Inches(1.2))
fn.text_frame.paragraphs[0].text = footnote
fn.text_frame.paragraphs[0].font.size = Pt(10)
fn.text_frame.paragraphs[0].font.color.rgb = MGRAY
if current and total:
add_progress_bar(slide, prs, current, total)
return slide
```
### 4.6 图形文件预处理
若 `figures/` 目录存在 **PDF 向量图**,先转为高分辨率 PNG 再嵌入 PPTX:
```python
import subprocess, os
def pdf_to_png(pdf_path, dpi=200):
"""PDF → PNG(需系统安装 poppler)"""
png_base = pdf_path.replace(".pdf", "")
subprocess.run([
"pdftoppm", "-r", str(dpi), "-png", "-singlefile",
pdf_path, png_base
], check=True)
return png_base + ".png"
# 若 pdftoppm 不可用,回退 pdf2image
def pdf_to_png_fallback(pdf_path, dpi=200):
from pdf2image import convert_from_path
imgs = convert_from_path(pdf_path, dpi=dpi)
png_path = pdf_path.replace(".pdf", ".png")
imgs[0].save(png_path, "PNG")
return png_path
```
安装依赖:
```bash
pip install python-pptx pdf2image --break-system-packages
apt-get install -y poppler-utils 2>/dev/null || true
```
### 4.7 演讲者备注
为每张关键幻灯片在 `notes_slide` 中添加备注,包含:核心论点(1–2 句)、预期Q&A 回答、时间提示。
```python
def add_speaker_notes(slide, notes_text):
notes_slide = slide.notes_slide
tf = notes_slide.notes_text_frame
tf.text = notes_text
```
---
## Step 5:文件输出
### 5.1 文件目录
```
slides/
├── slides.pptx # Beamer 风格 PPTX(可用 PowerPoint / LibreOffice 编辑)
└── slides.pdf # PDF 版本(用于投稿、邮件分发、归档)
```
### 5.2 保存 PPTX 文件
```python
import os
output_dir = os.path.join(workspace, "slides")
os.makedirs(output_dir, exist_ok=True)
pptx_path = os.path.join(output_dir, "slides.pptx")
prs.save(pptx_path)
print(f"✅ PPTX 已保存:{pptx_path}")
print(f" 共 {len(prs.slides)} 张幻灯片")
```
### 5.3 导出 PDF
用 LibreOffice headless 将 PPTX 转为 PDF(推荐,保留字体和布局):
```python
import subprocess, shutil
def pptx_to_pdf(pptx_path, output_dir):
"""使用 LibreOffice headless 将 PPTX 转为 PDF"""
result = subprocess.run(
["libreoffice", "--headless", "--convert-to", "pdf",
"--outdir", output_dir, pptx_path],
capture_output=True, text=True
)
pdf_path = pptx_path.replace(".pptx", ".pdf")
if os.path.exists(pdf_path):
print(f"✅ PDF 已导出:{pdf_path}")
return pdf_path
else:
print(f"⚠️ LibreOffice 转换失败:{result.stderr}")
return None
pdf_path = pptx_to_pdf(pptx_path, output_dir)
```
若 LibreOffice 不可用,回退方案(需安装 `unoconv` 或 `soffice`):
```bash
# 检查 LibreOffice 是否可用
which libreoffice soffice 2>/dev/null || echo "未找到 LibreOffice"
# Ubuntu/Debian 安装
apt-get install -y libreoffice 2>/dev/null || true
```
### 5.4 验证检查
```python
from pptx import Presentation
# 验证 PPTX
verify = Presentation(pptx_path)
assert len(verify.slides) > 0, "PPTX 文件为空!"
pptx_kb = os.path.getsize(pptx_path) // 1024
# 验证 PDF(若已生成)
pdf_ok = pdf_path and os.path.exists(pdf_path)
pdf_kb = os.path.getsize(pdf_path) // 1024 if pdf_ok else 0
print(f"✅ 验证通过")
print(f" PPTX:{len(verify.slides)} 张,{pptx_kb} KB")
if pdf_ok:
print(f" PDF :{pdf_kb} KB")
else:
print(f" PDF :未生成(可在 PowerPoint 中手动导出)")
```
---
## Step 6:阶段确认与移交
> **演示文稿产出摘要**
>
> ✅ Beamer 风格幻灯片:`slides/slides.pptx`(共 [N] 张,上限 [L] 张)
> ✅ PDF 版本:`slides/slides.pdf`(用于投稿、邮件分发、归档)
> ✅ 主题:[A Metropolis / B 极简 / C Madrid],16:9 宽屏,海军蓝配色
> ✅ PPTX 可直接用 PowerPoint 或 LibreOffice Impress 打开和编辑
>
> ---
>
> **幻灯片质量自检(报告前建议核查):**
> - [ ] 总张数是否在上限以内(A ≤ 15 / B ≤ 30 / C ≤ 20)?
> - [ ] "This Paper" 幻灯片是否包含主系数数值和量级?
> - [ ] 回归表是否精简到 ≤ 3–4 列?首选规格列是否加粗高亮?
> - [ ] 最后一张是否为 Takeaways(不是 "Thank you / Questions?")?
> - [ ] 图形是否以 ≥ 200 DPI PNG 嵌入,清晰无锯齿?
> - [ ] 每张关键幻灯片是否有演讲者备注?
> - [ ] 总时长估算:[N 张] × 1.5 分钟/张 ≈ [总分钟数],是否合理?
---
## 常见问题处理
**Q:图形文件不存在(`figures/` 目录为空),如何处理?**
先运行 `/plot` 命令(Phase 7 的绘图输出),生成所有分析图形,再运行 `/present`。若用户希望先生成幻灯片框架,用占位矩形替代:
```python
# 占位图(灰色矩形 + 说明文字)
from pptx.util import Inches, Pt
ph = slide.shapes.add_shape(
1, Inches(1), Inches(1.5), Inches(11.33), Inches(4.5))
ph.fill.solid(); ph.fill.fore_color.rgb = RGBColor(200, 200, 200)
ph.line.fill.background()
tf = ph.text_frame
tf.paragraphs[0].text = "[图形占位:figures/figNN_name.png]"
tf.paragraphs[0].font.size = Pt(18)
tf.paragraphs[0].font.color.rgb = RGBColor(100, 100, 100)
```
**Q:python-pptx 未安装?**
```bash
pip install python-pptx pdf2image --break-system-packages
```
**Q:PDF 图形转换失败?**
检查是否安装了 poppler:`which pdftoppm`。若未安装:
```bash
# macOS
brew install poppler
# Ubuntu/Debian
apt-get install poppler-utils
```
若环境受限,直接将 PNG 图形(来自 `/plot` 阶段输出的 `figures/*.png`)嵌入,跳过 PDF→PNG 转换。Help user transform their idea into a clear research question through interactive dialogue.
# /question — Research Question Scoping
When the user invoke /question, transforms their preliminary idea into a confirmed, well-scoped research question through focused and multi-round conversations. The output is a single clear research question statement.
---
## Step 1: Draw Out the Idea
Ask the user to describe their idea in 1–3 sentences. Frame it as low-stakes:
> "请用1–3句话描述你初步的研究想法。"
After they respond, identify the most unclear part and ask **one targeted follow-up** — focusing on whichever is most ambiguous:
- **谁受影响?**(研究对象:个体、企业、地区、国家?)
- **什么在变化?**(关键自变量或政策冲击是什么?)
- **关心什么结果?**(因变量:工资、健康、生产率、犯罪?)
Do not ask all three at once. One follow-up at a time.
---
## Step 2: Identify the Motivation
Once you understand the core idea, tell the user which type of research motivation this is. This helps them articulate the "why this paper" framing later.
| 类型 | 描述 | 例子 |
|------|------|------|
| **Type 1: 有趣的现象** | 数据中观察到的规律,需要解释 | 靠近高速公路的农村土地反而规模化更快 |
| **Type 2: 理论与现实的矛盾** | 理论预测X,但现实显示¬X | 最低工资理论上减少就业,但实证结果不一致 |
| **Type 3: 新制度/政策/技术** | 外生变化创造了研究机会 | 某省2015年推行宅基地改革 |
| **Type 4: 新数据** | 过去无法回答的问题现在数据可及 | 首次获得某平台的个体级交易数据 |
Say something like: *"你的研究动机最接近 Type X——[简短解释]。"*
---
## Step 3: Quick Check
Apply three quick checks. Flag any failure immediately.
**可检验 (Testable)**
Can the question be stated as "X 对 Y 的影响",where both X and Y are measurable variables?
- ✅ Pass: both X and Y can be operationalized as data columns
- ❌ Fail: question is too conceptual, normative, or tautological → help the user operationalize
**可识别 (Identifiable)**
Is there a plausible source of variation to answer this question credibly?
- ✅ Level A (因果): 有准实验变异(政策、阈值、工具变量)
- ✅ Level B (可信相关): 面板数据 + 固定效应 + 充分控制
- ⚠️ Level C (描述): 截面OLS,需降低因果主张的力度
- ❌ Fail: 完全内生,且无可用变异 → 需重新设计或降格为描述性研究
Be honest about the identification level. If it's Level C, say so clearly and note what it means for the kind of claims the paper can make.
**可操作 (Feasible)**
Is the required data obtainable and the method executable?
- Is there a publicly available dataset, or does the user have their own data?
- Is the scope answerable in one paper (one main question, not five)?
If any check fails, help the user either reformulate or scope down before proceeding.
---
## Step 4: Confirm the Research Question
Once the three checks pass (or the user accepts a scoped-down version), produce the confirmed research question in this format:
```
研究问题:[X] 如何影响 [Y]?
研究对象:[总体/单位],[时间/地域范围]
识别层级:Level [A/B/C]
数据来源(初步):[数据集名称或类型]
研究假设:
H₀:X 对 Y 无显著影响(β = 0)
H₁:X 对 Y 有 [正向/负向/显著] 影响(β ≠ 0)
预期方向:[理论或直觉上的预期,简要说明原因]
```
Then ask: *"这个研究问题符合你的想法吗?有什么需要调整的?"*
After the user explicitly confirms, save the output as a `research-question.md` document in your working directory. Then move to next phase `literature-review`.
---
## Common Reformulation Examples
**Too broad → Narrowed**
- ❌ "数字化对经济的影响"
- ✅ "工业机器人的普及是否降低了中国制造业城市的就业率(2000–2015)?"
**Fails identifiable → Redesigned**
- ❌ "ESG评分高的企业财务表现更好吗?"(OLS内生)
- ✅ "强制ESG披露政策(2008年深交所要求)是否改善了中小上市公司的财务绩效?"(DiD)
**Too vague → Operationalized**
- ❌ "教育对人的影响"
- ✅ "义务教育年限延长对个人30岁时工资的影响(利用教育改革作为工具变量)"