refactor: screen() reuses run_combination(), single runner across combo sizes

- screen() now calls run_combination() internally, eliminating duplicated
  signal extraction/combination logic
- _run_combo_screen creates one CombinationRunner before the size loop,
  so signal cache is reused across 2-factor and 3-factor screens
- Add MAJORITY(2)=AND note to screen() docstring
This commit is contained in:
Justin Gu
2026-06-10 02:13:28 +08:00
parent 1e99feb7c2
commit 5691bb8432
2 changed files with 12 additions and 16 deletions
+7 -6
View File
@@ -97,12 +97,7 @@ def _run_combo_screen(
from math import comb
for size in combo_sizes:
total = comb(len(strategy_classes), size)
click.echo("\n" + "=" * 80)
click.echo(f"[*] {size}因子组合回测 (共{total}组, 模式={combo_mode})")
click.echo("=" * 80)
# 单个 Runner 跨 size 复用信号缓存,避免重复提取
runner = CombinationRunner(
strategy_classes=strategy_classes,
df=df,
@@ -110,6 +105,12 @@ def _run_combo_screen(
commission=commission,
)
for size in combo_sizes:
total = comb(len(strategy_classes), size)
click.echo("\n" + "=" * 80)
click.echo(f"[*] {size}因子组合回测 (共{total}组, 模式={combo_mode})")
click.echo("=" * 80)
results = runner.screen(combo_sizes=(size,), mode=combo_mode.upper())
if not results:
+4 -9
View File
@@ -398,6 +398,8 @@ class CombinationRunner:
Args:
combo_sizes: 要尝试的组合大小(如 (2, 3) 表示 2 因子和 3 因子组合)
mode: 信号合并模式(AND / OR / MAJORITY
注意:MAJORITY 模式下 2 因子需要两个都同意(等同 AND),
因为阈值 = 2/2 = 1.0,需 > 1.0 才触发。
filter_zero_trades: 是否过滤零交易组合
top_n: 只返回前 N 名(0 = 全部返回)
@@ -412,16 +414,9 @@ class CombinationRunner:
continue
for combo in itertools.combinations(range(n_factors), size):
result = self.run_combination(combo, mode=mode)
signals = [self._get_factor_signals(i) for i in combo]
# 合并信号
buy_mask, sell_mask = combine_masks(signals, mode=mode)
# 包装为策略并运行
combo_cls = _make_combo_strategy(buy_mask, sell_mask)
engine = self._make_engine(combo_cls)
result = engine.run(self._df)
name = " + ".join(s.name for s in signals)
results.append(