TOML Schema

The .hz.toml format for declarative backtest configs

Presets are TOML files that describe a full backtest configuration. The preset loader parses them and constructs the arguments to hz.run().

Top-level fields

toml
mode = "backtest"     # backtest | paper | shadow | live

[asset_classes]
classes = ["equity"]

[[universe]]
type = "static"
markets = ["AAPL", "MSFT", "NVDA"]
asset_class = "equity"

[[strategies]]
type = "horizon.quant.BollingerMeanRev"
window = 20
entry_z = 2.0

[portfolio]
type = "kelly"
kelly_fraction = 0.25

[risk]
profile = "moderate"
max_gross_leverage = 1.0

[venues.paper]
type = "paper"
initial_cash_usd = 100_000

[backtest]
start = "2023-01-01"
end = "2024-12-31"
initial_cash_usd = 100_000

Sections

What’s NOT in presets

Presets cover the common case. For advanced features, use the Python API:

  • Custom Python strategies (beyond dotted-path imports)
  • Full RiskConfig: stacked drawdown guards, custom stops, per-asset-class rules
  • Custom sizers
  • Custom data sources
  • Custom executors
  • LifecycleConfig
  • MetricsConfig

The preset is the “80% case”. zero-code config for standard backtests. Anything more sophisticated uses Python.

Loading from Python

python
from horizon.presets_loader import load_preset

kwargs = load_preset("my_preset.hz.toml")
# kwargs is a dict ready to pass to hz.run(**kwargs)

# Override anything before running
kwargs["data_source"] = my_custom_source
result = hz.run(**kwargs)

Validation

Parsing errors raise ValueError at load time:

python
# Unknown portfolio type
[portfolio]
type = "nonsense"
# → ValueError: Unknown portfolio type 'nonsense'

# Missing strategy type
[[strategies]]
lookback = 20
# → ValueError: strategy entry missing 'type'

Errors are caught at load: you don’t discover bad config 10 bars into a backtest.

Next