from __future__ import annotations import csv import hashlib import json from datetime import datetime from pathlib import Path from zoneinfo import ZoneInfo RUN_ID = "RUN-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-001" TASK_ID = "ANA-WUJI-V1-FINAL-CONCLUSION-20260610" SOURCE_RUN_ID = "RUN-ANA-WUJI-STRICT-SELL-ROLLING-REPAIR-20260609-001" SOURCE_EXEC_AUDIT_ID = "AUDIT-ANA-WUJI-STRICT-SELL-ROLLING-REPAIR-20260610-EXEC-REREVIEW-003" DESIGN_AUDIT_ID = "AUDIT-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-DESIGN-001" EXEC_AUDIT_ID = "AUDIT-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-EXEC-001" EXEC_REVIEW_MESSAGE_ID = "msg_20260610215718079_7732c8c2" EXEC_REVIEW_REQUEST_ID = "msg_20260610215112659_4d34e4c7" EXEC_REVIEW_TIME = "2026-06-10T21:57:18+08:00" OUT_DIR = Path(__file__).resolve().parents[1] PROJECT_ROOT = Path(__file__).resolve().parents[4] SOURCE_DIR = PROJECT_ROOT / "ana-data" / "result" / SOURCE_RUN_ID def now_iso() -> str: return datetime.now(ZoneInfo("Asia/Shanghai")).isoformat(timespec="seconds") def read_csv(path: Path) -> list[dict[str, str]]: with path.open("r", encoding="utf-8-sig", newline="") as f: return list(csv.DictReader(f)) def write_csv(path: Path, rows: list[dict[str, object]], fieldnames: list[str] | None = None) -> None: if fieldnames is None: fieldnames = list(rows[0].keys()) if rows else [] with path.open("w", encoding="utf-8-sig", newline="") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerows(rows) def write_json(path: Path, data: object) -> None: path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") def sha256_file(path: Path) -> str: h = hashlib.sha256() with path.open("rb") as f: for chunk in iter(lambda: f.read(1024 * 1024), b""): h.update(chunk) return h.hexdigest() def file_row(path: Path) -> dict[str, object]: return { "path": path.relative_to(OUT_DIR).as_posix(), "size": path.stat().st_size, "sha256": sha256_file(path), } def case_line(row: dict[str, str]) -> str: case_id = row["case_id"] ret = row.get("account_return_closed_lots", "") return ( f"- `{case_id}`:账户贡献 `{ret}`;" f"[图片板](../{SOURCE_RUN_ID}/cases/{case_id}/case_image_board.md);" f"[故事板](../{SOURCE_RUN_ID}/cases/{case_id}/case_story_board.md)" ) def main() -> None: summary_path = OUT_DIR / "v1_final_conclusion_summary.json" summary = json.loads(summary_path.read_text(encoding="utf-8-sig")) readouts = read_csv(OUT_DIR / "v1_final_readouts.csv") case_rows = read_csv(OUT_DIR / "v1_case_readout_index.csv") boundary_rows = read_csv(OUT_DIR / "v1_boundary_table.csv") primary = [r for r in case_rows if r["v1_return_scope"] == "V1_PRIMARY_STRICT_CLOSED_CASE"] positive = [r for r in primary if r["success_flag"] == "1"] non_positive = [r for r in primary if r["success_flag"] != "1"] boundary_cases = [r for r in case_rows if r["v1_return_scope"] != "V1_PRIMARY_STRICT_CLOSED_CASE"] top_positive = sorted(positive, key=lambda r: float(r["account_return_closed_lots"] or 0), reverse=True)[:3] top_negative = sorted(non_positive, key=lambda r: float(r["account_return_closed_lots"] or 0))[:3] boundary_example = boundary_cases[:1] readout_map = {r["readout_id"]: r for r in readouts} primary_readout = readout_map["V1_PRIMARY_STRICT_CLOSED_CASE"] coverage_readout = readout_map["V1_ALL_BUY_CASE_COVERAGE"] lot_readout = readout_map["V1_STRICT_CLOSED_LOT_RECALC_ONLY"] rolling_readout = readout_map["V1_ROLLING_LOW_BUY"] summary.update( { "execution_review_status": "EXECUTION_REVIEW_PASSED_LAYERED_V1_CITATION_ALLOWED", "execution_review_audit_id": EXEC_AUDIT_ID, "execution_review_message_id": EXEC_REVIEW_MESSAGE_ID, "execution_review_request_message_id": EXEC_REVIEW_REQUEST_ID, "execution_review_passed_at": EXEC_REVIEW_TIME, "citation_allowed": True, "formal_summary_written": True, "formal_summary_path": "ana-doc/wuji/无忌交易系统V1最终案例总结.md", } ) write_json(summary_path, summary) summary_md = f"""# 无忌 V1 最终结论引用包摘要 ## 当前可引用状态 当前包基于已通过执行复审的 V1 结果包生成,来源审计 ID 为 `{SOURCE_EXEC_AUDIT_ID}`。本包已通过最终结论引用包执行审核,审计 ID 为 `{EXEC_AUDIT_ID}`。 允许按 V1 口径、审计 ID 和边界表分层引用;不得写成无边界完整 baseline 结论或策略有效性证明。 ## V1 主口径:V1_PRIMARY_STRICT_CLOSED_CASE | 指标 | 读数 | |---|---:| | V1 主口径严格闭合 case | {primary_readout['case_count']} | | V1 主口径正收益 case | {primary_readout['positive_case_count']} | | V1 主口径非正收益 case | {primary_readout['non_positive_case_count']} | | V1 主口径成功率读数 | {primary_readout['success_rate']} | | V1 主口径账户贡献合计读数 | {primary_readout['account_contribution_sum']} | ## 覆盖口径 | 指标 | 读数 | |---|---:| | V1 有 BUY case | {coverage_readout['case_count']} | | V1 边界 case | {coverage_readout['boundary_count']} | | 滚动低吸 BUY 订单 | {rolling_readout['lot_count']} | ## lot 辅助口径 | 指标 | 读数 | |---|---:| | V1 lot 总数 | {lot_readout['lot_count']} | | V1 边界 lot | {lot_readout['boundary_count']} | ## 边界 `v1_boundary_table.csv` 完整保留来源边界表,共 {len(boundary_rows)} 行。必须特别保留 `MARKET_RISK_MINUTE_BREADTH_DATA_GAP_HELD`,它表示本地数据源没有开盘 10 分钟全 A 下跌家数分钟级广度,市场风险卖点不能被无边界化。 ## 禁止外推 1. 不得把 V1 读数写成旧 V0 包结论。 2. 不得写成无边界完整 baseline 成功率、收益率、胜率或回撤。 3. 不得作出策略有效性的证明结论。 4. 不得省略审计 ID、V1 口径、边界表和市场风险分钟广度数据缺口。 """ (OUT_DIR / "v1_final_conclusion_summary.md").write_text(summary_md, encoding="utf-8") human_index = f"""# 无忌 V1 最终结论人工审核第一入口 ## 先看这里 当前 V1 最终结论引用包已通过执行审核:`{EXEC_AUDIT_ID}`。 可以引用:在 V1 主口径 `V1_PRIMARY_STRICT_CLOSED_CASE` 下,250 个严格闭合 case 中 99 个为正收益,成功率读数为 0.396,账户贡献合计读数为 0.12970642。 必须同时引用: - 来源 V1 执行复审 ID:`{SOURCE_EXEC_AUDIT_ID}` - 本最终引用包执行审核 ID:`{EXEC_AUDIT_ID}` - `v1_boundary_table.csv` - `MARKET_RISK_MINUTE_BREADTH_DATA_GAP_HELD` 不能引用:不能把 V1 读数写成旧 V0 包结论,不能写成无边界完整 baseline 结论,不能作出策略有效性的证明结论,不能省略市场风险分钟广度数据缺口。 ## 当前状态 | 项目 | 内容 | |---|---| | 当前 run | `{RUN_ID}` | | 来源 run | `{SOURCE_RUN_ID}` | | 来源执行复审审计 ID | `{SOURCE_EXEC_AUDIT_ID}` | | 当前设计审核审计 ID | `{DESIGN_AUDIT_ID}` | | 当前执行审核审计 ID | `{EXEC_AUDIT_ID}` | | RETURN_STAT_READY | `false` | | 执行审核状态 | `通过 / 允许按 V1 边界引用` | ## V1 三层读数 1. `V1_PRIMARY_STRICT_CLOSED_CASE`:250 个严格闭合 case,正收益 99 个,成功率读数 0.396,账户贡献合计 0.12970642。 2. `V1_ALL_BUY_CASE_COVERAGE`:251 个有 BUY case,其中 1 个 case 进入边界;该口径不替代主成功率。 3. `V1_STRICT_CLOSED_LOT_RECALC_ONLY`:735 个 lot,其中 734 个闭合、1 个边界;lot 口径只用于复算和问题定位。 4. `V1_ROLLING_LOW_BUY`:滚动低吸 BUY 订单 25 笔;只说明 V1 执行数量,不单独构成策略有效性结论。 ## 第一入口链接 - 来源 V1 图片总入口:[case_image_board.md](../{SOURCE_RUN_ID}/case_image_board.md) - 来源 V1 摘要:[summary.md](../{SOURCE_RUN_ID}/summary.md) - 来源 V1 手工裁决草稿:[manual_decision_external_draft.md](../{SOURCE_RUN_ID}/manual_decision_external_draft.md) - 当前 V1 结论摘要:[v1_final_conclusion_summary.md](v1_final_conclusion_summary.md) - 当前 V1 同事总结:[v1_final_case_summary_for_colleagues.md](v1_final_case_summary_for_colleagues.md) - 当前 V1 读数表:[v1_final_readouts.csv](v1_final_readouts.csv) - 当前 V1 case 索引:[v1_case_readout_index.csv](v1_case_readout_index.csv) - 当前 V1 边界表:[v1_boundary_table.csv](v1_boundary_table.csv) ## 代表性 case 主口径正收益较高样例: {chr(10).join(case_line(r) for r in top_positive)} 主口径负收益较低样例: {chr(10).join(case_line(r) for r in top_negative)} 边界样例: {chr(10).join(case_line(r) for r in boundary_example)} ## 阅读提示 1. 先看本文件的可引用 / 不可引用边界。 2. 再看 `v1_final_case_summary_for_colleagues.md`,它是同事阅读版摘要。 3. 需要追溯单个案例时,从 `v1_case_readout_index.csv` 找到 `case_id`,再打开对应图片板和故事板。 4. 对卖点和滚动低吸的人工裁决来源,优先看 `manual_decision_external_draft.md` 和 `manual_decision_ledger.csv`。 """ (OUT_DIR / "v1_final_human_review_index.md").write_text(human_index, encoding="utf-8") final_md = f"""# 无忌交易系统 V1 最终案例总结(分层引用版) 创建人员:case_analysis.analyst / laoan 文件职责:给同事阅读的 V1 当前正式总结入口,说明可以引用的读数、必须带上的边界,以及从哪里追溯证据。 ## 一句话结论 `RUN-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-001` 已通过最终结论引用包执行审核,审计 ID 为 `{EXEC_AUDIT_ID}`。当前允许把 V1 读数按分层口径写给同事看,但不能写成无边界完整 baseline 结论,也不能作出策略有效性的证明结论。 ## 可以引用的 V1 读数 在 V1 主口径 `V1_PRIMARY_STRICT_CLOSED_CASE` 下,250 个严格闭合 case 中 99 个为正收益,成功率读数为 0.396,账户贡献合计读数为 0.12970642。 覆盖口径 `V1_ALL_BUY_CASE_COVERAGE` 为 251 个有 BUY case,其中 1 个边界 case;覆盖口径只说明样本覆盖,不替代主成功率分母。 辅助 lot 口径 `V1_STRICT_CLOSED_LOT_RECALC_ONLY` 为 735 个 lot,其中 734 个闭合、1 个边界;lot 口径只用于复算和问题定位,不包装成 case 成功率。 滚动低吸 BUY 订单为 25 笔;它只说明 V1 执行数量,不单独构成策略有效性结论。 ## 必须同时写明的边界 1. 来源 V1 执行复审 ID:`{SOURCE_EXEC_AUDIT_ID}`。 2. 本最终引用包执行审核 ID:`{EXEC_AUDIT_ID}`。 3. 该读数只覆盖 V1 已审核主口径,不等于无边界完整 baseline。 4. `v1_boundary_table.csv` 必须保留,其中包括 `MARKET_RISK_MINUTE_BREADTH_DATA_GAP_HELD`。 5. 当前仍保留 `RETURN_STAT_READY=false`。 ## 不可以写的内容 1. 不得把 V1 读数写成旧 V0 包结论。 2. 不得写成无边界完整 baseline 成功率、收益率、胜率或回撤。 3. 不得省略 1 个边界 case、1 个边界 lot 和市场风险分钟广度数据缺口。 4. 不得把滚动低吸 BUY 25 笔单独包装成策略有效性结论。 ## 给同事看的阅读入口 1. 先看 V1 人工第一入口:`ana-data/result/RUN-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-001/v1_final_human_review_index.md`。 2. 再看 V1 结果包摘要:`ana-data/result/RUN-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-001/v1_final_conclusion_summary.md`。 3. 想逐个看案例时,看 `ana-data/result/RUN-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-001/v1_case_readout_index.csv`,再进入对应 case 图片板和 story board。 4. 想查买卖和滚动低吸裁决来源时,看 `ana-data/result/RUN-ANA-WUJI-STRICT-SELL-ROLLING-REPAIR-20260609-001/manual_decision_external_draft.md` 和 `manual_decision_ledger.csv`。 5. 想复核边界时,看 `ana-data/result/RUN-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-001/v1_boundary_table.csv`。 ## 审计链 | 阶段 | 审计 ID | |---|---| | V1 精准卖点与滚动渣男执行复审 | `{SOURCE_EXEC_AUDIT_ID}` | | V1 最终结论引用设计审核 | `{DESIGN_AUDIT_ID}` | | V1 最终结论引用包执行审核 | `{EXEC_AUDIT_ID}` | ## 与旧 V0 总结的关系 旧 `ana-doc/wuji/无忌交易系统最终案例总结.md` 保留为 V0 / 代理卖点阶段的历史分层引用记录。当前要给同事看 V1 完整精准卖点与滚动低吸返修后的结果,应优先使用本文件和 `RUN-ANA-WUJI-V1-FINAL-CONCLUSION-20260610-001`。 """ (OUT_DIR / "v1_final_case_summary_for_colleagues.md").write_text(final_md, encoding="utf-8") final_json = { "schema_version": "1.0", "task_id": TASK_ID, "run_id": RUN_ID, "source_run_id": SOURCE_RUN_ID, "source_execution_rereview_audit_id": SOURCE_EXEC_AUDIT_ID, "design_audit_id": DESIGN_AUDIT_ID, "execution_review_audit_id": EXEC_AUDIT_ID, "execution_review_message_id": EXEC_REVIEW_MESSAGE_ID, "generated_at": now_iso(), "citation_allowed": True, "return_stat_ready": False, "readouts": summary["readouts"], "required_boundary": [ "V1 scope", SOURCE_EXEC_AUDIT_ID, EXEC_AUDIT_ID, "v1_boundary_table.csv", "MARKET_RISK_MINUTE_BREADTH_DATA_GAP_HELD", ], "public_summary_path": "ana-doc/wuji/无忌交易系统V1最终案例总结.md", } write_json(OUT_DIR / "v1_final_case_summary_for_colleagues.json", final_json) readme = f"""# 无忌 V1 最终结论引用包 本包是 V1 执行复审通过后的引用层整理,不重跑候选池、买卖裁决、人工裁决或账本。 当前执行审核已通过:`{EXEC_AUDIT_ID}`。 先看:[v1_final_human_review_index.md](v1_final_human_review_index.md) 给同事看的总结:[v1_final_case_summary_for_colleagues.md](v1_final_case_summary_for_colleagues.md) 来源执行复审 ID:`{SOURCE_EXEC_AUDIT_ID}` 设计审核 ID:`{DESIGN_AUDIT_ID}` 当前状态:允许按 V1 口径、审计 ID 和边界表分层引用;不得写成无边界完整 baseline 结论或策略有效性证明。 """ (OUT_DIR / "README.md").write_text(readme, encoding="utf-8") items = read_csv(OUT_DIR / "self_check_items.csv") if not any(r.get("item") == "EXECUTION_REVIEW_AUDIT_RECORDED" for r in items): items.append( { "item": "EXECUTION_REVIEW_AUDIT_RECORDED", "status": "PASS", "detail": f"audit={EXEC_AUDIT_ID}, message={EXEC_REVIEW_MESSAGE_ID}", } ) write_csv(OUT_DIR / "self_check_items.csv", items, ["item", "status", "detail"]) fail_count = sum(1 for r in items if r["status"] != "PASS") self_check = { "schema_version": "1.0", "run_id": RUN_ID, "generated_at": now_iso(), "status": "PASS_FOR_V1_FINAL_CONCLUSION_EXECUTION_REVIEW_PASSED" if fail_count == 0 else "FAIL", "pass_count": len(items) - fail_count, "fail_count": fail_count, "items_path": "self_check_items.csv", } write_json(OUT_DIR / "self_check.json", self_check) (OUT_DIR / "self_check.md").write_text( f"""# 自检摘要 - status:`{self_check['status']}` - PASS:{self_check['pass_count']} - FAIL:{self_check['fail_count']} - 检查项:`self_check_items.csv` """, encoding="utf-8", ) package_files = [] for p in OUT_DIR.rglob("*"): if not p.is_file(): continue if p.name in {"manifest.csv", "manifest.json"}: continue package_files.append(file_row(p)) package_files.sort(key=lambda r: str(r["path"])) write_csv(OUT_DIR / "manifest.csv", package_files, ["path", "size", "sha256"]) write_json( OUT_DIR / "manifest.json", { "schema_version": "1.0", "run_id": RUN_ID, "generated_at": now_iso(), "files": package_files, }, ) print( json.dumps( { "run_id": RUN_ID, "status": self_check["status"], "execution_review_audit_id": EXEC_AUDIT_ID, "manifest_files": len(package_files), }, ensure_ascii=False, ) ) if __name__ == "__main__": main()