Metadata-Version: 2.4
Name: mtsa-agent
Version: 0.3.0
Summary: 多源时序数据量化分析与可视化 Agent（课题 12 / S06）
License-Expression: Apache-2.0
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: pandas<4,>=3.0
Requires-Dist: numpy<3,>=2.5
Requires-Dist: scipy<2,>=1.18
Requires-Dist: statsmodels<0.16,>=0.15
Requires-Dist: plotly<8,>=7.1
Requires-Dist: kaleido<2,>=1.4
Requires-Dist: pydantic<3,>=2.13
Provides-Extra: docx
Requires-Dist: python-docx>=1.2; extra == "docx"
Provides-Extra: io
Requires-Dist: openpyxl>=3.1; extra == "io"
Requires-Dist: pyarrow>=25; extra == "io"
Requires-Dist: h5py>=3.16; extra == "io"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Dynamic: license-file

# 多源时序数据量化分析与可视化 Agent

> 本页是项目概览（一页看完）：它是什么、一条链路怎么走、做到哪一步、哪些没达标、从哪开始看。
> 完整手册（安装、全部命令、运行保护、能力边界）：[`doc/使用手册.md`](doc/使用手册.md)　|　首次运行：[`doc/安装与首次运行.md`](doc/安装与首次运行.md)

## 五分钟跑通

```bash
pip install mtsa-agent   # 从 PyPI 安装（发行名与命令名不同：装的是 mtsa-agent，用的是 mtsa）
# 或在仓库根目录：pip install .
mtsa demo            # 生成一份合成天气数据，跑完整链路，出报告
```

`mtsa demo` **不需要模型、不需要联网、不需要准备数据**。跑完当前目录多出 `mtsa_demo/`：

| 文件 | 是什么 |
| --- | --- |
| `report.md` | 人读报告：数据体检、指标、异常、变化点、结论与证据 |
| `result.json` | 结构化结果：每条结论的证据链、质量问题的可定位区间、运行参数 |
| `input.csv` | 本次用的合成数据（2,211 行；内含一段持续高温、一个气压台阶、一段连续缺失、3 条重复时间戳） |

换成自己的数据：

```bash
mtsa run --scene weather --input 你的数据.csv --question "分析温度的趋势和异常"
```

数据格式（时间列、多列、多站点）见 [`doc/安装与首次运行.md`](doc/安装与首次运行.md)。

---

| 项 | 内容 |
| --- | --- |
| 任务标识 | `multi_source_timeseries_analysis`（课题 12，AI for Science，S06） |
| 概要日期 | 2026-10-24 |
| 一句话 | 输入一份带时间列的多源数据 + 一句自然语言问题，输出「每条结论都绑定证据、可复现、可回放」的分析报告；同一套引擎提供固定流水线与模型编排两种运行方式。 |
| 核心结论 | 工程链路已闭环、证据体系完整；**分析正确性只证到「统计异常」与「季节/趋势」，官方灾害事件的召回仍为 0.071，未达标**。 |

> 本文只做「结论 + 索引」，不重复格式契约。
> 接口与字段以 `doc/接口与字段.md` 为准，任务状态以 `spec/当前开发任务.md` 为准。

---

## 1. 它是什么

**能回答的问题**

- 这份数据的结构是什么？时间轴连不连续，有没有缺失、重复、乱序、单位异常？
- 趋势方向、季节振幅、峰谷月份、主周期是多少？
- 哪些时刻是异常点、哪些区段是持续异常、变化点在哪里？
- 各列之间是否相关、是否存在滞后关系？
- 在给定假设下，下一个周期（默认 24 小时）大致是什么范围？（`--forecast`，仅天气）
- 结果能否复现？每条结论对应哪个数字、哪个文件、哪一行代码？

**明确不做**

- 不做因果推断，不做交易建议与自动交易；
- 不让模型参与任何数值计算（模型只决定「先跑哪个工具」）；
- 不改原始输入文件，所有产物写入独立 `artifacts/<run_id>/`；
- 股票场景只支持固定流水线，Agent 未实现（请求返回 `AGENT_SCENE_UNSUPPORTED`）；
- 彩票 / CSI 场景、多模型对比、对外 REST 服务，均未实现。

### 两种运行模式

| 模式 | 行为 | 无模型时 |
| --- | --- | --- |
| `pipeline`（默认） | 固定跑完 12 项计划，确定性 | 正常 |
| `agent` | 天气场景下由模型在白名单 5 个工具里选下一步 | `AGENT_UNAVAILABLE` |
| `auto` | 天气且有模型才升级，否则回退 | 回退 pipeline 并写 warning |

