1
2026-07-19 228d838fdb7f7dde7edc4993fdbb9654c9c31df7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
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()