Cai
5 hours ago 22384865fbdb92c4ce603c137b1cac52ab6450ba
ai-valuation-analyst/tools/enrich_valuation_bubbles.py
@@ -639,7 +639,7 @@
        f"- 价格交易日:`{trade_date_text}`",
        f"- 泡沫解释版本:`{trade_date_text}/v{SCRIPT_VERSION}`",
        f"- 记录数:`{len(rows)}`",
        "- 全量覆盖:`677`个已评估主体,其中本表为可形成数值区间判定的`672`只,另`5`只见同目录`latest_gaps.csv`。",
        f"- 数值判定覆盖:本表共`{len(rows)}`只;无法形成当日数值判定的证券单列于同目录`latest_gaps.csv`。",
        f"- 估值泡沫:`{bubble_count}`只;定义为当前价高于正式基准合理区间上沿。",
        "- 原因性质:除价格位置外,泡沫原因均是基于反向估值、基础报告和量价显影的最可能解释,不是已证实的资金流因果。",
        f"- 输入快照 SHA-256:`{source_hash}`;泡沫解释脚本:`enrich_valuation_bubbles.py v{SCRIPT_VERSION}`。",
@@ -729,15 +729,16 @@
    latest_md = resolve_under(project_root, args.latest_md)
    fieldnames, rows = read_csv(latest_csv)
    source_hash = hashlib.sha256(canonical_base_csv(fieldnames, rows)).hexdigest().upper()
    if len(rows) != 672:
        raise RuntimeError(f"Expected 672 current numeric judgements, got {len(rows)}")
    if not rows:
        raise RuntimeError("Current numeric judgement file is empty")
    tickers = [row["ticker"] for row in rows]
    if len(set(tickers)) != len(tickers):
        raise RuntimeError("Duplicate tickers in latest.csv")
    trade_dates = {date.fromisoformat(row["trade_date"]) for row in rows}
    if len(trade_dates) != 1:
        raise RuntimeError(f"Expected one trade date, got {sorted(trade_dates)}")
    metrics = market_metrics(tickers, next(iter(trade_dates)), args.skip_market)
    metrics: dict[str, MarketMetrics] = {}
    for trade_date in sorted(trade_dates):
        date_tickers = [row["ticker"] for row in rows if date.fromisoformat(row["trade_date"]) == trade_date]
        metrics.update(market_metrics(date_tickers, trade_date, args.skip_market))
    missing_market = sorted(set(tickers) - set(metrics)) if not args.skip_market else []
    enriched: list[dict[str, str]] = []