Integration guide
Freqtrade
Freqtrade is an open-source crypto trading bot. You write a strategy in Python, backtest it on historical OHLCV data, and deploy it in dry-run or live mode — all from the same codebase.
Every trading strategy has hyperparameters — values you set before running it, like a stoploss percentage, a timeframe, ROI targets, or indicator periods. Picking the right combination by hand is slow and error-prone. Hyperparameter optimization (HPO) automates that search: instead of guessing, an algorithm systematically tries different combinations and measures which ones perform best.
HyperOptimizer runs that search for you in our infrastructure. You build a Docker image of your Freqtrade backtest, configure which parameters to tune and their ranges in our web dashboard, and we handle the rest: we execute your container with different parameter values (chosen by algorithms like Bayesian optimization), collect the metrics each run produces, and surface the best results in the dashboard. No local compute, no long-running hyperopt sessions on your machine.
HyperOptimizer vs Freqtrade's built-in Hyperopt
Freqtrade has its own Hyperopt feature (freqtrade hyperopt): it runs on your machine, uses Optuna, and optimizes strategy parameters (buy/sell spaces, ROI, stoploss, trailing stop, etc.) by running many backtests locally. With HyperOptimizer, the optimization runs in our infrastructure: you define which parameters to tune and their ranges in our web dashboard, we run each trial (one backtest per trial with parameters we inject via CLI), collect the metrics you print to stdout, and use our optimization algorithms (e.g. Bayesian) to choose the next parameter set. You get a managed experiment, results in the dashboard, and no need to run long hyperopt runs locally.
How it works
- You build a Docker image that contains Freqtrade, your strategy, and a small wrapper that reads our CLI args, runs one backtest, and prints metrics in our format.
- In our dashboard you configure which parameters to optimize (e.g.
hpo-stoploss,hpo-timeframe, strategy params) and their ranges. - We run your container for each trial with different
--hpo-*arguments. - Your wrapper parses those arguments, runs Freqtrade backtesting once with the given parameters, parses the result, and prints metrics to stdout in our required format.
- Our system parses container stdout and records metrics for each trial in the dashboard.
1. Receive HPO parameters from the command line
Use argparse (or any CLI parser) to read the hyperparameters we inject. We pass them as --hpo-<name>=<value>. Map them to Freqtrade's options or to your strategy's parameters.
import argparse
def parse_args():
p = argparse.ArgumentParser(description="HPO: Freqtrade backtest with CLI hyperparameters.")
p.add_argument("--hpo-timeframe", type=str, default="5m", help="Candle timeframe (e.g. 1m, 5m, 1h).")
p.add_argument("--hpo-max-open-trades", type=int, default=3)
p.add_argument("--hpo-stake-amount", type=str, default="unlimited", help="e.g. 100 or unlimited")
return p.parse_args()
# In main():
args = parse_args()
# Pass to freqtrade backtesting (e.g. --timeframe, --max-open-trades, --stake-amount)
# or write a config / strategy params from these valuesUse these values when calling the backtesting command or when building your config/strategy.
2. In your code: one backtest per trial
When we run a trial, we start your container with one set of --hpo-* arguments. Your wrapper should run a single Freqtrade backtest with those values. Typical command shape:
freqtrade backtesting --strategy MyStrategy --config user_data/config.json \
--timeframe 5m --max-open-trades 3 --dry-run-wallet 1000From a Python wrapper you can use subprocess or Freqtrade's Python API. Example with subprocess:
import subprocess
cmd = [
"freqtrade", "backtesting",
"--strategy", "MyStrategy",
"--config", "user_data/config.json",
"--timeframe", args.hpo_timeframe,
"--max-open-trades", str(args.hpo_max_open_trades),
"--dry-run-wallet", "1000",
"--export", "none", # optional: avoid writing files if you parse stdout
]
result = subprocess.run(cmd, capture_output=True, text=True)
# Parse result.stdout or result.returncode as neededFreqtrade prints a backtesting report to stdout, including a summary metrics table (Total profit %, Absolute profit, Sharpe, Sortino, trade count, etc.). You can parse that text, or use --export trades and --backtest-directory and then read the exported backtest result (e.g. the JSON in the backtest output zip) to get the same metrics programmatically.
3. Emit metrics to stdout so we can collect them
Our system collects trial results by scanning container stdout for lines in this form:
hpo.metrics.<key>=<json.dumps(value)>
Each metric must be on its own line, with the exact prefix hpo.metrics.. Values must be JSON-serializable. Use json.dumps(value, default=str) for non-JSON types.
Example: assume you parsed the backtest summary into variables (e.g. from the summary table or from the backtest result JSON):
import json
# Example: you parsed these from the backtest report or result JSON
metrics = {
"total_profit_pct": 5.48,
"absolute_profit": 54.774,
"total_trades": 77,
"sharpe": 3.75,
"sortino": 2.48,
"profit_factor": 1.29,
}
for key, value in metrics.items():
print(f"hpo.metrics.{key}={json.dumps(value, default=str)}")Once your script prints lines like these, we associate them with the trial and show them in the dashboard.
Summary
- Build a Docker image with Freqtrade, your strategy, and a wrapper that parses
--hpo-*and runs one backtest per run. - In our dashboard: create an experiment and configure which parameters to optimize (names and ranges); we run the trials.
- In your wrapper: parse HPO args, run
freqtrade backtestingwith those values (or write a config/strategy params from them), parse the backtest result, and print each metric ashpo.metrics.<key>={json.dumps(value)}to stdout.
For backtesting options and the result format, see the Freqtrade backtesting documentation. For Freqtrade's own hyperopt (local, Optuna-based), see Freqtrade Hyperopt.