-
解析日期与目录。
- 如果用户指定了
signal date,直接使用。
- 如果没有指定,自动解析"已拿到收盘数据的最新交易日"。
- 永远计算真实的
next trade date。
- 如果收盘数据不可用,停止并说明 blocker,不要伪造报告。
- 默认目录:
outputs/YYYYMM/YYYYMMDD/stock-top8/。
-
调用 compute_auto_screening_results 拿 payload。
- 这是
src/main.py:622 的纯函数版 --auto 流水线,无 IO 副作用,返回 JSON-serializable dict。
- 不要走
uv run python src/main.py --auto CLI,那会落盘 + 打印表格,纯函数版更快更干净。
- 调用方式(在 Python REPL 或一次性脚本内):
from src.main import compute_auto_screening_results
payload = compute_auto_screening_results(trade_date="YYYYMMDD", top_n=20)
recommendations = payload["recommendations"]
market_state = payload["market_state"]
top_n=20 而非 top_n=8:留出排序空间,BUY 通过的可能 < 8,需要从 HOLD 中补足。
- 如果
recommendations 为空,停止并说明 blocker。
-
调用 detect_market_state 拿 regime。
- 不要从 payload 的
market_state 字段直接读 regime 字符串,要用 detect_market_state(trade_date).regime_gate_level,这是 regime 判定的唯一真源(见 src/screening/top_picks.py:114 注释)。
from src.screening.market_state import detect_market_state
ms = detect_market_state("YYYYMMDD")
regime = ms.regime_gate_level
-
对每条 recommendation 调用 build_front_door_verdict 拿 BUY/HOLD/AVOID + signal_horizon。
from src.screening.investability import build_front_door_verdict
for rec in recommendations:
verdict = build_front_door_verdict(rec, market_regime=regime)
rec["_verdict"] = verdict
build_front_door_verdict 内部已实现 NS-11(优先读 composite_score_gated pre-bonus 分数判 BUY gate,不被 consecutive bonus 放水)、C220(T+5 OR T+10 短期 horizon BUY gate)、C245(crisis/risk_off regime 下只看 T+10,BUY 全部降级 HOLD)、C221(signal_horizon 标注)。不要在 skill 里重复实现这些逻辑。
-
排序与截取 8 只。
- 排序键(与
rank_recommendations_by_investability 一致,C222):
BUY 优先 (action="BUY" 排最前)
→ composite_score_gated 降序
→ max(t5_edge, t10_edge) 降序
→ max(t5_winrate, t10_winrate) 降序
→ bucket_sample_count 降序
→ ticker 升序 (tie-break)
- 取前 8 只。如果 BUY + HOLD 不足 8 只,从 AVOID 中按相同键补足,并在报告中明确标注"备选观察"。
- 如果 8 只中有同行业/同概念重复,可以保留(不像
select_representative_candidates 那样去重),因为用户要的是"最佳 8 只"而非"分散 8 只";但在报告中提示行业集中度。
-
渲染报告。
- MANDATORY:起草前加载
references/final-doc-spec.md。
- 输出 1 份 Markdown:
outputs/YYYYMM/YYYYMMDD/stock-top8/stock-top8-YYYYMMDD.md
- 输出 1 份 JSON:
outputs/YYYYMM/YYYYMMDD/stock-top8/stock-top8-YYYYMMDD.json
- 报告必须包含三硬区块(标题完全一致):
胜率/赔率诊断卡(Alpha)
执行触发/取消/升级/降级矩阵(Beta)
大盘-板块-赚钱效应环境卡(Gamma)
- 渲染 regime 历史 winrate 时,必须用
render_regime_winrate_line(regime, today=signal_date) 和 render_regime_multihorizon_line(regime, today=signal_date),让 as_of 与 staleness 警告自动出现(NS-5 诚实披露)。
from src.screening.regime_winrate import (
render_regime_winrate_line,
render_regime_multihorizon_line,
)
alpha_block_lines = [
render_regime_winrate_line(regime, today=signal_date_obj),
render_regime_multihorizon_line(regime, today=signal_date_obj),
]
-
交付前验证。
- 所有 8 只票都有 verdict(action / signal_horizon / invalidation_reason)。
- 所有票的
composite_score_gated、t5_edge、t5_winrate、t10_edge、t10_winrate、t30_edge、t30_winrate、bucket_sample_count 都从 recommendation 直接读取,不要重新计算或脑补。
- crisis/risk_off regime 下的 BUY 候选已自动降级为 HOLD(C245),报告里必须明说"本可 BUY 但被市场门控降级"。
- regime winrate 行带
as_of + staleness ⚠(如 stale)。
- 报告里写真实的
next trade date,不能写 N/A。
- 文件名用
signal date,不是 next trade date。