Skip to content

Hyperparameters

Hyperparameters let one strategy definition produce a controlled set of backtests. AQE expands the configured domains lazily, runs each combination sequentially, and records the exact values with a deterministic seed. A normal run keeps the strategy’s fallback values, so adding this feature does not change ordinary backtests.

Create a HyperParameterConfig and register each parameter once. values() defines a discrete set. range(min, max, increment) creates a numeric domain. The fallback supplied to HyperParameter::new() is used whenever no hyperparameter flag is supplied.

use aq_engine::prelude::*;
let mut hyperparameters = HyperParameterConfig::new();
hyperparameters
.set_sweep_id("ema-crossover-v1")
.add_hyper_parameter(
HyperParameter::new("atr_period", 14).values([10, 14, 20]),
)?
.add_hyper_parameter(
HyperParameter::new("ema_period", 21).range(10.0, 30.0, 5.0),
)?;

set_sweep_id() is optional. If it is omitted, AQE derives a stable ID from the configuration. Give it an explicit value when you want a recognizable, durable sweep folder name.

Read an active value from the strategy context with the typed helpers. The final argument is still the ordinary, hard-coded fallback.

let atr_period = aq_engine::core::strategy::hyperparameters::hyper_int(
ctx,
"atr_period",
14_usize,
);
let ema_period = aq_engine::core::strategy::hyperparameters::hyper_int(
ctx,
"ema_period",
21_usize,
);

Use the values while constructing an alpha model, insight pipe, or any other strategy component. AQE’s hyperparameter example wires both inputs into the built-in EMA crossover alpha and adds an insight submission pipeline.

Attach the configuration to each StrategyState, then keep using the ordinary state runners. A state with no configuration behaves exactly as it did before. A state with a configuration resolves --hyper-seed automatically before run_backtest() or run_live().

let mut state = build_strategy_state(timeframe.clone());
state.set_hyper_parameter_config(hyperparameters);
state.run_backtest(start, end, timeframe).await?;

For a full sweep, enumerate hyperparameters.process_runs(&args), create a fresh state for each selection, call set_hyper_parameter_config(config.clone()), then set_hyper_parameter_run(&selection, true) before the usual run_backtest(). A completed state owns mutable broker and strategy runtime state, so it cannot safely be reused for the next seed.

For live mode, use the same shape: attach the configuration and call state.run_live(None).await?. Live mode automatically resolves one selected seed and rejects a full sweep.

The artifact root is optional. Without it, results are written relative to the process working directory (or an adjacent strategy metadata location when available). It does not decide whether a run is a sweep: the selected command-line flag does.

Command Result
cargo run --release Run once with the regular fallback values.
cargo run --release -- --hyper-sweep Run every Cartesian combination sequentially.
cargo run --release -- --hyper-seed c89cfd30 Run one saved combination. A unique seed prefix is accepted.
cargo run --release -- --live --hyper-seed c89cfd30 Start one live session with that exact parameter selection.

The selected seed must match exactly one generated seed. AQE reports a clear error if a prefix matches none or more than one run. A live session accepts at most one seed, so --hyper-sweep --live is rejected. You do not need to calculate or pass a JSON permutation table by hand.

For a full sweep, AQE writes results beneath backtests/hyper/<sweep-id>/<seed>/. Each result contains the normal SQLite backtest database and metrics enriched with the seed and resolved values. The same strategy configuration plus the same seed reproduce the same parameter selection; market data and any nondeterministic external integration still need to be held constant for identical performance.

If you use AlgoQuant Studio, configure the same domains in the node editor and bind node inputs from the Hyperparameters sidebar. AQS generates the AQE configuration and handles seed selection for you. See Hyperparameters in AQS.