pybroker.optimize module
Hyperparameter declaration and optimization with Optuna.
Hyperparams declare tunable values for indicators and executions. Each
hyperparam is registered globally by name via hyperparam() and
resolved to a concrete int or float at backtest or optimization time.
Pass hyperparams as keyword arguments to
pybroker.indicator.indicator(), or list them on
pybroker.strategy.Strategy.add_execution() to read them inside an
execution with ctx.hyperparam(name).
- class Hyperparam(name: str, default: int | float, low: int | float, high: int | float, step: int | float)[source]
Bases:
objectDeclares a named hyperparameter with bounds and step size.
Created with
hyperparam()and registered globally byname.- name
Unique identifier used in indicator kwargs, execution hyperparam lists, and optimization results.
- Type:
- default
Value for backtests and the baseline during optimization. Should lie within
[low, high].
- high
Maximum candidate value searched during optimize (inclusive). Candidate values are
low,low + step, … up to the largest value not exceedinghigh.
- step
Spacing between candidate values. Must be positive. Integer hyperparams use integer steps; float hyperparams use float steps with values rounded to match Optuna stepped suggestions.
Examples
Indicator period from 5 to 50 in steps of 5:
period = hyperparam("period", default=14, low=5, high=50, step=5)
- class ObjectiveBundle(objective: Callable[[Trial], float], search_space: SearchSpace, score_overrides: Callable[[dict[str, Any]], float])[source]
Bases:
objectReturn value of
make_objective().- search_space: SearchSpace
- class OptimizeMixin[source]
Bases:
objectMixin implementing hyperparameter optimization.
- optimize(score_fn: Callable[[TestResult], float], *, sampler: str | BaseSampler = 'grid', n_trials: int | None = None, direction: str = 'maximize', seed: int | None = None, windows: int | None = None, study: optuna.Study | None = None, pruner: optuna.pruners.BasePruner | None = None, train_size: float = 0.5, lookahead: int = 1, start_date: str | datetime | None = None, end_date: str | datetime | None = None, timeframe: str = '', between_time: tuple[str, str] | None = None, days: Any | None = None, warmup: int | None = None, parallel_indicators: bool = False, adjust: Any | None = None, calc_bootstrap: bool = False, verbose: bool = False) OptimizeResult[source]
Searches
pybroker.optimize.hyperparam()values on a training window, then evaluates the best values on the held out test window.Data supplied by the
pybroker.data.DataSourceis split into train and test as specified bytrain_size. Every trial backtests the train window with one combination of hyperparameter values and scores it withscore_fn. The winning combination is then replayed on the test window, whichscore_fnnever sees.Pretrained models (
model(..., pretrained=True)) are loaded per train window and reused across that window’s trials. Trainable models are not supported; tune them insidetrain_fnwith a validation split, or usepybroker.strategy.Strategy.walkforward().- Parameters:
score_fn –
Callable[[TestResult], float]that scores one trial’s train window backtest. Maximized by default; seedirection.sampler – How candidate values are chosen.
"grid"(the default) exhaustively enumerates every combination,"tpe"usesoptuna.samplers.TPESampler,"random"usesoptuna.samplers.RandomSampler. Anoptuna.samplers.BaseSamplerinstance is also accepted; it is deep-copied and re-seeded per window, and a multi-window run ships copies to worker processes, so it must be picklable. Grid and random samplers evaluate trials in parallel on the configured workers. Any other sampler —"tpe", or an instance that is not aGridSamplerorRandomSampler— is adaptive, and evaluating its trials in batches would change the values it proposes and tie results to the worker count; its trials therefore run sequentially, and an info-level log message notes that parallelism was disabled.n_trials – Number of trials to run. Required for every sampler except
"grid", where it defaults to the full grid size and a smaller value samples that many combinations at random.direction –
"maximize"(default) or"minimize"score_fn.seed – Random seed for the sampler and for bootstrap metrics. Defaults to
None, which does not reproduce.windows – When greater than
1, hyperparameters are optimized separately in each ofwindowswalkforward windows and the test windows are stitched into one continuous result. Defaults toNone, a single train/test split.study – Existing
optuna.study.Studyto record trials in, for example one backed by persistent storage. The study’s own sampler and pruner are used, and its direction must matchdirection. Not supported whenwindowsis greater than1.pruner –
optuna.pruners.BasePrunerattached to the created study. Each trial is one complete backtest with no intermediate values to report, so pruning never actually triggers.train_size – Fraction of each window used for training, exclusive of
0and1. Defaults to0.5.lookahead – Number of bars in the future of the target prediction. Held out between train and test to prevent training data from leaking across the boundary, in the bars of the timeframe each model is fitted on: a model bound to an interval with
pybroker.model.ModelSource.intervals()holds outlookaheadbars of that interval, not of the base timeframe. Defaults to1.start_date – Starting date of the optimization (inclusive). Must be within the range passed to the
pybroker.strategy.Strategyconstructor.end_date – Ending date of the optimization (inclusive). Must be within the range passed to the
pybroker.strategy.Strategyconstructor.timeframe – Formatted string specifying the timeframe resolution of the data, as in
pybroker.strategy.Strategy.walkforward().between_time –
tuple[str, str]of times of day e.g.('9:30', '16:00')used to filter the data (inclusive).days – Days (e.g.
"mon","tues") used to filter the data.warmup – Number of bars that need to pass before running the executions. Must be greater than
0when set.parallel_indicators – If
True,pybroker.indicator.Indicatordata is computed in parallel using multiple processes. Defaults toFalse.adjust – The type of adjustment to make to the
pybroker.data.DataSource.calc_bootstrap – Whether to compute randomized bootstrap evaluation metrics for the test result. Defaults to
False.verbose – Whether to log every trial’s backtest – indicator computation, test split progress bars, and Optuna’s own trial logging. Defaults to
False, which logs the optimization summary and the final test window evaluation only.
- Returns:
OptimizeResultwith the winning hyperparameter values, the train window score they earned, and the test windowpybroker.strategy.TestResultthey produced. Whenwindowsis greater than1,best_params,best_score, andstudydescribe the last window whileresultis stitched across all of them; seeOptimizeResult.windowsfor the per-window results.- Raises:
ValueError – If no executions were added, if any model source is trainable, if
train_sizeis not between0and1exclusive, ifwarmupis not greater than0, ifwindowsis not greater than0, ifstudyis combined withwindowsgreater than1or has a conflicting direction, or if the dates fall outside the range passed to thepybroker.strategy.Strategyconstructor.
- class OptimizeResult(best_params: dict[str, Any], best_score: float, result: TestResult, study: optuna.Study, windows: tuple[WindowOptimizeResult, ...] | None = None)[source]
Bases:
objectResult of
Strategy.optimize().- best_params
Winning hyperparameter values, including the ones that were fixed rather than searched. When
windowsis set, these are the last window’s values, since each window is tuned separately.
- best_score
score_fnvalue thatbest_paramsearned on the train window. Whenwindowsis set, this is the last window’s score.- Type:
- result
pybroker.strategy.TestResultfor the test window. Whenwindowsis set, this is a single continuous result stitched from every window’s test data, with positions and cash carried across window boundaries.- Type:
- study
optuna.study.Studyholding the trials. Whenwindowsis set, this is the last window’s study; seewindowsfor the rest.- Type:
optuna.Study
- windows
Per-window tuning results, or
Nonefor a single train/test split.- Type:
Optional[tuple[WindowOptimizeResult, …]]
- class SearchSpace(hyperparams: frozenset[str], specs: Mapping[str, Hyperparam])[source]
Bases:
objectSearchable hyperparameters collected from a strategy.
Only includes hyperparams with
low < highthat are passed to Optuna duringStrategy.optimize().- specs
Mapping of hyperparam name to
Hyperparamspec.- Type:
Mapping[str, pybroker.optimize.Hyperparam]
- class WindowOptimizeResult(params: dict[str, Any], study: Study, train_score: float, train_start_date: datetime | None = None, train_end_date: datetime | None = None, test_start_date: datetime | None = None, test_end_date: datetime | None = None, execution_symbols: dict[int, frozenset[str]] | None = None)[source]
Bases:
objectPer-window walk-forward optimization result.
Holds the values a window was tuned to, not a backtest of its own: the single out-of-sample
pybroker.strategy.TestResultlives onOptimizeResult.result, stitched across every window.- params
Winning hyperparameter values for this window, including the ones that were fixed rather than searched.
- study
optuna.study.Studyholding this window’s trials.- Type:
- train_start_date
First date of the window’s train data, or
Nonewhen the train split is empty.- Type:
datetime.datetime | None
- train_end_date
Last date of the window’s train data, or
Nonewhen the train split is empty.- Type:
datetime.datetime | None
- test_start_date
First date of the window’s test data – the span its tuned
paramstrade in the stitchedOptimizeResult.result– orNonewhen the test split is empty.- Type:
datetime.datetime | None
- test_end_date
Last date of the window’s test data, or
Nonewhen the test split is empty.- Type:
datetime.datetime | None
- execution_symbols
Symbols each execution id resolved to for this window when a
pybroker.common.SymbolSelectorchose them, orNonewhen no execution uses a selector.
- build_run_hyperparams(specs: Mapping[str, Hyperparam], overrides: dict[str, Any] | None = None) dict[str, Any][source]
Builds the hyperparam dict for a single backtest or trial run.
- Parameters:
specs – All hyperparams reachable from the strategy.
overrides – Trial or user-supplied values to merge over defaults.
- Returns:
Dict of
name -> valuefor every hyperparam inspecs.
- collect_hyperparams(strategy: _ExecutionsHost) dict[str, Hyperparam][source]
Collects all hyperparams reachable from
strategy.
- collect_search_space(strategy: _ExecutionsHost) SearchSpace[source]
Collects searchable hyperparams reachable from
strategy.
- hyperparam(name: str, *, default: int | float, low: int | float, high: int | float, step: int | float) Hyperparam[source]
Creates and registers a
Hyperparam.- Parameters:
name – Unique identifier for the hyperparam. Referenced in indicator kwargs,
add_execution(..., hyperparams=[...]), andctx.hyperparam(name).default – Value used for backtests.
low – Minimum candidate value searched during optimize (inclusive).
high – Maximum candidate value searched during optimize (inclusive).
step – Spacing between candidate values. Must be positive.
- Returns:
The registered
Hyperparaminstance.
- make_objective(strategy: _OptimizeTrialHost, score_fn: Callable[[TestResult], float], *, train_rows: np.ndarray, df: pd.DataFrame, hyperparams: Mapping[str, Hyperparam], search_space: SearchSpace, invariant_indicator_data: dict[IndicatorSymbol, pd.Series], window_executions: set[Execution], master_store: Any, interval_data: Any, parallel_indicators: bool, warmup: int | None, pretrained_models: Mapping[ModelSymbol, TrainedModel], exit_dates: Mapping[str, np.datetime64], verbose: bool = False) ObjectiveBundle[source]
Builds an Optuna objective for train-window scoring.
When
verboseisFalse(the default), each trial’s backtest runs with logging suppressed so that per-trial progress bars do not repeat for every combination searched.