---

## 2. 一条链路的六个步骤

| 阶段 | 做什么 | 由谁决定 |
| --- | --- | --- |
| ① 体检 | 时间轴连续性、缺失、重复、乱序、量级与单位；只报告，不自动改数据 | 固定 |
| ② 计划 | 分析项、目标列、周期、阈值 | 规则；或模型选择（agent） |
| ③ 清洗 | 插补 / 丢弃 / 单位换算，动作逐条记账 | 固定 |
| ④ 分析 | 指标、频谱、统计检验、异常、变化点、极端值、泄漏检查 | pipeline 固定；agent 由模型选工具 |
| ⑤ 结论 | 把数字写成一句话，绑定证据（指标名 / 产物编号 / 计算位置） | 固定 |
| ⑥ 报告 | `result.json` + `report.md` + 图表 + 清洗数据 + 复现脚本 | 固定 |

**三个容易混的口径**：规则计划选中 **12 项**分析；计划层 `TOOL_SPECS` 有 **13 项**（多 `randomness`）；引擎内部 `ALL_ANALYSES` 有 **14 项**（再多 `volatility`）。评估里的「规则计划覆盖率」固定以 12 项为分母，「工具覆盖率」以 5 个白名单工具为分母，两者不可互换。

---

## 3. 现在做到哪里（按证据分级）

| 维度 | 结论 | 关键数字 | 证据 |
| --- | --- | --- | --- |
| 工程基线 | **通过** | 51 个测试文件 / 473 项 / 0 失败 / 413.86 s（2026-10-24 21:46） | `evals/test_logs/summary.json` |
| 鲁棒性 | **通过** | 37 个坏输入与边界用例 37/37，0 崩溃；失败均带错误码与出错节点 | `evals/robustness_results.json` |
| 结论级门禁（独立数据 v2） | **通过** | 24/24（10 pipeline + 10 agent + 4 非劣性）；事件级命中 R=0.9667、F1=0.9831；点级 P=1.000 / R=0.840 | `evals/conclusion_gate_v2_results.json` |
| 真实数据验证（B） | **工程通过，正确性未证** | 10 份数据 × 4 问题 × 2 模式 = 80/80 成功，证据覆盖 1.000；14 项验收 13 项通过 | `evals/real_data_results.json` |
| 数据扩容（D3） | **部分通过** | 新增 7 份（3 大洲、4 份海拔 ≥1500 m），28/28 成功；registry 10 → 17 | `evals/d3_results.json` |
| 预测（可选，仅天气） | **通过** | 17 份 / 94 列全部完成；90% 区间覆盖率 0.8722（33,376 点）；MASE≤1.0 占 68/94 = 0.723 | `evals/forecast_results.json` |
| Agent 对照（13 用例） | **可用** | 13/13 成功；2.54 步；需求覆盖 1.00；结论 29.92 vs 39.00（−23.3%）；token 53,924；墙钟 12.77 s vs 12.09 s | `evals/mode_compare_results.json` |
| 规模与性能 | **有明确上限** | 20 万行上限（`MTSA_MAX_ROWS`）；1e5 行 37.1 s、2e5 行 123.9 s、5e5 行 736 s、1e6 未完成 | `doc/评估设计.md`、`doc/改进记录.md` #4/#6 |

**规模数字**：`src/mtsa` 29 个文件 / 6,330 行；`tests` 目录 50 个 py（逐文件入口统计 51 个文件 / 473 项）；`evals` 20 个文件 / 6,594 行；真实数据 registry 17 份（5 个来源：Open-Meteo / NOAA GHCN-Daily / DWD / ECCC / ASOS；2 种频率：hourly 14、daily 3）。

**评估指标**：29 项 = 22 项规则模式阈值指标 + 3 项 LLM 模式指标（合法率、回退率、覆盖率）+ 4 项 Agent 指标（后 7 项仅在对应评估缓存存在时纳入判定）。LLM 覆盖率只统计合法计划，回退时不计入平均——否则「模型全挂」会被算成高覆盖。

---

## 4. 还没做到 / 没达标的（诚实清单）

