# 股票估值端到端协调层 V2 创建人员:`dev.developer.project.secondary / infodev-2` 文件职责:说明 project 级股票估值 V2 协调层的入口、终态、产物、复算和边界。 管理规范/方案:`开发方案/CODE-DESIGN-PROJECT-INFO-STOCK-VALUATION-PIPELINE-V2-V003.md` 至 `V007.md`。 代码入口:`dev/project-dev/stock_valuation_pipeline_v2/` 测试入口:`dev/project-dev/test/stock_valuation_pipeline_v2/test_pipeline_v2.py` ## 1. 用途和边界 V2 接受 `ticker + as-of`,并发取得公告身份、行情、法定财务和机构预测,执行 as-of 检查、内容寻址缓存、公司增量基线、字段级来源回链、自动 QA 和固定 16 节 Markdown 报告。估值计算只桥接只读的 V1 `dev/ana-dev/stock_valuation_pipeline` 公共接口,不复制公式、校验或 V1 报告实现。 工具输出用于研究、复算和数据准备,不构成交易指令、收益承诺或自动投资决策。禁止把 `as-of` 之后发布或形成的数据带入本次计算。 ## 2. 运行环境 - Python 3;协调层只使用 Python 标准库。 - 从项目根目录运行,并把 `dev/project-dev` 加入 `PYTHONPATH`。 - 公开网络 provider 当前限于 registry 中登记的巨潮资讯和东方财富 HTTPS 端点;未知 host 在 transport 前拒绝。 ```powershell $env:PYTHONPATH="dev/project-dev" python -m stock_valuation_pipeline_v2 --help ``` ## 3. ticker + as-of 入口 ```powershell $env:PYTHONPATH="dev/project-dev" python -m stock_valuation_pipeline_v2 ` --ticker 001270.SZ ` --as-of 2026-08-01 ` --cache-dir dev/tmp/valuation-v2/cache ` --output-dir dev/tmp/valuation-v2/out ``` `--task-start` 接受带时区且不晚于进程启动时刻的实际用户任务起点,用来区分: - `process_wall_seconds`:本次进程从启动到原子提交完成; - `task_wall_seconds`:用户任务起点到原子提交完成。 若不传 `--task-start`,任务起点采用本次进程起点。已有正式输出目录会在任何缓存或网络动作前拒绝;只有显式 `--force` 才允许走可回滚替换状态机。 ## 4. 最小人工判断覆盖层 没有 `--judgment` 时,机械阶段成功终态固定为 `DATA_READY_NEEDS_JUDGMENT`,不会生成 `valuation_snapshot.json`、`valuation_results.json`,也不会在报告中伪造估值方向、价格区间或结论。 ```powershell python -m stock_valuation_pipeline_v2 ` --ticker 001270.SZ ` --as-of 2026-08-01 ` --judgment dev/project-dev/test/stock_valuation_pipeline_v2/fixtures/chengchang_20260801/judgment_overlay.json ` --cache-dir dev/tmp/valuation-v2/cache ` --output-dir dev/tmp/valuation-v2/out-with-judgment ``` 覆盖层只允许提供分析文字、归一化调整、估值情景和持有期假设。价格、股本、法定财务、日期、A1 身份和来源回链属于受保护字段,覆盖即输入错误。 ## 5. V1 兼容入口 ```powershell $env:PYTHONPATH="dev/project-dev" python -m stock_valuation_pipeline_v2 ` --input valuation_snapshot.json ` --output-dir generated ``` 此入口校验 V1 模块、registry 和函数签名指纹,再调用 V1 CLI 合同,保留 V1 的退出码 `0/2/3`、三件套产物和 `GENERATED/REUSED` 语义。合同漂移时 fail-fast,不退化为第二套计算实现。 ## 6. 终态和退出码 | 终态 | ticker 模式退出码 | 含义 | |---|---:|---| | `COMPLETE` | 0 | 数据、judgment、估值与 QA 全部完成且无 gap | | `COMPLETE_WITH_GAPS` | 0 | 完成估值,存在预算内、非阻断 gap | | `DATA_READY_NEEDS_JUDGMENT` | 0 | 机械数据与 QA 完成,等待人工判断 | | `INPUT_ERROR` | 2 | 参数、task-start 或 judgment 合同错误;无正式包 | | `BLOCKED` | 4 | 核心数据、as-of、A1 或 schema 不满足;只保留失败包 | | `FAILED` | 5 | 非业务阻断的运行时失败;只保留失败包 | 标准输出始终是单个 JSON 对象。包括 argparse 参数错误在内,ticker 模式都不把非规范错误写到 stdout 之外;成功对象包含正式目录、manifest 和外部 commit receipt 的路径、bytes、SHA-256,以及两种墙钟;失败字段统一使用 JSON `null`,不使用空串冒充缺失值。 ## 7. 正式产物 成功正式目录固定包含: - `data_snapshot.json` - `provider_results.json` - `snapshot_build_report.json` - `source_evidence.json` - `gaps.json` - `report.md` - `qa_report.json` - `runtime_metrics.json` - `runtime.log` - `manifest.json`(目录内最后写入) 有 judgment 时再包含 `valuation_snapshot.json` 和 `valuation_results.json`。同级外部 `.commit-receipt.json` 使用 schema 2,只写一次并绑定 run、终态、正式目录、manifest 指纹、`commit_ready_at` 和 `receipt_write_started_at`;它有意不写自指的“最终写后墙钟”。receipt 原子写入、重新读取、复算 hash/bytes、校验并尝试清理备份之后,ticker stdout 的 `terminal_at/task_wall_seconds/process_wall_seconds` 才是最终墙钟权威。包内 runtime 仍冻结在 `commit_ready`,不会为补写墙钟而破坏 manifest。 `report.md` 的 16 节顺序固定为:结论摘要、市场和资本结构、信源优先级、业务及利润来源、历史盈利、TTM 与归一化、机构预期、利润质量与现金流、模型选择、三情景、反向隐含条件、交叉验证、持有期测试、风险与触发器、复评清单、数据局限和复算摘要。 `snapshot_build_report.json` 保存每个核心值的 `field -> source_id -> A1 -> raw_hash` 机器可读回链;法定财务必须绑定到相同期间的年度/季度 A1 公告。上年同期值必须来自本期 A1 同一响应中的明确比较列,并记录 `same_response_comparative_row`、本期/比较期和共享发布日期,不能把独立 2025 行挂到 2026 Q1 A1 名下。自动 QA 不只检查标题,还检查 16 节唯一顺序、Markdown 围栏/表格/本地链接、字段回链、raw field/hash、A1 支持范围与期间、比较关系、受保护字段、V1 数值、as-of 和确定性重渲染;任一失败都不能提交正式包。 ## 8. 信源、停止和 as-of - A1 公告身份:巨潮公告索引;截止时刻按 Asia/Shanghai 的 `as-of` 日末构造,核心财务必须能回链至不晚于 `as-of` 发布的法定年度/季度报告。 - 行情与股本:东方财富历史 K 线和行情接口;K 线查询窗口为 `as-of - 14` 个自然日至 `as-of`,过滤未来行后按 `f51` 取最大日期。实时行情的 `f124` 必须证明与该交易日一致,不能把当前股本/市值改标成历史日期;历史股本只有同 as-of 的 FRESH 语义基线或可验证实时日期才能使用,否则核心阻断。 - 结构化财务:东方财富利润表、资产负债表、现金流量表及主要指标;资产负债表完整键/alias 规则不满足即阻断。 - 机构预测:固定汇总和明细端点;只接受响应中的真实 `REPORT_DATE/UPDATE_DATE`,不以请求 `as-of` 伪造发布日期或期间。汇总 4 家、明细 3 家只形成一个 `W_FORECAST_COVERAGE` gap,不进行无界搜索。 所有请求共享唯一 90 秒单调 task deadline。请求、2xx 与 4xx/5xx 响应体读取、重试和退避均裁剪到剩余预算;错误体也使用分块、剩余 socket timeout 和可取消读取,不会在 HTTPError 分支绕过截止时间。四个 worker 截止后不创建新请求或写缓存/基线;协调层最多再等待 1 秒让受控传输协作返回。非核心缺口按 gap 降级,核心缺口阻断。 ## 9. 缓存和公司基线 请求 fingerprint 对规范化后的 provider、method、精确 endpoint、保序重复 query、headers、form/JSON body、adapter 版本和 as-of 计算。registry 同时限制 host/path/method、精确 query/body 键和值、request/response content-type 与逐 provider 响应上限;重定向、路径/query/reportName 变体在 transport 前拒绝。HTTP 成功响应先以 `PENDING_PARSE` 写原始归档,只有 adapter 完成 schema/as-of 解析后才提升为可复用逻辑索引;4xx/5xx、空响应、字段漂移和未确认响应不会永久命中。 公司基线按 `stock_identity/announcement_index/market_close/shares_market_cap/finance_main/finance_income/finance_balance/finance_cashflow/forecast_summary/forecast_detail` 逐类保存 provider/fingerprint、schema/version、as-of、TTL、水位、语义状态、来源 raw hash 和 data hash。每类在固定进程起点判为 `FRESH/STALE/MISSING`:FRESH 直接从其内容寻址 blob 装载,只有目标 stale/missing 种类会运输;核心刷新失败则整次阻断且不推进 `current.json`,非核心按 gap 降级;STALE 不进入正式值。基线 envelope/data hash 与逐 data-kind blob 完整性分开校验:单个 blob 缺失或被篡改只把对应种类判为 STALE,其余健康种类保持 FRESH;相同 digest 路径若实物哈希错误,刷新时原子重写并写后复验。缓存层把 repair 写失败或写后复验失败显式标为完整性失败;任一 kind 出现该信号,或十类条目/实物不完整,workflow 都跳过 company baseline/current 提交。核心种类仍阻断,非核心 forecast 可保留带 gap 的正式输出,但不得新建、替换或归档活动基线,也不得提升目标 reusable。成功增量合并后,同一 as-of 的上一活动基线移入 `history/`,原始 blob 继续保留,`baselines/` 只留下新活动世代,避免旧 stale 候选因 hash 排序再次胜出。活动候选选择仍严格按最大 `baseline_as_of`、最大规范化 watermark、ASCII 最大的小写 `data_hash`;较新的未来基线不能污染旧 as-of 回跑。`current.json` 在 ticker 级进程/系统锁内重新读取并原子更新,避免并发 TOCTOU。所有 blob、索引、基线和正式输出均使用临时文件加原子替换。 ## 10. 离线 fixture 与复算 ```powershell $env:PYTHONPATH="dev/project-dev" python -m stock_valuation_pipeline_v2 ` --ticker 001270.SZ ` --as-of 2026-08-01 ` --fixture-dir dev/project-dev/test/stock_valuation_pipeline_v2/fixtures/chengchang_20260801 ` --cache-dir dev/tmp/valuation-v2-fixture/cache ` --output-dir dev/tmp/valuation-v2-fixture/out ``` fixture 模式禁止真实 transport,只读取 `fixture_manifest.json` 登记的响应,可用于冷/热缓存、负响应、schema 漂移、未来信息、原子提交和 V1 数值一致性回归。 提交前以词法绝对路径逐级 `lstat` 检查文件、目录、符号链接和 Windows reparse point,不先跟随链接解析。`--force` 只有在新目录和外部 receipt 都耐久写入后才宣告成功;真实提交失败恢复旧目录/receipt并保留双异常证据,备份清理失败则保留新成功和备份、只发 warning,不把已成功的新真值回滚。 ## 11. 已知限制 - 当前只实现首期 A 股公开 provider registry,未实现 GUI、API 服务、数据库或批处理。 - 未接入付费、登录态或绕过访问控制的数据源;provider 页面变更会通过 schema drift 阻断或 gap 暴露。 - 机构明细可能受公开页面结构变化影响;系统不会为补齐明细进行无界查找。 - 首期公开行情接口可能不给出可验证的历史股本时间戳(例如 `f124=0`);此时真实历史 as-of 会诚实 `BLOCKED/E_CORE_INPUT`,不会用当前股本冒充历史股本。可在未来经独立方案审核后增加历史股本信源,但当前实现不会静默扩 provider。 - `DATA_READY_NEEDS_JUDGMENT` 只是数据准备完成,不应被解释为方向性估值结论。