edit | blame | history | raw

股票估值端到端协调层 V2

创建人员:dev.developer.project.secondary / infodev-2
文件职责:说明 project 级股票估值 V2 协调层的入口、终态、产物、复算和边界。
管理规范/方案:开发方案/CODE-DESIGN-PROJECT-INFO-STOCK-VALUATION-PIPELINE-V2-V003.mdV007.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 前拒绝。
$env:PYTHONPATH="dev/project-dev"
python -m stock_valuation_pipeline_v2 --help

3. ticker + as-of 入口

$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.jsonvaluation_results.json,也不会在报告中伪造估值方向、价格区间或结论。

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 兼容入口

$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.jsonvaluation_results.json。同级外部 <output>.commit-receipt.json 使用 schema 2,只写一次并绑定 run、终态、正式目录、manifest 指纹、commit_ready_atreceipt_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 与复算

$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 只是数据准备完成,不应被解释为方向性估值结论。