第 9 课 · 报告管理

批量管理投研报告

前面 8 讲把研究跑通了;
今晚把它们收成能打开、能一起管的 HTML 报告。

主案例 reports/lesson_09/if_ma10_atr/index.html
报告
管理
跑通研究
九个章节
Research
Report
index.html
catalog
先看现状

先看 reports 现在长什么样

CSV、PNG、短 README 都在,公开示例也有薄 HTML,但没有一份打开就能读完的九章报告。

reports/
├── strategy_examples/
│   ├── *.html
│   └── *_performance.png
├── lesson_06_multifactor_blind_validation/
│   ├── validation_report.md
│   ├── combination_performance_summary.csv
│   └── target_weights_*.parquet
├── lesson_07_etf18_logdiff_pca_ml/
│   ├── fold_metrics_lasso.csv
│   ├── overall_metrics.csv
│   └── README.md
├── lesson_07_etf18_horizon_sensitivity/
│   ├── comparison.csv
│   └── fold_metrics_h5_*.csv
文件都有用,但还是散落的材料,不是一份别人打开就能读懂的报告。
理解检查 · 现状

这些文件能直接算一份研究报告吗?

情境

同事发来一张净值图和一份指标 CSV,但没有写研究问题、样本和执行约定。

请用一句话作答,并说出理由。先独立想 30 秒,再展开答案。
点击展开答案
答案:不能直接算完整报告。至少要把研究问题、样本、方法、执行约定和证据来源写清。
判断依据:零散文件可以用于分析,但读者无法只靠它们复核结论。
1 · 九个章节

完整报告要写满这九章

模板里就是这九个标题。少一章,别人就没法复核。

1研究问题这次在问什么。没有它,读者只看到一条曲线。
2数据与样本标的、频率、起止、有没有切 IS/OOS。
3假设与方法规则、因子或模型到底是什么。
4执行约定什么时候成交、lag、佣金、滑点。
5证据与指标收益、回撤、换手、成本从哪来。
6图表净值、回撤,以及和问题对得上的图。
7对照与稳健性和谁比过。没做就写「本报告未做」。
8限制与下一步哪些结论推不出来,下一步想做什么。
9复现与产物怎么重跑,文件都在哪。
对照可以没做,第 7 章还是要写「本报告未做」。不要另加一章「投资建议」。
九个章节 · 动手检查

少一章,读者会失去什么?

理解检查 · 九章契约

没做对照时,第 7 章怎么写?

情境

一份报告还没有与基准策略比较。作者想删掉“对照与稳健性”整章。

请用一句话作答,并说出理由。先独立想 30 秒,再展开答案。
点击展开答案
答案:不能删。保留第 7 章,明确写“本报告未做”对照。
判断依据:写明未做能界定证据边界;直接省略会让读者误以为已经检验过。
2 · 现有 skill

report skill 从结果到网页怎么走

别的 skill 只交结果。图用 charts 画,网页用 ReportRenderer 拼。预览页只看指标,九章报告才能交出去。

%%{init: {"theme":"base","themeVariables":{"fontFamily":"PingFang SC, Microsoft YaHei, sans-serif","fontSize":"15px","primaryColor":"#d5e6ea","primaryTextColor":"#1a2a30","primaryBorderColor":"#2a4a54","lineColor":"#2a4a54","secondaryColor":"#fff8e8","tertiaryColor":"#f8e6e8"}}}%%
flowchart LR
  IN["研究结果"] --> CH["charts 画图"]
  CH --> P{"要哪种网页?"}
  P -->|只要指标和曲线| D["自己调渲染器"]
  D --> D1["预览页"]
  P -->|要交得出去的研究| R["write_research_bundle"]
  R --> R1["九章 index.html"]
  R1 --> C["write_research_catalog"]
  C --> C1["目录页"]

  classDef ok fill:#d5e6ea,stroke:#2a4a54,stroke-width:2px,color:#1a2a30
  classDef ask fill:#fff8e8,stroke:#2a4a54,stroke-width:2px,color:#1a2a30
  classDef focus fill:#c5d9de,stroke:#2a4a54,stroke-width:2px,color:#1a2a30
  class IN,CH,D,D1 ok
  class P ask
  class R,R1,C,C1 focus
