# 股票估值端到端协调层 V2 编码方案 V002 创建人员:`dev.developer.project.secondary` / `infodev-2` 文件职责:在不修改、不复制 `ana-dev` V1 计算内核的前提下,冻结 project 级股票估值端到端协调层的接口、证据、缓存、失败、报告、性能和验收合同。 关联事项:`DEV-ANA-STOCK-VALUATION-PIPELINE-V2-20260801-001`。 上游依据:用户关于日常开发员接手 V2 的原生任务委派;`dev-doc/ana-doc/开发方案/CODE-DESIGN-ANA-STOCK-VALUATION-PIPELINE-V2-V001.md`;股票价格合理性评估操作手册;V1 流水线与铖昌科技既有结果。 管理规范/模板:`../../../common/dev-doc/编码规范.md`;`../../编码规范.md`;`../../开发审计规范.md`。 引用文件:`../开发工作区说明.md`;`../../../dev/ana-dev/stock_valuation_pipeline/README.md`;`../../../outputs/20260730_stock_valuation_guide/股票价格合理性评估操作手册_v1.0.md`。 记录方式:重型编码方案;`dev.reviewer.project` 在 `dev-doc/开发审计报告.md` 给出方案 PASS 前不得实施重型代码。 ## 1. 接手、重分类与方案继承 1. 原 V001 已冻结业务目标,但实现落点为 `dev/ana-dev/stock_valuation_pipeline/`,负责人和审核员分别是 `dev.developer.ana.cai`、`dev.reviewer.ana.cai`;后者会话失效,未产生独立 PASS。 2. 本次由项目日常开发池明确将事项交给空闲的 `dev.developer.project.secondary`。合法实现落点改为 `dev/project-dev/stock_valuation_pipeline_v2/`,测试落点为 `dev/project-dev/test/stock_valuation_pipeline_v2/`,审核员改为共享 `dev.reviewer.project`。 3. V001 的业务目标、状态、四类来源、性能指标和验收底线继续作为输入;V002 取代 V001 成为本次实现方案。V001 保留为历史证据,不改写、不冒充已审核方案。 4. `dev/ana-dev/stock_valuation_pipeline/` 及其测试、Schema、注册表和 README 在本事项中全部只读。V2 通过稳定 Python 入口调用 V1,不复制公式、校验或报告计算逻辑。 5. 如后续发现必须修改 V1 公共合同,立即停止相关实现并向 `project.admin` 申请一事项范围调整;未获调整前不得写 `ana-dev`。 ## 2. 问题、目标与非目标 ### 2.1 问题 V1 只能在人工准备好 `valuation_snapshot.json` 后执行毫秒级计算。用户从提出 ticker/as-of 请求到收到完整报告的主要时间仍消耗在资料取得、来源校验、快照构建、报告扩写和人工终检,现有引擎耗时不能代表总墙钟。 ### 2.2 目标 1. 新增 ticker + as-of 端到端入口,同时保留 V1 `--input` 兼容入口。 2. 并发取得公开行情、法定公告索引、结构化财务和机构预测,并在预算内结束或降级。 3. 保存原始响应哈希、请求索引、来源元数据、A1 回链、公司基线和增量水位。 4. 有判断覆盖层时构造合法 V1 快照并调用 V1 计算核心;无覆盖层时不伪造情景或方向性结论。 5. 固定生成 16 节 Markdown、自动 QA、原子提交、运行 manifest 和从用户任务起点开始的总墙钟。 ### 2.3 非目标 1. 不连接付费数据库,不绕过登录、验证码、反爬或访问控制。 2. 不修改 V1 计算公式、Schema、注册表、缓存或报告实现。 3. 不复制 V1 核心到 project 目录,不建立第二套估值公式实现。 4. 不自动推断未披露客户、订单、型号或敏感军工事实。 5. 不输出交易指令、收益承诺或自动批准的投资结论。 6. 不引入 GUI、常驻服务、数据库、定时任务或第三方 Python 依赖。 ## 3. 代码、测试与文档落点 ```text dev/project-dev/ stock_valuation_pipeline_v2/ __init__.py __main__.py cli.py telemetry.py http_client.py cache.py providers.py acquisition.py snapshot_builder.py judgment.py v1_bridge.py full_report.py report_qa.py workflow.py provider_registry.json judgment_overlay.schema.json README.md test/stock_valuation_pipeline_v2/ test_*.py fixtures/chengchang_20260801/ dev-doc/project-doc/ 股票估值端到端协调层V2.md 开发方案/CODE-DESIGN-PROJECT-INFO-STOCK-VALUATION-PIPELINE-V2-V002.md ``` 现有操作手册位于角色常规写入范围之外。实现和审核期间先在 project 文档中维护 V2 使用说明;正式修改原操作手册前需由 `project.admin` 明确授予该单文件写入范围,或由其根据本事项证据代为同步。不得用“用户委派”静默扩大目录权限。 ## 4. CLI 与兼容合同 ### 4.1 V1 兼容入口 ```powershell python -m stock_valuation_pipeline_v2 ` --input ` --output-dir ` [--force] ``` 该模式只做参数校验和 V1 桥接,调用 V1 `run_pipeline`,保留 `GENERATED/REUSED`、退出码和三件套产物语义。不得改变传入快照或追加 V2 结论。 ### 4.2 ticker/as-of 入口 ```powershell python -m stock_valuation_pipeline_v2 ` --ticker 001270.SZ ` --as-of 2026-08-01 ` --output-dir ` --cache-dir ` [--judgment ] ` [--fixture-dir ] ` [--task-start ] ` [--force] ``` 硬合同: 1. `--input` 与 `--ticker` 互斥;ticker 模式必须给 as-of、output-dir、cache-dir。 2. ticker 规范化为 `NNNNNN.SZ/SH/BJ`;无法确定市场时在网络前失败。 3. as-of 不得晚于当前本地日期;所有来源按发布日期和数据日期双重过滤。 4. fixture 模式禁止打开网络;夹具缺失是显式合同错误。 5. stdout 只输出结构化终态摘要,进度写 stderr 和 `runtime.log`。 ## 5. 两阶段数据与判断合同 V1 的 `valuation.scenarios` 必须非空且必须包含唯一基准情景。因此 V2 不得在无 judgment 时捏造机械场景来强行调用 V1。 ### 5.1 无 judgment 1. 采集、证据、字段级来源、公司基线和数据快照照常完成。 2. 生成 `data_snapshot.json`、`snapshot_build_report.json`、16 节数据就绪报告、QA、gap、遥测和 manifest。 3. 情景、结论、触发器等判断章节明确写 `GAP:需要人工判断覆盖层`,不得出现方向性价格结论。 4. 终态固定为 `DATA_READY_NEEDS_JUDGMENT`;不生成伪 V1 `valuation_snapshot.json` 或 `valuation_results.json`。 ### 5.2 有 judgment 1. `judgment_overlay.schema.json` 仅允许业务摘要、归一化调整、三情景、主模型、交叉验证、风险、上下调触发器、持有期和结论边界。 2. 覆盖层不得写价格、股本、法定利润、财务期间、来源日期或 A1 文档身份;出现禁写字段立即 `E_JUDGMENT_CONFLICT`。 3. 覆盖层与数据快照合并后生成合法 V1 `valuation_snapshot.json`,通过 `v1_bridge.py` 调用 V1 `load_snapshot` 和 `compute_valuation`。 4. V1 计算结果是所有数值章节的唯一来源;V2 报告模板不得重新计算 PE、PB、PS、情景、反向 PE 或持有期结果。 ## 6. 统一提供者合同 四类适配器统一返回: ```json { "provider_id": "market", "adapter_version": "1.0.0", "status": "OK|GAP|BLOCKED", "fetched_at": "ISO-8601", "as_of_date": "YYYY-MM-DD", "records": [], "sources": [], "gaps": [], "warnings": [], "raw_artifact_hashes": [] } ``` ### 6.1 法定公告索引 取得交易所或巨潮公开公告索引,登记证券代码、标题、公告日期、报告期、公告 ID、原文 URL、修订状态和支持字段。财务核心字段必须能回链至 A1 原文;公告索引不负责凭叙事直接填利润。 ### 6.2 行情 取得不晚于 as-of 的最近交易日收盘价、价格时间、总股本和平台市值。自动检查 `价格×股本` 与平台市值差异;当前股本晚于历史 as-of 时不得回填历史快照。 ### 6.3 结构化财务 取得最近完整年度、本期累计、上年同期累计、资产负债和现金流字段;每个记录带报告期、公告日期、单位、币种和 A1 公告 ID。结构化字段无法回链 A1 时为 gap;与 A1 明示数值超容差时阻断受影响字段。 ### 6.4 机构预测 保存汇总机构数和可见明细两套记录。汇总 4 家、明细 3 家只形成一个 `W_FORECAST_COVERAGE` gap;最多查询两个登记来源,不为未知第四家无限搜索。明细日期晚于 as-of 的记录排除。 ## 7. HTTP、并发与网络预算 1. 仅允许 `provider_registry.json` 登记的 HTTPS 域名;巨潮如需 HTTP 回退必须在注册表明确标识并只用于公开公告查询。 2. 连接超时 8 秒、单请求总读取超时 20 秒、单响应上限 20 MiB。 3. 仅对超时、连接重置和 5xx 最多重试 2 次;4xx、解析错误和字段变化不盲重试。 4. `ThreadPoolExecutor(max_workers=4)` 并发运行四类适配器。单个失败不取消其他来源,异常统一转 gap 或 blocked。 5. 机械网络阶段总预算默认 90 秒;到达预算后取消未开始任务,等待中的请求依自身超时结束,不再发起新搜索。 6. 进度日志记录 provider、开始、缓存命中、请求次数、完成、失败和耗时。 ## 8. 可信信源停止规则与 as-of 安全 同一数字满足以下全部条件即停止搜索: 1. 已取得 A1 原文或与 A1 公告 ID 可核对的结构化记录; 2. 公司、报告期、币种、单位和口径明确; 3. as-of 之前没有后续修正或替代版本; 4. 报表勾稽或 `价格×股本`、`EPS×股本` 等数量关系无异常; 5. 数量级合理且足以支持估值用途。 任何 `publish_date > as_of`、`data_date > as_of`、历史 as-of 使用当前不可历史化字段的行为均为 `E_ASOF_VIOLATION`,不得仅警告后继续。 ## 9. 内容寻址缓存与公司增量基线 ```text / blobs/.bin requests//.json companies//baseline.json companies//source_index.json ``` 请求索引至少包含规范化请求、provider、ticker、as-of、请求/响应时间、状态、内容类型、字节数、SHA-256、适配器版本、来源发布日期和 `complete=true`。 复用必须同时通过请求指纹、blob 哈希、适配器版本、as-of 安全和完成标记;任一失败只废弃逻辑索引并重取,不删除其他 blob。fixture 响应也走同一缓存路径,以便机械验证缓存合同。 公司基线只在核心采集完成且基线自身哈希正确后原子提交。新 as-of 只刷新价格、最新公告状态、机构预测、股本、现金债务和公司行动;未重述历史报告按内容哈希复用。 ## 10. 快照构建、字段来源与缺口 1. `snapshot_builder.py` 从统一提供者结果建立唯一数据主记录,不直接读取网页模板字段。 2. 金额统一为元、股本为股、价格为元/股;原始值和原始单位保留在证据包。 3. TTM 输入固定为最近完整年度、本期累计、上年同期累计;由 V1 负责正式计算。 4. `snapshot_build_report.json` 对每个 V1 字段记录来源 provider、source_id、raw_hash、转换、as-of 判断和状态。 5. 核心行情、股本、TTM 三期利润或资产负债核心字段缺失时 `BLOCKED_CORE_INPUT`;机构、辅助说明或单一非核心来源缺失允许 `COMPLETE_WITH_GAPS`。 6. gap 必须包含 gap_id、provider、字段、原因、影响、是否阻断、已用预算和建议人工补充,不得用 0、空字符串或测试值掩盖。 ## 11. 16 节 Markdown 报告 固定章节顺序: 1. 结论摘要;2. 市场和资本结构;3. 信源优先级;4. 业务及利润来源;5. 历史盈利;6. TTM 与归一化;7. 机构预期;8. 利润质量与现金流;9. 模型选择;10. 三情景;11. 反向隐含条件;12. 交叉验证;13. 持有期测试;14. 风险与触发器;15. 复评清单;16. 数据局限和复算摘要。 所有数值表格读取数据主记录或 V1 结果对象。无 judgment 的判断章节写明确 GAP 和需要的覆盖层字段,不得出现 TODO、TBD、待计算、默认倍数、默认方向性评级或伪价格区间。 ## 12. 自动 QA 硬 gate: 1. 16 个标题齐全、顺序唯一;Markdown 围栏成对;表格列数一致。 2. 无 TODO/TBD/待计算/NaN/Infinity;本地产物链接存在。 3. 报告关键数字与统一数据或 `valuation_results.json` 一致。 4. 所有核心字段有来源,A1 回链存在,来源和数据日期不晚于 as-of。 5. judgment 不得改写受保护字段;无 judgment 不得出现方向性估值结论。 6. 不包含“买入、卖出、加仓、减仓”等交易指令或收益承诺。 7. manifest 声明的每个正式产物哈希和字节数可复算。 外部 URL 在线可达性是警告,不因临时网络抖动改写已经生成的正式结果。 ## 13. 状态、错误与降级 | 终态/错误 | 处理 | |---|---| | `COMPLETE` | judgment、V1 计算、报告和 QA 全部完成 | | `COMPLETE_WITH_GAPS` | 非核心数据缺口已披露,硬 gate 通过 | | `DATA_READY_NEEDS_JUDGMENT` | 数据和证据就绪,无方向性结论 | | `BLOCKED_CORE_INPUT` | 价格、股本、核心财务或 A1 回链不足 | | `E_INPUT_CONTRACT` | 网络前 fail-fast | | `E_ASOF_VIOLATION` | 阻断并保留失败证据 | | `E_SOURCE_CONFLICT` | 阻断受影响核心字段 | | `E_JUDGMENT_CONFLICT` | 覆盖层越权,阻断 | | `FAILED` | 内部异常或提交失败 | 非核心提供者失败转换为一个有预算记录的 gap;不得 silent fallback,不得无限换站搜索。 ## 14. 暂存、原子提交与失败证据 1. 所有本次正式产物先写输出目录同级的唯一暂存目录。 2. 每个 JSON 先写同目录临时文件、flush 后原子 replace;manifest 最后生成并含 `complete=true`。 3. QA 全部通过后,暂存目录以一次 rename 提交到尚不存在的正式输出目录。 4. 输出已存在时默认拒绝;`--force` 先形成完整新目录,再以备份交换,失败时恢复旧目录。 5. 失败时暂存目录改名为 `.failed-`,只含 `failure.json`、runtime.log 和已形成的诊断产物;不得存在 COMPLETE manifest。 6. 网络原始缓存可保留,但只有哈希、版本和完成标记都正确的索引才能复用。 ## 15. 遥测与性能 `runtime_metrics.json` 必须包含:run_id、task_start、process_start、commit_ready_at、每阶段 started_at/finished_at/elapsed_seconds/status、provider 请求/缓存命中计数、`task_wall_seconds` 和 `process_wall_seconds`。 性能验收: 1. 铖昌 fixture 冷运行 `<5 s`;相同缓存复跑 `<2 s`。 2. 真实网络机械阶段目标 `<90 s`;外站异常也必须在预算内结束并形成 gap。 3. V1 原 10 项测试全部通过;V1 `--input` 桥接输出关键结果与直接调用一致。 4. 性能只比较同机、同夹具、同输出模式;不得用 V1 毫秒级计算时间冒充完整任务耗时。 ## 16. 验收分层 ### 16.1 L0 全包 py_compile/import、JSON Schema/注册表解析、V1 10/10 回归。 ### 16.2 L1 覆盖 HTTP 超时/4xx/5xx/超大响应、fixture 禁网、缓存哈希篡改/版本变化/未完成标记/as-of 不安全、判断层禁写字段、报告结构和原子写。 ### 16.3 L2 铖昌 fixture 1. ticker/as-of 单命令生成全部适用产物;网络访问为 0。 2. 有 judgment 时,市值、TTM 收入、TTM 归母、TTM 扣非、PB、PS、情景、反向 PE 和持有期关键数值与既有 fixture 一致。 3. 无 judgment 时为 `DATA_READY_NEEDS_JUDGMENT`,不生成方向性价格区间。 4. 汇总 4 家、明细 3 家只出现一个 forecast coverage gap。 5. 冷运行 `<5 s`、缓存 `<2 s`。 ### 16.4 L3 失败与回归 未来来源阻断;A1 与结构化财务冲突阻断;缓存篡改重取;无预测允许 gap;输出冲突、强制替换失败和中断不留下伪 COMPLETE;V1 `--input` 直接与桥接结果一致。 ### 16.5 L4 真实网络 smoke 使用 001270.SZ 或另一只深市股票受控运行一次,核对请求索引、官方公告链接、价格日期、股本、市值、财务期间、机构日期、A1 回链和 90 秒预算。第二次运行证明历史 blob/公司基线复用;真实网络缺口如实记录,不把临时站点故障升级成伪成功。 ## 17. 高风险点与控制 1. V1 双实现:只允许 `v1_bridge.py` 解析并调用既有公共函数,测试比较直接与桥接结果。 2. 无判断伪结论:无覆盖层不构造 V1 valuation 分组,不生成方向性结论。 3. 未来信息:provider、builder、QA 三层检查 publish/data/as-of。 4. 接口缩放变化:注册表版本化、原始响应归档、数量级和市值勾稽。 5. 缓存误复用:请求、哈希、版本、as-of、完成标记联合门禁。 6. 汇总/明细差异无限搜索:两个来源上限和单 gap 合同。 7. 半成品冒充完成:暂存目录、manifest-last、目录级原子提交。 8. 角色越权:实现和正式文档只写 project target;V1 与原操作手册分别保持只读,直到项目管理员明确调整单事项范围。 ## 18. 审核门禁 本方案状态为 `PENDING_DEV_REVIEWER_PROJECT_DESIGN_REVIEW`。只有 `dev.reviewer.project` 在 `dev-doc/开发审计报告.md` 给出明确 `PASS` 后,才能创建 V2 代码、测试和 fixture。开发者不自审。