| 编号 | 缺口 | 实测 | 影响 | 状态 |
| --- | --- | --- | --- | --- |
| R13 / E4 | 官方灾害事件召回 | **0.0714**（阈值 ≥0.50）；14 条事件只命中 1 条 | 「能检出真实灾害」这句话目前**不成立**，只能声称能检出统计异常 | 未达标，未立项 |
| D3-4 | 阵风是否有额外收益 | 阵风 3/4、小时平均风速 3/4（完全相同） | 假设被证伪；真正起作用的是「日均 → 小时」的时间分辨率，且样本只有 4 条事件 | 未通过，按原标准记录 |
| 变化点判据 | v2 上的 F1 | **0.50**，恰好等于阈值 0.50 | 门禁形同虚设，任何轻微波动都会跌破 | 压线通过，待立项 |
| 预测覆盖 | 出界列 | 6 列超出 [0.80, 0.98]（降水类、ASOS 不规则报时） | 「一条口径打天下」不够，降水类需单独处理 | 如实记录，未调参迁就 |
| 检测器能力 | 缓慢漂移与持续偏移 | 逐点判定检不出「单点不超阈、整段偏移」 | 传感器漂移类故障会漏 | 见 `doc/改进记录.md` 遗留问题汇总 |
| 规模 | 百万行 | 1e6 超 300 s 未完成；ADF 不能截断滞后阶（实测会翻转平稳性判定） | 大文件只能拒绝或降采样 | 已设 20 万行上限 |
| 场景 | 股票 Agent | `AGENT_SCENE_UNSUPPORTED` | 「多场景 Agent」实际只有天气 | 用户明确暂缓 |
| 产品化 | E1 可观测性 / E2 金额换算 / E3 REST | 未立项 | 对外交付前必须先做 | 按需启动 |

**一条必须记住的口径**：`agent` 比 `pipeline` 少 23.3% 的结论，**100% 归因于「工具未执行」**，不是算错；但「没跑」也不能当成「没问题」——报告里必须写「未执行」，不能写「未检出」。

---

## 5. 交付物与入口

### 运行

```bash
# 安装：pip install .（Python >= 3.12）；开发用 pip install -e .
# 未安装时也可用 PYTHONPATH=src
python -m mtsa.cli run --scene weather \
  --input fixtures/weather_v1.csv \
  --question "分析温度的趋势、季节性和异常点，并检测变化点"

python -m mtsa.cli run --mode agent --scene weather \
  --input fixtures/weather_v1.csv --question "分析温度的趋势、季节性和异常"

python -m mtsa.cli run --scene weather --input fixtures/weather_eval_v2.csv \
  --question "分析温度的趋势" --forecast --forecast-horizon 24

python -m mtsa.cli run --replay artifacts/<run_id>/result.json   # 离线重放，不调模型
```

**判断成败看 `result.json` 的 `status`，不要以「产物目录非空」为准**——失败时也会落盘留档。

### 文档索引

| 文档 | 作用 |
| --- | --- |
| `doc/使用手册.md` | 全部命令与能力边界（最全） |
| `doc/项目说明书.md` | 对外说明书：能做什么、做到什么程度、怎么复现 |
| `doc/架构设计.md` | 12 个节点、两种模式的边界、依赖表 |
| `doc/接口与字段.md` | `result.json` 字段契约（含 `data.extremes` / `data.forecast`） |
| `doc/评估设计.md` | 每项指标的算法与口径（含 6.19 预测口径） |
| `doc/改进记录.md` | T1 起逐条改进账本 + 遗留问题汇总 |
| `spec/当前开发任务.md` | 当前阶段状态与下一项候选 |
| `spec/项目承接已完成.md` | 41 章执行记录：做了什么、实测数字、取舍、限制、证据路径 |
| `spec/已完成任务.md` / `spec/任务书归档.md` | 各项验收表与遗留限制（「当时要求什么」的对照证据） |
| `doc/全链路Demo_柏林2024.docx` | 5 页演示：一份数据走完六步 + 三张结果图 |
| `doc/Agent一键Demo说明_2026-10-24.docx` | 一键 demo 的图文说明（含单位变化诊断案例） |
| `doc/Agent全流程Demo_2026-10-23.docx` | 10-23 旧版演示（历史留档，评审看上面两份） |

---

## 6. 目录

```text
src/mtsa/            引擎：导入 / 摘要 / 质量 / 预处理 / 指标 / 频域 / 检验 / 异常 / 图表 / 报告 / 编排
  scenarios/         场景适配器（weather 主场景；stock 仅 pipeline）
scripts/             一键 demo、真实数据抓取与标注、两份 Word 文档生成
tests/               50 个测试文件
evals/               20 个评估脚本 + 结果 JSON + 评估记录
fixtures/            固定样例、真实数据 registry、标签与真值
artifacts/           运行产物（按 run_id 隔离，不入库）
spec/                任务书、状态、已完成记录、未来规划
doc/                 使用手册、架构、接口、评估、改进记录、报告与 Word 交付物
```