预览页 自己调渲染器,马上看到指标和曲线。像仪表盘,不是研究报告。
九章报告 今晚要写的那种。问题、样本、方法、数字、限制都写全。另调 catalog 才能进目录。
3 · 同一条写出路径

完整报告都走同一条路:字段 → 函数 → 模板 → 固定目录

字段ResearchReport同一套内容
写出函数write_research_bundle文件名函数自己定
模板research_report.html九个中文标题
保存位置namespace/slugindex.html
约束做法漏了会怎样
字段questionmetrics_source 就报错写不出 HTML
版式九个中文 <h2> 写在同一份模板里测试会检查标题齐不齐
只收 PNG,嵌进页面不会出现有的图要外链才能看
路径函数自己拼 reports/<namespace>/<slug>/index.html目录页才能稳定扫到
编目同时有 index.htmlparams.json 才算一份 study旧的 CSV 堆不会混进总览
分类靠文件夹和 params.json,不上数据库。默认 private,不要提交。公开示例是薄 HTML 卡片,不是九章档案。
统一写出路径 · 单步播放

ResearchReport 怎样变成 HTML?

4 · 写出函数

一个函数写出一份报告

write_research_bundle(report: ResearchReport, reports_root=None) -> Path
# 传入内存里填好的 ResearchReport。
# 不要丢一堆 CSV 路径,也不要自己指定 index.html 叫什么。
1 检查先拦住不完整的输入路径、必填字段、visibility。有图就要 png 或路径,有表就要 frame 或 html
2 转换变成模板能用的数据图变成 data URI,表变成 HTML
3 渲染复用现有渲染器ReportRenderer.render("research_report", …),再保存
4 返回这份报告所在目录同一 namespace/slug 再写一次会覆盖
5 目录页不会顺便生成全部写完后,再调 write_research_catalog()
会写出这两个文件index.html 是九章正文,图已经嵌进去。params.json 给目录页用:标题、样本、指标摘要、数字来源。有指标时还会写出 artifacts/metrics.csv
课堂上至少要填研究问题 questionmetricsmetrics_source;成交约定 execution。图和表都可以空。
没写研究问题或数字来源,直接报错。课堂例子:reports/lesson_09/if_ma10_atr/index.html。一份报告用 bundle,全部报告用 catalog。
5 · 谁写 HTML

别的 skill 不要自己写研究报告

%%{init: {"theme":"base","themeVariables":{"fontFamily":"PingFang SC, Microsoft YaHei, sans-serif","fontSize":"15px","primaryColor":"#d5e6ea","primaryTextColor":"#1a2a30","primaryBorderColor":"#2a4a54","lineColor":"#2a4a54","secondaryColor":"#fff8e8","tertiaryColor":"#f8e6e8"}}}%%
flowchart LR
  U["上游只交结果"] --> A["填 ResearchReport"]
  A -->|自己写 HTML| X["不允许"]
  A -->|只交对象| Q{"字段齐全?"}
  Q -->|缺了| E["报错,不写文件"]
  Q -->|齐全| B["write_research_bundle"]
  B --> F["index.html + params.json"]
  F --> C{"要总览?"}
  C -->|另调一次| CAT["catalog.html"]
  C -->|先看这一份| H["打开 HTML"]

  classDef ok fill:#d5e6ea,stroke:#2a4a54,stroke-width:2px,color:#1a2a30
  classDef err fill:#f8e6e8,stroke:#7a3a42,stroke-width:2px,color:#7a3a42
  classDef ask fill:#fff8e8,stroke:#2a4a54,stroke-width:2px,color:#1a2a30
  class U,A,B,F,CAT,H ok
  class X,E err
  class Q,C ask
完整报告只走 write_research_bundle。report skill 不算因子、不跑回测。
理解检查 · 统一入口

谁负责写九章 HTML?

情境

回测 skill 已得到指标和图,团队准备让它自己拼出研究报告 HTML。

