diff --git a/src/easy_tdx/backtest/strategies/presets.py b/src/easy_tdx/backtest/strategies/presets.py index 2f360f5..655cb2f 100644 --- a/src/easy_tdx/backtest/strategies/presets.py +++ b/src/easy_tdx/backtest/strategies/presets.py @@ -98,6 +98,129 @@ STRATEGY_PRESETS: dict[str, dict[str, list[Any]]] = { # capital 仅作粗档扫描(1千万/1亿/10亿股),覆盖小盘→大盘 "capital": [1e7, 1e8, 1e9, 1e10], }, # 4 + # ── V1.30.2 存量指标补齐 ──────────────────────────────────────────────── + "psy_reversal": { + "n": [12, 20], + "oversold": [20, 25, 30], + }, # 6 + "mtm_cross": { + "n": [6, 12, 24], + }, # 3 + "roc_zero": { + "n": [6, 12, 24], + }, # 3 + "expma_cross": { + "n1": [5, 10, 12], + "n2": [26, 50, 60], + }, # 9(n1 None: + """注册表与 STRATEGY_PRESETS 键集一一对应(双向:不多不少)。""" + from easy_tdx.backtest.strategies import ( + builtin, # noqa: F401 # 触发注册 + get_registry, + ) + from easy_tdx.backtest.strategies.presets import STRATEGY_PRESETS + + names = set(get_registry().names()) + missing = names - set(STRATEGY_PRESETS) + extra = set(STRATEGY_PRESETS) - names + assert not missing, f"这些策略无预设网格,会被一键寻优静默跳过: {sorted(missing)}" + assert not extra, f"这些预设指向未注册的策略: {sorted(extra)}" + + def test_preset_values_within_param_bounds(self) -> None: + """预设取值必须在参数 schema 边界内(否则寻优端点 422)。""" + from easy_tdx.backtest.strategies import ( + builtin, # noqa: F401 # 触发注册 + get_registry, + ) + from easy_tdx.backtest.strategies.presets import STRATEGY_PRESETS + + registry = get_registry() + for name, grid in STRATEGY_PRESETS.items(): + params = {p.name: p for p in registry.get(name).params} + for pname, values in grid.items(): + assert pname in params, f"{name}: 预设参数 {pname} 不在 schema 中" + for v in values: + params[pname].validate(v) # 越界抛 ValueError + + def test_preset_grid_size_within_limit(self) -> None: + """单策略笛卡尔积 ≤ 200(ParamGridOptimizer.MAX_GRID_POINTS)。""" + import math + + from easy_tdx.backtest.strategies.presets import STRATEGY_PRESETS + + for name, grid in STRATEGY_PRESETS.items(): + size = math.prod(len(v) for v in grid.values()) if grid else 1 + assert size <= 200, f"{name}: 预设网格 {size} 点超上限"