| | |
| | | return "https://push2his.eastmoney.com/api/qt/stock/kline/get?secid=" + ("1." if ticker.endswith(".SH") else "0.") + ticker[:6] |
| | | |
| | | |
| | | def as_of_stamp() -> str: |
| | | return AS_OF.replace("-", "") |
| | | |
| | | |
| | | def build_one(stock: Stock, proof_map: dict[str, dict[str, Any]]) -> dict[str, Any]: |
| | | v2dir = failed_dir(stock.ticker) |
| | | provider = read_json(v2dir / "provider_results.json") |
| | |
| | | "report_date": AS_OF, |
| | | "include": True, |
| | | "core_assumption": "汇总接口未提供逐家报告日期;估值日仅作为C1汇总快照日期,不替代单家研报。", |
| | | "source_id": "SRC-EM-CONSENSUS-20260804", |
| | | "source_id": f"SRC-EM-CONSENSUS-{as_of_stamp()}", |
| | | "estimates": {year: {"profit": values["profit"], "eps": values["eps"]} for year, values in forecast["years"].items() if year in {"2026", "2027", "2028"}}, |
| | | }) |
| | | sources = [ |
| | |
| | | "supports": ["financials.current_cumulative", "financials.prior_year_same_period", "balance_sheet", "balance_sheet.equity"], "revision_status": "current", |
| | | }, |
| | | { |
| | | "id": "SRC-EM-FINANCE-20260804", "source_type": "financial_mirror", "title": "东方财富结构化财务字段提取与法定报告勾稽", "publish_date": current["publish_date"], "period_end": financials["current_cumulative"]["period_end"], "url": "https://datacenter-web.eastmoney.com/api/data/v1/get", |
| | | "id": f"SRC-EM-FINANCE-{as_of_stamp()}", "source_type": "financial_mirror", "title": "东方财富结构化财务字段提取与法定报告勾稽", "publish_date": current["publish_date"], "period_end": financials["current_cumulative"]["period_end"], "url": "https://datacenter-web.eastmoney.com/api/data/v1/get", |
| | | "supports": ["financials", "balance_sheet"], "revision_status": "current", |
| | | }, |
| | | { |
| | | "id": "SRC-EM-KLINE-20260804", "source_type": "quote_provider", "title": "东方财富2026-08-04未复权日K收盘价", "publish_date": AS_OF, "period_end": AS_OF, "url": source_type_market(stock.ticker), |
| | | "id": f"SRC-EM-KLINE-{as_of_stamp()}", "source_type": "quote_provider", "title": f"东方财富{AS_OF}未复权日K收盘价", "publish_date": AS_OF, "period_end": AS_OF, "url": source_type_market(stock.ticker), |
| | | "supports": ["market.price", "market.price_timestamp", "market.amount"], "revision_status": "current", |
| | | }, |
| | | shares_source, |
| | | ] |
| | | if forecast_rows: |
| | | sources.append({ |
| | | "id": "SRC-EM-CONSENSUS-20260804", "source_type": "institution_aggregator", "title": f"东方财富{company}盈利预测汇总", "publish_date": AS_OF, "period_end": AS_OF, "url": "https://datacenter-web.eastmoney.com/api/data/v1/get", |
| | | "id": f"SRC-EM-CONSENSUS-{as_of_stamp()}", "source_type": "institution_aggregator", "title": f"东方财富{company}盈利预测汇总", "publish_date": AS_OF, "period_end": AS_OF, "url": "https://datacenter-web.eastmoney.com/api/data/v1/get", |
| | | "supports": ["institutions"], "revision_status": "current", |
| | | }) |
| | | snapshot = { |
| | | "snapshot_id": f"SNAPSHOT-{stock.ticker[:6]}-20260804-V1", |
| | | "snapshot_id": f"SNAPSHOT-{stock.ticker[:6]}-{as_of_stamp()}-V1", |
| | | "meta": {"company": company, "code": stock.ticker, "market": identity["market"], "as_of_date": AS_OF, "currency": "CNY", "report_period_end": financials["current_cumulative"]["period_end"], "latest_operating_info_date": current["publish_date"]}, |
| | | "market": {"price": market["price"], "price_type": "最近完整交易日未复权收盘价", "price_timestamp": f"{market['date']}T15:00:00+08:00", "diluted_shares": market["shares"], "shares_date": shares_date, "platform_market_cap": market["market_cap"]}, |
| | | "financials": financials, |
| | |
| | | "kline_window_start": market["window_start"], "kline_window_start_close": market["window_start_close"], "kline_window_return": market["window_return"], "latest_amount": market["amount"], |
| | | "ttm_cfo": ttm_cfo, "ttm_capex": ttm_capex, "ttm_fcf": ttm_cfo - ttm_capex, |
| | | "total_equity_original": report_proof["total_equity_original"], "attributable_equity_used": report_proof["parent_equity"], "minority_interest_original": report_proof["minority_original"], |
| | | "report_shares": report_proof["report_shares"], "share_proof_status": share_status, "information_cutoff": "2026-08-04T23:40:00+08:00", |
| | | "report_shares": report_proof["report_shares"], "share_proof_status": share_status, "information_cutoff": f"{AS_OF}T23:40:00+08:00", |
| | | }, |
| | | } |
| | | out_dir = RESULT_ROOT / f"20260804_{stock.slug}_valuation" |
| | | out_dir = RESULT_ROOT / f"{as_of_stamp()}_{stock.slug}_valuation" |
| | | calc_dir = out_dir / "calculation" |
| | | snapshot_path = out_dir / f"{company}估值快照_20260804.json" |
| | | snapshot_path = out_dir / f"{company}估值快照_{as_of_stamp()}.json" |
| | | write_json(snapshot_path, snapshot) |
| | | run = run_pipeline(snapshot_path, calc_dir, REGISTRY) |
| | | results = read_json(calc_dir / "valuation_results.json") |
| | | formal_text = (calc_dir / "valuation_report.md").read_text(encoding="utf-8") |
| | | formal_text = formal_text.replace("价格合理性评估(流水线生成底稿)", "价格合理性评估", 1).replace("本文是研究计算底稿,不构成交易指令或收益承诺。", "本文为按《股票价格合理性评估操作手册》形成的条件化研究结论,不构成交易指令或收益承诺。", 1) |
| | | formal_path = out_dir / f"{company}价格合理性评估_20260804.md" |
| | | formal_path = out_dir / f"{company}价格合理性评估_{as_of_stamp()}.md" |
| | | formal_path.write_text(formal_text, encoding="utf-8") |
| | | raw_hashes = [] |
| | | for section in provider.values(): |
| | | raw_hashes.extend(section.get("raw_artifact_hashes", [])) |
| | | evidence = { |
| | | "batch_id": BATCH_ID, "ticker": stock.ticker, "company": company, "information_cutoff": "2026-08-04T23:40:00+08:00", "market_date": market["date"], |
| | | "batch_id": BATCH_ID, "ticker": stock.ticker, "company": company, "information_cutoff": f"{AS_OF}T23:40:00+08:00", "market_date": market["date"], |
| | | "v2_status": "BLOCKED", "v2_failure_package": str(v2dir.relative_to(ROOT)).replace("\\", "/"), "v2_failure_reason": read_json(v2dir / "failure.json")["error"], |
| | | "raw_hashes": raw_hashes, "market_evidence": market_evidence, "share_proof_status": share_status, "share_proof": proof if proof else {"report_shares": report_proof["report_shares"]}, |
| | | "manual_finance_override": {"used": provider["finance"]["status"] != "OK", "reason": "V2对负少数股东权益严格阻断;人工使用法定归母权益,EV少数股东权益按0保守处理" if provider["finance"]["status"] != "OK" else None}, |