fix: 如实说明买卖理由的覆盖边界(哪些不算买卖点)

`unimplemented` 与「买卖说明」里都没写清一件事:理由覆盖的是 **signal_history 里的
每个买卖点(含涨停/停牌/跌停/现金不足等未成交情形)**,而「当日排名在 TopN 之外、
策略本来就无意买入」的候选根本不算买卖点 —— 用户看不到某只票的买入理由时,
应该能立刻分清「是漏了记录」还是「策略本来就没打算买」。

- 组合引擎与单策略引擎的 `_unimplemented` 各加一条说明,指向 `selection_history`
  可查完整候选与名次(AGENT.md §24:没实现/有边界的要显式写出)。
- 「买卖说明」卡片底部同步写出这条边界。
This commit is contained in:
Simon
2026-10-01 18:15:26 +08:00
parent a3055eff5d
commit 57d6082f91
3 changed files with 15 additions and 0 deletions
+5
View File
@@ -173,6 +173,11 @@ _UNIMPLEMENTED_BASE = [
"多策略打分采用 Borda 秩和(各策略 1/名次 求和):不假设不同策略的因子分值可比,"
"但极端情况下某策略覆盖极少股票会使其秩和贡献偏大"
),
(
"买卖说明覆盖 signal_history 里的每个买卖点(含涨停/停牌/现金不足等未成交情形);"
"但「当日排名在 TopN 之外、策略本来就无意买入」的候选不计为买卖点,"
"要看完整候选与名次请查选股明细(selection_history)"
),
]
+7
View File
@@ -927,6 +927,13 @@ class TopKBacktestRunner:
def _unimplemented(self, curve_note: str | None = None) -> list[str]:
notes = list(_DEFAULT_UNIMPLEMENTED) + unimplemented_notes(self.spec.portfolio)
# 如实说明买卖理由的覆盖边界:每个买卖点(含涨停/停牌/现金不足等未成交)都有理由,
# 但「排名在 TopN 之外、策略本来就无意买入」的候选不算买卖点(看选股明细即可)。
notes.append(
"买卖说明覆盖 signal_history 里的每个买卖点(含涨停/停牌/现金不足等未成交情形);"
"「当日排名在 TopN 之外、策略本来就无意买入」的候选不计为买卖点,"
"要看完整候选与名次请查选股明细(selection_history)"
)
if self._no_prev_close_symbols:
notes.append(
f"有 {len(self._no_prev_close_symbols)} 只标的成交时缺少上一有效收盘价,"
+3
View File
@@ -302,6 +302,9 @@ export function TradeReasonsCard({
{withReason < signals.length
? ` 有 ${signals.length - withReason} 条来自 2026-10 之前的旧归档,当时还没有结构化理由。`
: ""}
{" "}覆盖边界:「当日排名在 TopN 之外、策略本来就无意买入」的候选不算买卖点
(要看完整候选与名次,请看选股明细);每个真正的买卖点 —— 包括涨停、停牌、
跌停、现金不足这类没成交的 —— 都在上表里。
</div>
</Card>
);