---

## 7. 复现与验收命令

```bash
# 一键演示：同一份数据跑完六步，不需要模型、不需要联网
python scripts/demo.py --mode pipeline

# 全量测试（逐文件独立进程，避免单进程卡死）
python run_tests.py --timeout 300

# 主评估：22 项核心阈值 + LLM 3 项 + Agent 4 项（缓存齐全时共 29 项）
python -m evals.run_evals

# 独立数据上的结论门禁（4 问题 × pipeline/agent，24 项）
python -m evals.conclusion_gate_eval --pipeline-only   # 离线；去掉参数会调模型

# 鲁棒性矩阵（37 用例，约 72 s）
python -m evals.robustness_eval

# 数据扩容与事件覆盖（约 7 分钟）
python -m evals.d3_expansion_eval

# 预测评估（17 份 / 94 列）
python -m evals.forecast_eval

# 重跑全链路 demo 并重新生成 Word 演示文档
python scripts/make_chain_demo_doc.py --rerun
```

---

## 8. 文档一致性（2026-10-24 已收敛）

C 阶段（交付卫生）修完以下不一致，记录在此防止回退：

| 位置 | 原问题 | 现状 |
| --- | --- | --- |
| `doc/项目说明书.md` | 「不做预测」与同文预测能力矛盾 | 改为「不做业务预测与因果推断；`--forecast` 只给点预测 + 经验区间」 |
| `doc/项目说明书.md` | 输出结构写成子目录 | 改为 `fig_*.png` / `fig_*.html` 直接写在运行目录 |
| `doc/项目说明书.md` 6.6 | 主表是 F 阶段 11 份 / 58 列 | 标注为「F 阶段口径」，并指向 6.8 的 17 份 / 94 列 |
| `spec/已完成任务.md` | 测试数停在 31 文件 / 304 项 | 更新为 51 / 473（2026-10-24 21:46） |
| 三份 spec 的「下一步」 | 三个不同说法 | 统一到 `spec/未来规划.md` 的 C → B1 → B2 → B3 |
| 多站点 | 一直列为「待拍板」 | 已声明为正式支持（README、项目说明书） |

> `spec/项目承接已完成.md` 里出现的旧数字（如「31 个文件 / 304 项」）是**历史记录**，
> 按项目规则不回改，只以当前文件为准。

## 9. 下一步（2026-10-24 已定：产品化优先）

用户决定「要给别人用」：先把产品做出来，再继续研究、迭代。

| 顺序 | 任务 | 状态 | 门槛 |
| --- | --- | --- | --- |
| C | 交付卫生：文档口径、三份规划收敛、多站点正式声明 | **已完成** | 文档与代码逐条对齐 |
| B1 | E1 可观测性：未执行原因 + 覆盖矩阵 | **已完成** | 每个 `not_run` / `failed` / `skipped` 都有原因；矩阵进 `report.md` 与 `coverage.tools[]` |
| B2 | E2 成本语义：token → 金额、预算前置 | **已完成** | 金额标「估算」、带价目表出处；无表不按 0 计价；预扣后不超限 |
| B3 | 交付形态（用户选 C 档：不做 HTTP） | **已完成** | `pip install .` 后 `mtsa run` 可用；从无关目录、无 PYTHONPATH 实测通过；Dockerfile 未构建验证 |
| 之后 | A1/A2 检测器质量 | 挂起 | v2 F1 ≥0.55 且 22 项逐位不变 |

研究线（A1 变化点判据 → A2 持续段/漂移 → 预测场景化）在产品可用后启动，
详见 `spec/未来规划.md`。

---

## 10. 授权与使用

代码采用 **Apache License 2.0**：可自由使用、修改、分发，包括商业用途，条件是保留版权与许可声明。
完整条款见 [`LICENSE`](LICENSE)，版权归属见 [`NOTICE`](NOTICE)。

本项目同时是课程/课题「课题 12 · AI for Science · S06」的提交物（2026-10-24 首次提交）。

第三方材料的授权链独立，不受本许可证影响：

| 文件 | 管什么 |
| --- | --- |
| [`DATA_SOURCES.md`](DATA_SOURCES.md) | `fixtures/` 下 17 份外部数据的来源、许可证与**必须保留的署名文本** |
| [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md) | pandas / numpy / scipy / statsmodels / plotly 等依赖的许可证 |

> 数据署名（CC BY 4.0）是数据提供方的要求，与代码许可证无关；删掉署名即违反数据条款。