请用一句话作答,并说出理由。先独立想 30 秒,再展开答案。
点击展开答案
答案:上游交结果;Agent 填 ResearchReport,交给 write_research_bundle 写出九章 HTML。
判断依据:同一契约、入口和模板才能保证字段、版式与目录一致;缺关键字段时由入口校验并报错。
6 · 交给 AI

让 AI 来写这份报告

Prompt 里把这几句说清楚

  1. 先读 AGENTS.mdskills/report/SKILL.md
  2. 不要新开研究,也不要重写现有渲染器。
  3. 用已有回测填 ResearchReport,走 write_research_bundle 写出九章 HTML,图嵌进页面。
  4. 落到 reports/lesson_09/if_ma10_atr/index.html,再另调一次编目。
怎么算做完
文件:目录里有 index.htmlparams.json
打开:按九章能读完;把 HTML 单独拷走,图还在。
目录:catalog.html 能点进这份报告;不要把 private 报告 git add 进去。
7 · 课堂例子

用第 5 课的 IF 规则出一份 HTML

这课不新开研究,不调参,也不报具体收益。规则第 5 课已经讲过。

空仓、且 MA10 / ATR14 算得出来时,close < MA10 就满仓;
止损只上移;close 跌破止损就空仓。
字段课堂上怎么填
路径namespace=lesson_09slug=if_ma10_atrreports/lesson_09/if_ma10_atr/index.html
品种 / 频率["CFFEX.IF99"] · 1d
成交约定和第 5 课课堂上说的一致,写进报告正文
visibilityprivate(默认不要提交)
metrics_sourceBacktestResult.metrics,或写清 parquet / csv 路径
问题怎么写写成「看这条规则在给定成本下的历史表现」,不要写成「这是稳赚策略」。
数字怎么对报告里的关键数字,要能在 metrics_sourceparams.json 里找到同一来源。
图怎么验index.html 单独拷到桌面再打开。图还在,才算嵌进去了。
理解检查 · AI 交付与课堂案例

这份 HTML 能直接交付了吗?

情境

AI 已根据第 5 课 IF 回测生成 index.html,却没说明报告中指标的来源。

请用一句话作答,并说出理由。先独立想 30 秒,再展开答案。
点击展开答案
答案:不能。要写清 metrics_source,并核对报告中的关键数字能追溯到该来源。
判断依据:有 HTML 文件不等于研究结论可复核;数字来源是验收要点。
8 · 编目

目录页要另调一次,不会跟着 bundle 自动生成

做完 8 讲,本地会有一堆实验文件夹。没有总览,就只能凭记忆去翻。

write_research_catalog()
    → 扫描 reports/(跳过 README、catalog 自己)
    → 同时有 params.json 和 index.html → 收成一条
    → 只有 CSV/PNG → 还没写成报告,不进目录
    → 写出 reports/catalog.html 和 reports/catalog.json
目录里至少列出namespace、slug、标题、样本起止、有指标就展示(没有就空着,不要编)、visibility,以及点进该 index.html 的链接。
不是数据库catalog.json 只是把扫描结果存成文件,方便 Agent 读。下次生成会整份覆盖。报告几十到几百份时,扫目录足够快。
旧目录不会自动升级没有 index.html 的 CSV 堆,不会混进总览。有人补写成报告之后才会出现。
公开示例短页不进目录strategy_examples 没有 params.jsonindex.html,不会自动编进来。
编目录是为了好找,不是宣布这些实验都有效。不要把指标排序讲成排行榜。catalog 默认也不要提交。
批量编目 · 动手判断

哪些实验能进入 catalog?

理解检查 · 目录编目

这个旧实验会进目录吗?

情境

某实验目录只有 comparison.csv 和 performance.png。现在运行 write_research_catalog()。

请用一句话作答,并说出理由。先独立想 30 秒,再展开答案。
点击展开答案
答案:不会。目录里必须同时有 index.html 和 params.json 才会被编目。
判断依据:只有 CSV/PNG 的实验尚未装订成研究档案;catalog 不会自动替它生成报告。