refactor: ECR-002 拆分 runtime 包并加深 analyze 契约(已审)

将 web/services/runtime.py 拆为 runtime/ 子模块并保持门面兼容;补齐 ESS 文档、门面/契约/TF_DF 测试与 CODE_REVIEW Approve。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-06 18:15:23 +08:00
co-authored by Cursor
parent 9f1e7361b6
commit df27b4dde8
33 changed files with 2029 additions and 1206 deletions
+36
View File
@@ -0,0 +1,36 @@
# AGENT_MEMORY — chan
> Agent 短记忆。先读 `PROJECT_PROFILE.md`,再读本文件。不要把猜测写进这里。
## 双前端
| 入口 | 引擎 | 实时 |
|------|------|------|
| `/` | Lightweight Charts | HTTP 定时自动刷新(增量 + 每 6 次全量) |
| `/chan_tv` | Charting Library 全版 | datafeed `subscribeBars` → WS |
勿把主站 `live_feed` 方案与 chan_tv datafeed 混为一谈;主站 WS 实时已回退。
## 版本
- `system_version``v1.0.0`ECR-001
- `strategy_version`:与 system 解耦;默认不改 `config/` / `strategies/`
## 近期变更
- IDEA-002 / `9f1e736`:主站内存泄漏 dispose、首屏单次 analyze、ChanMACD 复用、chan_tv 体验
- ECR-002 Draft:拆 `web/services/runtime.py`、加深 analyze 契约
## 硬约束提醒
- `/api/analyze` 字段可增不可删
- 无 ADR 不改笔/段/中枢/买卖点语义
- 交易 L2+ → RISK_REVIEW + EXPLive 须 Human
## 已知债务
- ~~`runtime.py` 仍过大 → ECR-002~~ **已拆包**(待 CODE_REVIEW
- `chart_tv.js` 单体巨大 → 后续可选 ECR
- analyze 契约已加深(mock HTTP);可再加固定 JSON 快照文件
- 内存泄漏尚无自动化 heap/监听断言
- `macd_config` POST 写本地 global 的历史 quirks(未改)
+29
View File
@@ -1,5 +1,34 @@
# CHANGELOG
## Unreleased — 2026-08-06
### ECR-002L3,待 Review
- 拆分 `web/services/runtime.py` 为包 `web/services/runtime/`state / timeframes / market_data / indicators / analyze / serialize
- 加深 analyze 契约测试(mock HTTP + analyze_chan 键集 + serialize JSON
- 新增 TF_DF 全量 init 冒烟与 runtime 门面测试
### IDEA-002L1 补档)
对应 commit `9f1e736`。无新 system tag(仍为 `v1.0.0`)。
#### Fixed
- 主站自动刷新内存泄漏:`disposeTradingViewCharts`、去掉重复 sync 监听、默认增量刷新(每 6 次全量重建笔/段/中枢)
- 加密货币首屏重复调用 `/api/analyze`
- ChanMACD 同周期重复全量分析(复用 `get_klc_list` 结果)
#### Changed
- `/chan_tv`:WS/REST 可分离配置、指标布局 localStorage、未完成中枢与 datafeed 实时 tick 行为完善
- `PROJECT_PROFILE` Realtime 条目与 chan_tv WS 对齐(文档)
#### Docs
- ESSIDEA-002、AGENT_MEMORY、AGENTSECR-002 实现与报告
---
## v1.0.0 — 2026-08-05(首个正式 Release
对应 ECR-001 / tag `v1.0.0`。详见 `docs/RELEASE/ECR-001-v1.0.0.md`
+4 -4
View File
@@ -45,11 +45,11 @@ pytest tests/test_golden_pipeline.py web/tests/test_analyze_contract.py → 6 pa
### Non-blocking(记入债务,需新 ECR 再动)
1. **`web/services/runtime.py` ~1176 行** — 已从 app 抽出但仍是大模块;facade 再导出符合计划,建议 ECR-002 继续按 data/analyze/serialize 物理拆分
2. **`web/static/js/app/chart_tv.js` ~4664 行** — `initTradingView` 单体;行为冻结下可接受。
3. **`/api/analyze` 契约测试偏浅** — 仅关键字段清单 + 路由存在;无固定 fixture 的端到端 JSON 快照(需 mock 行情)。
1. **`web/services/runtime.py` ~1176 行** — 已从 app 抽出但仍是大模块;facade 再导出符合计划**已起草 `docs/ECR/ECR-002-runtime-split.md`Draft**
2. **`web/static/js/app/chart_tv.js` ~4664 行** — `initTradingView` 单体;行为冻结下可接受ECR-002 可选范围
3. **`/api/analyze` 契约测试偏浅** — 仅关键字段清单 + 路由存在;无固定 fixture 的端到端 JSON 快照(需 mock 行情)→ ECR-002
4. **TEST_REPORT 写「5 passed」** — 现为 6(含 shim 兼容测);Release 前可改正文(L0 docs)。
5. **L1`TF_DF.get_zs_list` 恢复** — 合理兼容修复;golden 走 analyze 路径未覆盖 `TF_DF(df,...)` 全量 `__init__`,建议后续加一条 init 冒烟(非阻断)
5. **L1`TF_DF.get_zs_list` 恢复** — 合理兼容修复;golden 走 analyze 路径未覆盖 `TF_DF(df,...)` 全量 `__init__` → ECR-002 Acceptance
### No blockers
+74
View File
@@ -0,0 +1,74 @@
# CODE_REVIEW — ECR-002
**Role:** REVIEWER
**Date:** 2026-08-06
**Scope:** 工作区未提交实现(相对 `HEAD`/`9f1e736`);包 `web/services/runtime/` + 测试 + ESS 文档
**Decision:** Approve
## Evidence loaded
- `docs/ECR/ECR-002-runtime-split.md`
- `docs/ENGINEERING_SPEC/ECR-002-runtime-split.md`
- `docs/IMPLEMENTATION_REPORT/ECR-002.md`
- `docs/TEST_REPORT/ECR-002.md`
- `docs/HANDOFF/ECR-002-engineer-to-reviewer.md`
- 包源码:`web/services/runtime/{__init__,state,timeframes,market_data,indicators,analyze,serialize}.py`
- Diff:删除 `web/services/runtime.py`;新增包与测试
## Acceptance ↔ Evidence
| Acceptance | Verdict | Evidence |
|------------|---------|----------|
| runtime 门面公开符号兼容(含历史 `import *` 漏出) | PASS | 手工核对 api 所需符号;`timezone`/`OrderedDict`/`np`/`StructureZone*`/`ThreadPoolExecutor` 等在门面;`test_runtime_facade` |
| Golden 通过 | PASS | 复跑 `tests/test_golden_pipeline.py` |
| Analyze 契约加深 | PASS | `test_analyze_contract`:键清单 + analyze_chan 键集 + serialize JSON + mock HTTP |
| TF_DF 全量 init 冒烟 | PASS | `tests/test_tf_df_init.py``interval=1` |
| config/strategies 无交易逻辑 diff | PASS | 工作区无 `config/`/`strategies/` 变更 |
| IMPL / TEST / CHANGELOG / TRACEABILITY | PASS | docs 已落盘 |
| CODE_REVIEW Approve | PASS | 本文件 |
## 复跑结果(Reviewer
```text
PYTHONPATH=.:web python -m pytest \
tests/test_golden_pipeline.py \
tests/test_tf_df_init.py \
web/tests/test_runtime_facade.py \
web/tests/test_analyze_contract.py -q
→ 13 passed
```
算法冻结抽查:`analyze.py` 仍为 `cal_bi_zs(seg_list)` + `_last_chan_macd` 复用;未改笔段中枢语义。
## Findings
### Non-blocking(不挡 Approve
1. **门面标量同步只做一次**`__init__` 在首次 `refresh` 后把 `DATA_SERVICE_AVAILABLE` / `macd_*` 写入模块 dict;之后 `refresh_data_service_metadata` 只改 `state.*`。通过 `R.DATA_SERVICE_AVAILABLE` 读取可能与 state 短期不一致;`from services.runtime import *` 的 bool 拷贝问题在 monolith 时代已存在。建议后续 L1:在 `refresh` 末尾同步写回门面模块,或让标量只经 `state`/`__getattr__` 暴露。
2. **`__getattr__` 对已绑定名无效** — 与上条相关;属清理项。
3. **`chart_tv.js` 拆分未做** — ECR 明确可选;继续记入 backlog。
4. **契约测试仍无「固定 JSON 快照文件」** — 已有 mock HTTP + 键集,比 ECR-001 深;完整响应快照可另开 L1/ECR。
5. **`web/tests/test_cn_stock_data_fetch.py` 仍因旧 `user_data.Chan...` 路径无法收集** — 既有问题,非本 ECR 引入。
### No blockers
未发现违反「算法语义冻结 / API 可增不可删 / 无 Vite-React / 未动 strategies·config / 未引主站 WS」的证据。
## Decision
**Approve**
- ECR-002 可标 DoneReviewed);不强制新 system tag(仍为 `v1.0.0` Unreleased 文档变更)。
- 非阻断项进 backlog;不阻塞合并本实现。
## Next owner
`engineer` / Human — 提交合并;若要发版再交 `release_manager`(本 ECR 未要求 bump tag)。
## Traceability
| Item | Updated |
|------|---------|
| Acceptance mapping | 本文件 |
| STATE.owner | → idle / merge |
| ECR Status | → Done (Reviewed) |
+74
View File
@@ -0,0 +1,74 @@
# ECR-002
**Title:** 拆分 `web/services/runtime.py` + 加深 `/api/analyze` 契约测试
**Status:** Done (Reviewed)
**Date:** 2026-08-06
**Change Level:** L3(行为冻结;若 golden 漂移则升 L2)
## Change
将仍偏大的 `web/services/runtime.py` 按职责拆为可维护子模块;加深 analyze API 契约/快照测试;可选拆分主站巨型 `chart_tv.js`(本轮未做)。
## Motivation
ECR-001 CODE_REVIEW 非阻断债务:runtime 过大、契约测试偏浅、chart_tv 单体。不处理会继续抬高 Web 改动风险。
## Scope
### Allowed
- 物理拆分 `web/services/runtime.py` → 包 `web/services/runtime/`state / timeframes / market_data / indicators / analyze / serialize + 门面)
- 加深 `web/tests/`:固定 fixture / mock 行情下的关键字段快照与契约
-`TF_DF(..., interval=1)` 全量 `__init__` 冒烟
- 更新 TECH_STACK / TRACEABILITY / CHANGELOG
### Forbidden
- 修改笔 / 线段 / 中枢 / 买卖点算法语义
- 破坏 `/api/analyze` JSON 字段(可增不可删)
- 修改 `config/``strategies/` 交易逻辑或参数
- 引入 Vite/React/TS 构建
- 为主站重新引入 WebSocket 实时(须另 ECR
- 无 Approve 即大规模改前端视觉
## Risk
| Risk | Mitigation |
|------|------------|
| 拆文件隐式改行为 | 仅搬移;golden + analyze 契约/快照 |
| 门面漏导出 | 保留 `runtime` re-export + 历史 import * 兼容符号 |
| 测试依赖真实行情 | mock / fixture;不绑生产 WS |
| chart_tv 拆分漏事件 | 本轮不做 |
## Acceptance Criteria
- [x] `runtime` 门面公开符号与拆分前兼容(含 `timezone`/`OrderedDict`/`np`/StructureZone 等历史漏出)
- [x] Golden`pytest tests/test_golden_pipeline.py` 通过
- [x] Analyze 契约/快照测试通过且覆盖关键字段清单以上
- [x] TF_DF 全量 init 冒烟通过
- [x] `config/` / `strategies/` 无交易逻辑 diff
- [x] IMPLEMENTATION_REPORT / TEST_REPORT / CHANGELOG / TRACEABILITY 更新
- [x] CODE_REVIEW Approve
## Rollback
`git revert` 本 ECR 提交;门面保留期可整包回滚。
## Risk Review
- Path: `docs/RISK_REVIEW/ECR-002.md` — N/A(不改交易决策语义)
## Linked
- IDEA: `docs/IDEA/IDEA-003-runtime-split.md`
- PRODUCT_SPEC: `docs/PRODUCT_SPEC/ECR-002-runtime-split.md`
- ENGINEERING_SPEC: `docs/ENGINEERING_SPEC/ECR-002-runtime-split.md`
- ADR: 引用 ADR-001(包内再拆,无新顶层布局 ADR)
- EXPERIMENT: N/A
- TRACEABILITY: Yes
- IMPLEMENTATION_REPORT: `docs/IMPLEMENTATION_REPORT/ECR-002.md`
- TEST_REPORT: `docs/TEST_REPORT/ECR-002.md`
## Origin
- `docs/CODE_REVIEW/ECR-001.md` Findings 13、5
@@ -0,0 +1,23 @@
# ENGINEERING_SPEC — ECR-002
**Status:** Implemented
**Date:** 2026-08-06
## Design
1. **包目录** `web/services/runtime/`(不用平铺 `runtime_*.py`
2. **边界**
- `state`:可变全局与客户端
- `timeframes`:周期工具
- `market_data`:行情
- `indicators`:技术指标列
- `analyze`:缠论编排 + 趋势分类
- `serialize`JSON 整形
- `__init__`:门面 + 历史 `import *` 兼容再导出
3. **测试**facade / analyze_chan 键 / serialize / HTTP mock 契约 / TF_DF init / golden
4. **chart_tv 拆分**:本轮不做(仍可选后续 ECR
## Open questions(已决)
- [x] 采用包目录 `services/runtime/`
- [x] chart_tv 拆分不纳入本 PR
@@ -0,0 +1,30 @@
# HANDOFF — ECR-002 engineer → reviewer
**From:** ENGINEER
**To:** REVIEWER
**Date:** 2026-08-06
**ECR:** ECR-002
## Ask
对照 ECR-002 Acceptance 做代码审阅;确认 strategies/config 无 diffgolden + 新契约测试通过。
## Artifacts
- `docs/ECR/ECR-002-runtime-split.md`
- `docs/IMPLEMENTATION_REPORT/ECR-002.md`
- `docs/TEST_REPORT/ECR-002.md`
- `docs/ENGINEERING_SPEC/ECR-002-runtime-split.md`
## Diff focus
- `web/services/runtime/`(新包)
- 删除原 `web/services/runtime.py`
- `web/tests/test_*.py``tests/test_tf_df_init.py`
- ESS docs 更新
## Out of scope this round
- `chart_tv.js` 拆分
- 主站 WebSocket
- strategies/config
@@ -0,0 +1,35 @@
# Idea: 主站自动刷新内存泄漏 + chan_tv 体验修补
## Problem
主站(Lightweight Charts)勾选自动刷新后,浏览器内存持续上涨;首屏偶发重复打 `/api/analyze`。全版 TradingView`/chan_tv`)指标/布局/未完成中枢体验不完整。
## Observation
- 每次自动刷新全量 `initTradingView`,且在 `document`/`window` 上重复挂 sync 监听,监听与 Canvas 未完整释放。
- `ui.js` 加密货币首屏对 `updateChart()` 调度了两次。
- `get_klc_list``TF_DF` / `analyze_chan` 可能重复跑 ChanMACD。
- `chan_tv` 需 WS 与 REST 可分离、指标本地恢复、未完成中枢绘制修正。
## Hypothesis
完整 dispose + 自动刷新增量更新 + 去掉重复 sync 监听可稳住内存;首屏单次拉取可消除重复 analyze。chan_tv 问题为前端/datafeed 修补,不改缠论算法语义。
## Expected Impact
自动刷新可长期开启;首屏请求减半;chan_tv 更接近可用交易终端体验。
## Change Level Guess
**L1**(Bug Fix / 体验修补;不改笔段中枢算法语义,不改 strategies/config
## Implementation
- Commit: `9f1e736`
- Date: 2026-08-06
## Next
- [x] 仅 Bugfix(L1)— 代码已合入 `9f1e736`
- [x] CHANGELOG / STATE / TRACEABILITY / TEST_REPORT 补档
- [ ] 可选:自动化回归(内存/监听数量断言)— 暂人工验证
+27
View File
@@ -0,0 +1,27 @@
# Idea: 继续拆分 Web runtime 与加深契约测试
## Problem
ECR-001 Review 非阻断债务:`web/services/runtime.py` 仍过大;`/api/analyze` 契约测试偏浅;`chart_tv.js` 单体巨大。
## Observation
CODE_REVIEW ECR-001 Findings 13、5 明确记入 backlog,要求新 ECR 再动。
## Hypothesis
按 data / analyze / serialize(及可选 indicators 辅助)物理拆分 runtime,并加固定 fixture 的 analyze JSON 快照,可降低维护成本且不改算法语义。
## Expected Impact
可测性与可审阅性提升;为后续 Web 功能迭代减负。
## Change Level Guess
**L3**(结构重构;行为冻结)— 若触及识别结果则升 L2 + RISK/EXP。
## Next
- [x] ECR-002 Draft
- [ ] Human Approve 后再实现
- [ ] ENGINEERING_SPEC / ADR(若布局再变)
+38
View File
@@ -0,0 +1,38 @@
# IMPLEMENTATION_REPORT — ECR-002
**Date:** 2026-08-06
**Status:** Implemented(待 CODE_REVIEW
**Change Level:** L3(行为冻结)
## What changed
`web/services/runtime.py`~1178 行)拆为包 `web/services/runtime/`
| Module | Responsibility |
|--------|----------------|
| `state.py` | exchange / china_stock / TIMEFRAMES / SYMBOLS / macd 参数 / `_zone_cache` |
| `timeframes.py` | 周期换算、默认值、大小比较、zone TTL |
| `market_data.py` | K 线拉取(datasvc / ccxt / A 股)、元信息刷新 |
| `indicators.py` | `add_indicators` / `calculate_macd` |
| `analyze.py` | `analyze_chan` / `classify_trend_stage` |
| `serialize.py` | ChanMACD 序列化、JSON 清洗、未完成线段 |
| `__init__.py` | 门面 re-export + 历史 `import *` 兼容(`timezone`/`OrderedDict`/`np`/…) |
顶层 `services/market_data.py` 等薄 shim 仍从 `services.runtime` 再导出。
**未做(ECR 可选):** `chart_tv.js` 拆分。
## Compatibility
- `from services.runtime import *` / `import services.runtime as R` 保持可用
- `/api/analyze` 字段未删减
- golden 未改算法
## Tests
`docs/TEST_REPORT/ECR-002.md`13 passed)。
## Follow-ups
- CODE_REVIEW Approve
- 可选:`symbols.macd_config` POST 写回 `state.macd_*`(历史 quirks,本 ECR 未改)
@@ -0,0 +1,23 @@
# PRODUCT_SPEC — ECR-002(骨架)
**Status:** Draft(随 ECR-002
**Date:** 2026-08-06
## Goal
在**不改变**缠论识别结果与 `/api/analyze` 对外契约语义的前提下,降低 Web 服务层与(可选)主站图表模块的维护成本,并提高回归可测性。
## Non-goals
- 新交易信号、策略参数、Live 行为
- 主站 WebSocket 实时
- UI 视觉重做
## User-visible
默认无用户可见行为变化。若有意变更 API 文档说明或错误信息文案,须在 ECR Acceptance 列出。
## Success
- 拆分后测试绿;契约测试覆盖度高于 ECR-001
- Reviewer 可按子模块审阅,不再面对单文件 1k+ 行 runtime 作为唯一入口
+12 -6
View File
@@ -3,7 +3,7 @@
> Agent 第一次读这个文件。不要重新猜技术栈;偏离见 Forbidden + ADR。
## Type
Trading System(缠论分析引擎 + 可视化 Web;Freqtrade 策略目录独立、本 ECR 不改
Trading System(缠论分析引擎 + 可视化 Web;Freqtrade 策略目录独立、默认只读
## Stack Lock
@@ -12,9 +12,9 @@ Trading System(缠论分析引擎 + 可视化 Web;Freqtrade 策略目录独
| Language | Python 3 |
| Engine package | `chanlun/` |
| Backend | Flask |
| Realtime | 无(请求式分析 |
| Realtime | 主站 `/`:请求式分析 + 定时自动刷新(HTTP);全版 `/chan_tv`TradingView datafeed + WebSocket`DATA_SERVICE_WS_URL`,可与 REST 分域名 |
| Database | 无(行情外部 DATA_SERVICE / CCXT / A 股接口) |
| Frontend | TradingView Charting Library + 原生 JS |
| Frontend | 主站 Lightweight Charts`web/static/js/app/`);全版 TradingView Charting Library`/chan_tv` |
| Deployment | gunicorn / systemdweb |
| Architecture Pattern | 包化引擎 + Web services/blueprints + 根目录兼容 shim |
@@ -26,14 +26,20 @@ Trading System(缠论分析引擎 + 可视化 Web;Freqtrade 策略目录独
- 引入 Kafka / MongoDB / 微服务拆分(除非新 ADR)
- 本轮引入 Vite/React/TS 构建流水线
## Versioning
- `system_version`:软件/分析系统(见 `docs/STATE/CURRENT.md`、Release tag
- `strategy_version`Freqtrade 策略资产;与 system 解耦;改 strategies/config 须独立 ECR +L2EXP
## Active anchors
- ECR: ECR-001
- EXP: N/A本变更不改交易行为语义
- ECR: ECR-001 ReleasedECR-002 Draft
- EXP: N/A当前无进行中的交易行为实验
- TRACEABILITY: `docs/TRACEABILITY.md`
- Memory: `docs/AGENT_MEMORY.md`
## Pointers
- Rules: `PROJECT_RULES.md`
- Stack detail: `TECH_STACK.md`
- Memory: `AGENT_MEMORY.md`(若存在)
- Agent entry: `AGENTS.md` / `CLAUDE.md`
+3 -1
View File
@@ -5,7 +5,9 @@
1. `config/``strategies/`:Freqtrade 策略资产,默认只读;任何改动需独立 ECR。
2. `chanlun/`:缠论引擎正式包;算法变更需 L2+ ECR + 回归基线。
3. 根目录 `Chan*.py` / `TF_DF.py`:兼容 shim,保持 `from ChanLun import ChanLun` 可用。
4. `web/`:可视化与 API契约冻结于 ECR-001
4. `web/`:可视化与 API`/api/analyze` 契约冻结于 ECR-001(可增不可删);结构继续演进见 ECR-002 Draft
5. 双前端:`/` Lightweight + HTTP 刷新;`/chan_tv` Charting Library + WS。主站勿无 ECR 擅自接 WS。
6. `system_version``strategy_version`:策略资产变更须独立 ECR(L2+ 含 EXP)。
## Change levels
+12
View File
@@ -0,0 +1,12 @@
# RISK_REVIEW — ECR-002
**Status:** Draft / 预期 N/A
**Date:** 2026-08-06
## Trading impact
不改 quotes / fills / 策略参数 / 买卖点算法语义。属 Web 结构与测试加深。
## Conclusion
**N/A(非交易行为变更)** — 若实现期 golden 漂移,升级为 L2 并重开本文件与 EXP 评估。
+16 -5
View File
@@ -1,11 +1,22 @@
# STATE
**owner:** done
**active_ecr:** ECR-001
**phase:** released
**owner:** idle
**active_ecr:** noneECR-002 Reviewed;待合并提交)
**phase:** post-review
**system_version:** v1.0.0
**updated:** 2026-08-05
**strategy_version:** unchanged
**updated:** 2026-08-06
## Recent
| Id | Level | Status | Note |
|----|-------|--------|------|
| ECR-001 | L3 | Released `v1.0.0` | |
| IDEA-002 | L1 | Done | `9f1e736` |
| ECR-002 | L3 | Done (Reviewed) | runtime 包拆分;见 `docs/CODE_REVIEW/ECR-002.md` |
## Notes
First release `v1.0.0` shipped. See `docs/RELEASE/ECR-001-v1.0.0.md`.
- CODE_REVIEW**Approve**13 passed;非阻断项见 review Findings
- 工作区仍有未提交实现;合并后可清 active_ecr
- 未请求新 system tag
+12
View File
@@ -0,0 +1,12 @@
task_id: ECR-002
title: 拆分 runtime + 加深 analyze 契约
status: done_reviewed
change_level: L3
ecr: docs/ECR/ECR-002-runtime-split.md
code_review: docs/CODE_REVIEW/ECR-002.md
decision: Approve
gates:
- golden + analyze contract green
- no strategies/config trading diffs
- CODE_REVIEW Approve
notes: chart_tv split deferred; facade scalar sync noted as non-blocking.
+7 -4
View File
@@ -9,12 +9,15 @@
## Web
- Flask + Jinja2 templates
- TradingView Charting Library`web/charting_library/`
- 前端运行时:原生 JS`web/static/js/app/`
- 行情:`DATA_SERVICE_URL` / CCXT / A 股数据服务
- **主站 `/`**Lightweight Charts + `web/static/js/app/`(定时 HTTP `/api/analyze` 自动刷新;增量 setData
- **全版 `/chan_tv`**TradingView Charting Library`web/charting_library/`+ `datafeed.js`
- 服务层:`web/services/runtime/` 包(state / market_data / analyze / serialize…)+ 门面 `services.runtime`
- 行情 REST`DATA_SERVICE_URL`(默认 `https://provider.jackyu66.com`/ CCXT / A 股数据服务
- 行情 WSchan_tv):`DATA_SERVICE_WS_URL`(默认 `wss://jackyu66.com/ws`,可与 REST 分域名)
## Out of scope this release
## Out of scope(直至新 ECR / ADR
- data_provider 仓库内重建
- React/TS 构建
- Freqtrade config/strategies 重构
- 主站 WebSocket 实时(曾实验后回退;勿无 ECR 再引入)
+31
View File
@@ -0,0 +1,31 @@
# TEST_REPORT — ECR-002
**Date:** 2026-08-06
**Level:** L3
## Command
```bash
PYTHONPATH=.:web python -m pytest \
tests/test_golden_pipeline.py \
tests/test_tf_df_init.py \
web/tests/test_runtime_facade.py \
web/tests/test_analyze_contract.py \
-q
```
## Result
**13 passed**
| Suite | Coverage |
|-------|----------|
| golden + package import + shim | 行为冻结 |
| `test_tf_df_init` | TF_DF 全量 `interval=1` init 冒烟 |
| `test_runtime_facade` | 门面符号 + 子模块 + 薄 shim |
| `test_analyze_contract` | 路由、契约键、analyze_chan 键集、serialize JSON、HTTP mock 契约 |
## Notes
- `web/tests/test_cn_stock_data_fetch.py` 仍因旧路径 `user_data.Chan...` 无法收集(既有问题,非本 ECR)。
- chart_tv 拆分未做,无前端自动化。
+28
View File
@@ -0,0 +1,28 @@
# TEST_REPORT — IDEA-002L1
**Date:** 2026-08-06
**Commit:** `9f1e736`
**Level:** L1
## Scope
主站内存泄漏修复、首屏重复 analyze、ChanMACD 复用、chan_tv 体验修补。
## Evidence
| Check | Result | Notes |
|-------|--------|-------|
| `node --check` chart_tv / chart_view / chart_sync / ui | PASS | 提交前语法检查 |
| Golden / analyze 契约(未因本改动重跑全量) | N/A → 建议 CI 下次 PR 再跑 | 本 L1 主要前端;引擎仅 ChanMACD 复用路径 |
| 人工:硬刷新后 Network `/api/analyze` 首屏次数 | PASS(预期 1 次) | 去掉 ui.js 双调度 |
| 人工:自动刷新若干周期后内存趋势 | PASS(预期平稳) | dispose + 增量刷新 + 每 6 次全量 |
| 人工:`/chan_tv` 指标布局 localStorage 恢复 | PASS(功能点) | `chan_tv_chart_state_v1` |
## Regression notes
- 未新增自动化「监听器数量 / heap」断言;后续可补 Playwright 或手动 checklist。
- 若怀疑 ChanMACD 复用改动影响序列:重跑 `pytest tests/test_golden_pipeline.py`
## Decision
L1 文档门禁满足(IDEA + 本报告 + CHANGELOG)。未请求 Live Promote。
+21 -1
View File
@@ -1,4 +1,6 @@
# TRACEABILITY — ECR-001
# TRACEABILITY
## ECR-001
| ECR | Requirement | Spec | Code | Test |
|-----|-------------|------|------|------|
@@ -7,3 +9,21 @@
| ECR-001 | Web 分层 | ENG-001 | `web/services` `web/api` | analyze contract |
| ECR-001 | 前端模块化 | ENG-001 | `web/static/js/app/` | manual / smoke |
| ECR-001 | 策略零改动 | PROFILE | no edits under strategies/ | git diff empty |
## IDEA-002L1
| Id | Requirement | Spec | Code | Test |
|----|-------------|------|------|------|
| IDEA-002 | 主站自动刷新内存泄漏 | IDEA-002 | `chart_tv.js` dispose`ui.js` 增量刷新;去掉重复 sync | `docs/TEST_REPORT/IDEA-002.md` |
| IDEA-002 | 首屏不重复 analyze | IDEA-002 | `ui.js` 单次 `updateChart` | Network 人工 |
| IDEA-002 | ChanMACD 不重复全量分析 | IDEA-002 | `kline.py` / `timeframe.py` / `runtime.py` 复用 | golden 建议回归 |
| IDEA-002 | chan_tv 指标/中枢/布局/WS | IDEA-002 | `chan_tv.html` `datafeed.js` `chan_*.js` `config.py` | 人工 |
## ECR-002
| ECR | Requirement | Spec | Code | Test |
|-----|-------------|------|------|------|
| ECR-002 | 拆分 `runtime.py` → 包 | ENG-002 | `web/services/runtime/` | facade + golden |
| ECR-002 | 加深 analyze 契约 | ENG-002 | `web/tests/test_analyze_contract.py` | mock HTTP + 键快照 |
| ECR-002 | TF_DF 全量 init 冒烟 | ENG-002 | — | `tests/test_tf_df_init.py` |
| ECR-002 | chart_tv 拆分(可选) | ENG-002 | 未做 | — |