# 股票估值每日台账业务需求 v1.0 创建人员:`case_analysis.analyst.valuation` 文件职责:把已有股票估值结果结构化入库,并用每日完整交易日收盘价持续生成当日估值判定。 管理规范/模板:`../../../common/pro-doc/需求规范.md`;`../../项目规范.md`;`../案例分析规范.md`。 引用文件:`目录导读.md`;`股票价格合理性评估操作手册.md`;`../../ana-data/result/股票估值/目录说明.md`;`../../dev/project-dev/stock_valuation_pipeline_v2/README.md`。 记录方式:用户确认的轻量开发需求输入;项目当前未启用独立需求体系,交由项目管理员调度日常开发池实现,并按开发体系完成必要验收。 当前修订:2026-08-09;本文件使用稳定路径原位维护,不再为普通修订新增并列版本文件。 ## 1. 状态与目标 - 需求 ID:`DEV-STOCK-VALUATION-LEDGER-MVP-20260805-001` - 来源:用户要求把公司、基准合理区间等估值字段存入数据库,便于检索和每日更新。 - 语义确认:用户原话中的“每天的估价师发生变动”按上下文解释为“每天的股价发生变动”。 - 需求状态:用户已确认;项目管理员已派给日常开发员,2026-08-05按用户补充要求将存储从SQLite改为本机MySQL。 - 实施原则:快速落地、实用优先、不做过度设计。 目标是建立一个本地股票估值台账:合理区间在没有正式复评时保持不变,每个完整交易日只刷新收盘价,并自动回答“按最近一次正式估值区间,这只股票今天属于偏低、基本合理、偏贵还是明显偏贵”。 ## 2. 首版范围 首版只实现以下最小闭环: 1. 从现有标准估值结果包批量导入公司、代码、市场、币种、估值日、估值方法、悲观/基准/乐观区间、关键估值指标、机构预期和报告路径。 2. 每日取得已有股票的最新完整交易日前复权收盘价。 3. 使用最近一版有效估值区间计算每日判定。 4. 把历史价格和每日判定写入数据库,支持按公司、代码、日期和判定检索。 5. 生成一份人可读的最新总表和一份CSV导出。 6. 新复评结果出现时,显式导入为新估值版本;旧版本保留,不能被每日价格更新覆盖。 ## 3. 技术与落点 首版固定复用本机MySQL(`127.0.0.1:3306`)并使用轻量驱动`mysql.connector`,不另建数据库服务: - 代码:`dev/project-dev/stock_valuation_ledger/` - 测试:`dev/project-dev/test/stock_valuation_ledger/` - 工程说明:`dev-doc/project-doc/股票估值每日台账.md` - 运行数据库:MySQL独立库`stock_valuation` - 行情和证券主数据来源:只读MySQL库`trading_xuntou` - Darkline事件拓扑:继续使用MySQL库`tianxia`,本工具不得读写其`dl_`表 - 最新总表:`ana-data/result/股票估值/估值台账/latest.md` - 最新CSV:`ana-data/result/股票估值/估值台账/latest.csv` - 导入缺口:`ana-data/result/股票估值/估值台账/import_gaps.csv` `stock_valuation`已经建立,生产数据不进入Git;可复现的MySQL schema、最小迁移脚本、测试fixture和工程说明进入版本控制。连接主机、端口、用户、密码和库名从环境变量或本机配置读取,密码不得硬编码或写入仓库。`latest.md`、`latest.csv`是否提交由项目现有结果目录规则决定,首版不得每天产生大量Git文件。 ## 4. 数据表 首版只使用四张业务表,不增加消息队列、缓存表、审计事件表或复杂状态机。 ### 4.1 `security` | 字段 | 口径 | |---|---| | `ticker` | 主键;带市场后缀,如`300450.SZ`、`09880.HK` | | `company` | 公司简称 | | `market` | 上交所、深交所、北交所或港交所 | | `currency` | `CNY`或`HKD` | | `active` | 是否纳入每日更新,默认1 | | `created_at`、`updated_at` | 数据库时间戳 | ### 4.2 `valuation_version` | 字段 | 口径 | |---|---| | `valuation_id` | 主键;内容可稳定复现 | | `ticker` | 外键到`security` | | `valuation_date` | 正式估值基准日 | | `method` | 主模型,如`PE`或`PB` | | `pessimistic_low/high` | 悲观每股价值区间 | | `base_low/high` | 基准每股价值区间 | | `optimistic_low/high` | 乐观每股价值区间 | | `normalized_profit` | 当时使用的归一化利润,可空 | | `normalized_pe`、`pb`、`ps` | 当时估值指标,可空 | | `consensus_year`、`consensus_profit`、`consensus_count` | 机构预期,可空 | | `report_path` | 正式报告相对项目根目录路径 | | `snapshot_path` | 标准估值快照路径 | | `source_hash` | 快照或结果JSON哈希,用于幂等导入 | | `active_from`、`active_to` | 该估值版本的有效区间;最新版本`active_to`为空 | | `created_at` | 导入时间 | 唯一约束:`ticker + valuation_date + source_hash`。 ### 4.3 `daily_price` | 字段 | 口径 | |---|---| | `ticker`、`trade_date` | 联合主键 | | `close` | 完整交易日前复权收盘价 | | `currency` | 必须与证券币种一致 | | `source_id` | 登记行情来源 | | `source_timestamp` | 来源时间 | | `ingested_at` | 写入时间 | ### 4.4 `daily_judgement` | 字段 | 口径 | |---|---| | `ticker`、`trade_date` | 联合主键 | | `valuation_id` | 当天使用的估值版本 | | `close` | 当天收盘价冗余快照,便于查询 | | `base_low/high`、`optimistic_high` | 当天采用的区间快照 | | `label` | `偏低`、`基本合理`、`偏贵`、`明显偏贵` | | `distance_to_base_low/high` | 当前价相对基准上下沿的百分比 | | `computed_at` | 计算时间 | ## 5. 输入合同 ### 5.1 估值结果 从`ana-data/result/股票估值/`递归读取标准公司结果包: - `*估值快照_*.json` - `calculation/valuation_results.json` - 对应正式`*价格合理性评估_*.md` 导入器必须优先使用结构化JSON,不从Markdown正文抓数字。相同公司存在多个估值日时全部保留,最新估值日成为当前有效版本。同一输入重复导入必须幂等。 无法结构化导入的历史人工报告不得猜测字段,写入`import_gaps.csv`。首版必须覆盖2026-08-05六张图片批次的83只股票,并覆盖当前标准结果包基线的全部125只证券、136个估值版本;如果正式结果包实际数量变化,以扫描结果和显式缺口清单为准,不以旧SQLite试制库作为迁移数据源。 ### 5.2 每日行情 生产`daily`的唯一价格来源是只读`trading_xuntou.cn_stock_kline_1d_front`中的显式前复权、完整交易日日K;必须由专表身份、字段schema和行级时间共同证明来源口径,证据不足时失败关闭,不得读取`cn_stock_kline_1d`替代,不得调用或回退V2 provider及其网络行情: 1. 只接受请求日及以前的最大有效完整交易日日K。 2. 实时quote和盘中值不得作为生产`daily`输入;只有已经作为完整交易日日K落入`cn_stock_kline_1d_front`的记录才可读取。 3. `cn_stock_kline_1d_front`只有在其最大行情日期满足请求日时才可作为价格来源;日期滞后时不得冒充当前价。 4. 行情`symbol`必须与`stock_valuation.security.ticker`逐字一致并符合A股代码后缀;`cn_stock_instrument_static`可作辅助诊断,但因其当前缺少部分北交所证券,不作为生产`daily`硬依赖。 5. 每条价格必须保存来源和来源时间,`source_id`固定包含`trading_xuntou.cn_stock_kline_1d_front`和`front`口径。 ## 6. 输出与查询 CLI模块名固定为`stock_valuation_ledger`,至少提供: ```powershell python -m stock_valuation_ledger init --results-root ana-data/result/股票估值 --database stock_valuation python -m stock_valuation_ledger daily --as-of latest python -m stock_valuation_ledger list --date latest python -m stock_valuation_ledger show --ticker 300450.SZ python -m stock_valuation_ledger export --date latest ``` `list`和`latest.md`至少展示:代码、公司、市场、币种、收盘价、交易日、基准合理区间、乐观上沿、当日判定、估值版本日期、距离基准上下沿、机构预期覆盖和正式报告路径。 `show`展示单股全部估值版本及每日价格/判定历史。`list`支持按`label`、`ticker`或公司名过滤。 ## 7. 核心流程 ### 7.1 首次初始化 1. 检查MySQL连接与`stock_valuation`四表schema;缺表时仅由`init`按版本化SQL创建,不静默创建其他数据库。 2. 扫描现有标准估值结果包。 3. 幂等写入证券和估值版本。 4. 为每只股票选择最新有效估值版本。 5. 输出导入数量、跳过数量和缺口清单。 ### 7.2 每日更新 1. 读取所有`active=1`证券。 2. 并发取得请求日以前的最新完整日K。 3. 在一个数据库事务中幂等写入`daily_price`。 4. 找到交易日当天有效的最近估值版本。 5. 计算并幂等写入`daily_judgement`。 6. 原子更新`latest.md`和`latest.csv`。 7. 输出成功、无新交易日、失败和缺估值版本的数量。 单只行情失败不得阻止其他股票更新;失败证券列在命令结果中,旧价格不能改标为新日期。 ### 7.3 新复评结果 新估值报告完成后再次执行`init`或等价`import-valuations`命令: 1. 新增估值版本。 2. 关闭该股票上一版本的`active_to`。 3. 次日起每日判定使用新版本。 4. 历史每日判定不反向重算,除非显式执行只读模拟或用户明确要求重建。 每日行情更新绝不能修改任何估值区间。 ## 8. 判定规则 固定使用正式V1结论口径,不在台账中发明第二套估值公式: | 条件 | 判定 | |---|---| | `close < base_low` | 偏低 | | `base_low <= close <= base_high` | 基本合理 | | `base_high < close <= optimistic_high` | 偏贵 | | `close > optimistic_high` | 明显偏贵 | 边界值按上表闭区间执行。币种必须一致,区间缺失或币种不一致时该股票当日判定失败,不允许猜测。 ## 9. 失败处理 - 数据库不存在或连接失败:所有命令给出明确提示并停止;生产库由已授权的初始化动作创建,业务命令不得隐式新建数据库。 - 必需区间缺失、上下沿反转、同一有效期存在两个估值版本:阻止该股票判定并报告。 - 行情无新交易日:状态为`NO_NEW_TRADING_DAY`,不视为失败。 - `trading_xuntou`连接失败或schema证明失败:本次`daily`整体失败关闭;单只证券缺少合格日K或行级时间证据时,只跳过并报告该证券,不写伪数据,也不影响其他合格证券。 - 数据库写入失败:事务回滚,不能留下价格已更新但判定未更新的半状态。 - 导出失败:数据库提交结果保留,命令返回非零并指出导出失败。 ## 10. 每日运行方式 开发交付一个`run_daily.ps1`,用于在项目根目录运行每日命令并留下简短日志。可以同时提供Windows计划任务安装示例,但不得在开发或测试期间自动安装系统计划任务。 建议正式运行时间为交易日18:00以后;真正安装计划任务属于一次性运行配置,由用户或项目管理员在工具验收后执行。 ## 11. 不做事项 首版明确不做: - 不做网页、GUI、REST API、后台服务或多用户权限。 - 不做盘中实时估值;只用完整交易日收盘价。 - 不自动修改合理区间、估值倍数、利润预测或正式报告。 - 不做重大事件自动监控和自动复评。 - 不做交易指令、仓位、买卖点、止损或收益承诺。 - 不接付费、登录态或需要新增凭据的provider。 - 不把`stock_valuation`扩展成通用证券主数据平台,也不把估值台账写进`tianxia`或`trading_xuntou`。 - 不保留SQLite兼容后端;旧`stock_valuation.sqlite3`只用于迁移数量核对,MySQL导入校验通过后按明确文件路径清理。 - 不为首版增加消息队列、ORM、迁移框架或复杂审计协议。 ## 12. 验收标准 ### 12.1 主流程必过 1. 空测试库按schema初始化成功,四张表、外键和唯一约束正确;测试不得清空或覆盖生产库`stock_valuation`。 2. 当前标准结果包基线的125只证券、136个估值版本全部成功导入,其中必须覆盖2026-08-05六张图片批次83只股票;无重复证券和重复估值版本。若正式结果包扫描结果变化,差异必须逐项进入导入摘要或`import_gaps.csv`。 3. 使用离线行情fixture运行`daily`后,全部已导入且具备有效估值区间的证券均生成正确判定;四个判定边界各至少有一个测试。 4. 重复执行`init`和`daily`不增加重复行,不改变已有历史数据。 5. 每日价格变化时,估值区间和估值版本哈希保持不变。 6. 新估值版本导入后只影响其生效日以后的判定,历史结果不被改写。 7. 单只行情失败不影响其他股票,失败证券不写新日期数据。 8. `latest.md`、`latest.csv`和`list/show`结果与数据库一致。 9. 价格来源日期不得晚于请求日,也不得把旧价标成新交易日。 10. 项目现有V1/V2测试不退化。 11. 代码、命令和运行配置中不存在SQLite双后端;MySQL数据核验通过后,旧SQLite运行文件按明确路径完成清理。 ### 12.2 实用性目标 - 200只股票的暖库查询应在1秒内完成。 - 本机MySQL正常可用时,200只股票每日更新应在2分钟内完成。 - 用户从`latest.md`或`list`能直接看到全部已入库公司的当前价、合理区间和当日判定,不需要逐份打开估值报告。 ## 13. 上游一致性检查 - 需求方案文档:不适用;这是单一台账工具的第一版轻量需求,不需要另建方案。 - 架构、模块说明、核心流程三大文档:不适用;单进程CLI、一个独立MySQL库、四张表和一个每日流程已在本文唯一化,不属于第一版复杂系统。 - 与操作手册一致:合理区间来自正式估值版本;每日股价属于必须刷新的时点数据;历史年报和已核实公式不重复搜索。 - 与V1一致:判定边界和三情景区间直接复用V1结果,不复制估值公式。 - 与V2时间边界一致:行情只接受请求日以前最大有效完整日K,不能把无时间戳的实时值冒充历史数据;价格口径按用户确认固定为`cn_stock_kline_1d_front`前复权,仅复用V2时间约束,不调用或回退V2 provider及网络行情。 - 与项目边界一致:只输出条件化估值判定,不输出交易指令。 - 无冲突、无待确认实现分支。 ## 14. 验收与审核边界 本需求由用户直接确认并要求快速推进。项目当前未启用独立需求体系,因此本文作为股票价值评估角色提交给项目管理员的轻量业务需求输入;项目管理员负责从日常开发池选择一名空闲开发员,开发员不得扩大范围,代码质量由`dev.reviewer.project`按风险做必要审核,最终实用性由用户和本角色普通验收。 ## 15. 单一最新版与日常交付补充规则 1. 全量日更默认覆盖 `security.active=1` 且目标交易日存在有效估值版本的全部证券;同日价格、来源、估值版本和判定已经一致的证券必须幂等跳过。 2. 用户可见日更结果只保留固定的 `latest.md`、`latest.csv` 和 `latest_gaps.csv`,成功运行时原子覆盖,不创建日期、批次或版本后缀的并列日更文件。 3. 数据库继续保留历史价格、历史判定和不可变估值版本,用于检索、追溯和复算;这些数据库行及基础证据包不属于并列用户文档版本。 4. 日历 current asset 必须先覆盖请求日,再派生最近开市日。日历滞后时由有权限的上游运维入口刷新,台账不得通过 fixture、旧表、网络或手工日期回退绕过。 5. 每次成功刷新后验证数据库与固定 latest 文件的日期、数量、价格、估值版本和标签一致;缺口进入固定 `latest_gaps.csv`。 6. 验证通过后只暂存本次规范和固定 latest 文件,提交当前 Git 分支并推送远端;不得使用 `git add .` 带入其他任务改动。没有文件差异时不创建空提交,但仍确认远端同步状态。