From 80d78226dc7aab7631540d71f8bfaac77cca3d52 Mon Sep 17 00:00:00 2001 From: Alexander Pietsch Date: Sun, 22 Feb 2026 15:09:53 +0700 Subject: [PATCH 1/2] feat: gate optimization by dof multiplier --- src/backtest/runner.py | 18 ++++++++++++++++++ src/config.py | 2 ++ 2 files changed, 20 insertions(+) diff --git a/src/backtest/runner.py b/src/backtest/runner.py index e6e8233..fb5d973 100644 --- a/src/backtest/runner.py +++ b/src/backtest/runner.py @@ -514,6 +514,24 @@ def run_all(self, only_cached: bool = False) -> list[BestResult]: else: search_space[name] = options + n_params = len(search_space) + dof_multiplier = self.cfg.param_dof_multiplier + min_bars_for_optimization = max(2000, dof_multiplier * n_params) + if search_space and len(df) < min_bars_for_optimization: + self.logger.info( + "skipping optimization due to insufficient bars", + collection=col.name, + symbol=symbol, + timeframe=timeframe, + bars=len(df), + min_bars=min_bars_for_optimization, + n_params=n_params, + dof_multiplier=dof_multiplier, + strategy=strat.name, + search_method=search_method, + ) + search_space = {} + best_val = -np.inf best_params: dict[str, Any] | None = None best_stats: dict[str, Any] | None = None diff --git a/src/config.py b/src/config.py index 8c390da..10c0289 100644 --- a/src/config.py +++ b/src/config.py @@ -50,6 +50,7 @@ class Config: engine: str = "pybroker" # pybroker engine param_search: str = "grid" # grid | optuna param_trials: int = 25 + param_dof_multiplier: int = 100 max_workers: int = 1 asset_workers: int = 1 param_workers: int = 1 @@ -127,6 +128,7 @@ def load_config(path: str | Path) -> Config: engine=str(raw.get("engine", "pybroker")).lower(), param_search=str(raw.get("param_search", raw.get("param_optimizer", "grid"))).lower(), param_trials=int(raw.get("param_trials", raw.get("opt_trials", 25))), + param_dof_multiplier=int(raw.get("param_dof_multiplier", 100)), max_workers=int(raw.get("max_workers", raw.get("asset_workers", 1))), asset_workers=int(raw.get("asset_workers", raw.get("max_workers", 1))), param_workers=int(raw.get("param_workers", 1)), From 4ac86ed5a2e87fbde6ae06d216bb081e4a436352 Mon Sep 17 00:00:00 2001 From: Alexander Pietsch Date: Sun, 22 Feb 2026 17:28:53 +0700 Subject: [PATCH 2/2] feat: make min bars configurable --- src/backtest/runner.py | 4 +++- src/config.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backtest/runner.py b/src/backtest/runner.py index fb5d973..2f6b4b4 100644 --- a/src/backtest/runner.py +++ b/src/backtest/runner.py @@ -516,7 +516,8 @@ def run_all(self, only_cached: bool = False) -> list[BestResult]: n_params = len(search_space) dof_multiplier = self.cfg.param_dof_multiplier - min_bars_for_optimization = max(2000, dof_multiplier * n_params) + min_bars_floor = self.cfg.param_min_bars + min_bars_for_optimization = max(min_bars_floor, dof_multiplier * n_params) if search_space and len(df) < min_bars_for_optimization: self.logger.info( "skipping optimization due to insufficient bars", @@ -527,6 +528,7 @@ def run_all(self, only_cached: bool = False) -> list[BestResult]: min_bars=min_bars_for_optimization, n_params=n_params, dof_multiplier=dof_multiplier, + min_bars_floor=min_bars_floor, strategy=strat.name, search_method=search_method, ) diff --git a/src/config.py b/src/config.py index 10c0289..d48e53d 100644 --- a/src/config.py +++ b/src/config.py @@ -51,6 +51,7 @@ class Config: param_search: str = "grid" # grid | optuna param_trials: int = 25 param_dof_multiplier: int = 100 + param_min_bars: int = 2000 max_workers: int = 1 asset_workers: int = 1 param_workers: int = 1 @@ -129,6 +130,7 @@ def load_config(path: str | Path) -> Config: param_search=str(raw.get("param_search", raw.get("param_optimizer", "grid"))).lower(), param_trials=int(raw.get("param_trials", raw.get("opt_trials", 25))), param_dof_multiplier=int(raw.get("param_dof_multiplier", 100)), + param_min_bars=int(raw.get("param_min_bars", 2000)), max_workers=int(raw.get("max_workers", raw.get("asset_workers", 1))), asset_workers=int(raw.get("asset_workers", raw.get("max_workers", 1))), param_workers=int(raw.get("param_workers", 1)),