估值线 vs 市场报价线图
核心理念
企业内在价值是"锚"(慢变量),市场价格是"摆"(快变量)。两者的偏离度即为安全边际信号:
偏离 < -50% 为深度低估(重仓击球),偏离 > +50% 为泡沫(卖出离场)。
价值线 = DCF权重 x DCF每股价值 + (1-DCF权重) x EPS x 合理PE,受"慢变量约束"保护
(单年最多回落5%,好生意价值线不塌陷)。价格线 = 历年不复权收盘价。
前置条件
valuation_system 代码库必须存在于工作区,目录结构:
valuation_system/
config/settings.py # 五档信号阈值、DCF默认参数、困境甄别配置
data/models/financials.py # BalanceSheet/IncomeStatement/CashFlowStatement 数据模型
data/sources/akshare_source.py # A股数据源(东财三大报表+新浪行情)
data/sources/hk_source.py # 港股数据源(东财港股报表+新浪港股日线+汇率)
analysis/valuation.py # DCFModel + build_value_line + RelativeValuation
analysis/margin_of_safety.py # MarginOfSafety + DistressScreener
analysis/ratios.py # RatioAnalyzer(四类财务比率)
analysis/dupont.py # DuPontAnalyzer(三因子/五因子分解)
Python venv 路径(已安装 streamlit/akshare/pandas/numpy/plotly/openpyxl):
C:/Users/lenovo/.workbuddy/binaries/python/envs/default/Scripts/python.exe
工作流程
第1步:确定企业类型与参数
查阅 references/company_type_params.md,根据行业确定企业类型,选取对应参数集:
- beta(贝塔系数)
- reasonable_pe(合理市盈率,估值线兜底用)
- high_growth / high_growth_years / fade_years / terminal_growth(DCF假设)
- smooth_fcf_years(周期型 > 1,用滚动均值熨平周期顶/谷)
- 是否需要 net_debt_by_year(高杠杆公司必扣净债务)
第2步:拉取真实数据
A股(代码如 600519):
- 财报:AkshareDataSource().get_financials(code, name) → CompanyFinancials 列表
- 逐年股本:ak.stock_profit_sheet_by_report_em(symbol=f"SH{code}"),取 PARENT_NETPROFIT/BASIC_EPS 反算
- 年度收盘价:ak.stock_zh_a_daily(symbol=f"sh{code}", start_date="20140101", adjust="")
(东财 stock_zh_a_hist 常被限流,优先用新浪 stock_zh_a_daily)
港股(代码如 00700):
- 财报:hk_source.get_financials(stock, name) → CompanyFinancials 列表(人民币计价)
- 逐年股本:hk_source.get_shares_by_year(fins)
- 年度收盘价:hk_source.get_yearly_price(stock) → 港元,需乘 hk_source.get_hkd_cny() 换算人民币
第3步:构建估值线
from analysis.valuation import build_value_line
from analysis.margin_of_safety import MarginOfSafety
cfg = {**VALUE_LINE, "reasonable_pe": <企业类型合理PE>}
# 周期型额外传 smooth_fcf_years 和 net_debt_by_year
vline = build_value_line(fins, shares_by_year, yearly_price, dcf_params, cfg,
smooth_fcf_years=<N>, net_debt_by_year=<dict或None>)
dash = MarginOfSafety.build_dashboard(vline)
sig = MarginOfSafety.current_signal(dash)
第4步:困境甄别(区分短期困境 vs 价值陷阱)
from analysis.margin_of_safety import DistressScreener
auto_cf = DistressScreener.auto_cash_flow_score(fins) # 现金流项自动打分
scores = {"moat": <0-2>, "external": <0-2>, "cash_flow": auto_cf,
"management": <0-2>, "reversibility": <0-2>}
screener = DistressScreener(scores)
verdict = screener.verdict() # total >= 7 才允许触发买入信号
打分依据参见 references/company_type_params.md 的困境甄别五项打分卡。
第5步:渲染对比图
查阅 references/chart_svg_spec.md 获取完整 SVG 模板规范。关键要素:
- 蓝色折线 = 估值线(内在价值,慢变量锚)
- 红色折线 = 价格线(市场报价,快变量摆)
- 绿色阴影区域 = 击球区(价格 < 价值80%)
- 红色阴影区域 = 泡沫区(价格 > 价值150%)
- 每年标注偏离度百分比和档位标签
- 底部摘要框:今日价格 vs 价值、偏离度、信号档位、困境甄别分数
使用 show_widget 渲染 SVG,loading_messages 设置 3-4 条加载提示。
图表数据来自 JSON 结果文件(如 coal_result.json、haitian_result.json)或直接从分析脚本内存数据生成。
第6步:输出报告
生成 Markdown 分析报告到 output/ 目录,内容包括:
1. 估值结论一句话(今日价格 vs 价值、偏离度、档位)
2. 杜邦分解真相表(ROE拆解,揭示盈利质量)
3. 两线对比图解读(泡沫→击球区→回归的故事线)
4. 困境甄别打分卡
5. DCF敏感性矩阵
6. 与同业对比(如有)
关键注意事项
- 股本是变的:A股有送转股、港股有增发,必须用逐年股本 dict,不能假设固定股本
- 周期股特殊处理:基期 FCF 用 3-5 年滚动均值平滑,合理 PE 压低至 10-11 倍,
估值线必须逐年扣减净债务(高杠杆公司净负债可能数百亿) - 慢变量约束的局限性:对盈利中枢真实下移的公司(如兖矿煤价见顶后回落),
慢变量约束会把估值线托高,需用敏感性矩阵中档假设交叉验证 - 港股汇率:报表以人民币计价,行情以港元计价,必须统一口径(乘港币兑人民币汇率)
- 行情接口限流:东财 stock_zh_a_hist 经常被限流,优先使用新浪 stock_zh_a_daily
- 困境甄别分数决定估值线可信度:10/10 满分(如神华)价值线可信;
7/10 刚过线(如兖矿)必须用敏感性矩阵交叉验证 - show_widget 的 widget_code 必须是原始 SVG,不含 DOCTYPE/html/head/body 标签
- light 主题:浅色背景 + 深色文字;红色涨/绿色跌(A股配色习惯)