Freqtrade Strategy

Freqtrade hyperopt guide: optimise a strategy without over-fitting it

Updated 31 Oct 2026 · 3 min read

Hyperopt runs your strategy's backtest hundreds of times with different parameter values and keeps the set that scores best. Used carefully it can improve a sound strategy. Used carelessly it produces strategies that look brilliant on past data and fail immediately afterwards.

Several strategies in our leaderboard are hyperopt products, such as Diamond and PowerTower. Their rules show what over-fitting looks like in practice.

Before you start

  • Hyperopt dependencies are included in the Docker image. For a manual install, run pip install -r requirements-hyperopt.txt.
  • You need downloaded data for the pairs and timeframe you will optimise. See the backtesting tutorial.
  • Hyperopt is CPU-heavy. It uses all cores by default; limit it with -j 2 on a small VPS.

Make parameters optimisable

Hyperopt only changes values you declare as parameters in your strategy class:

from freqtrade.strategy import IntParameter, DecimalParameter

class MyStrategy(IStrategy):
    buy_rsi = IntParameter(10, 40, default=30, space="buy")
    sell_rsi = IntParameter(60, 90, default=70, space="sell")

    def populate_entry_trend(self, dataframe, metadata):
        dataframe.loc[dataframe["rsi"] < self.buy_rsi.value, "enter_long"] = 1
        return dataframe

Keep ranges realistic. A range that allows RSI thresholds of 1 to 100 invites the optimiser to find coincidences.

Run hyperopt

freqtrade hyperopt --config user_data/config.json \
  --strategy MyStrategy \
  --hyperopt-loss SharpeHyperOptLossDaily \
  --spaces buy sell \
  --timerange 20230101-20240101 \
  -e 300

-e sets the number of epochs (test runs). A few hundred is a reasonable start.

Choosing spaces

The --spaces option controls what hyperopt changes:

Space Optimises
buy / enter Entry parameters
sell / exit Exit parameters
roi The take-profit table
stoploss The stoploss value
trailing Trailing stop settings
trades Max open trades
protection Protection parameters
default Everything except trailing, trades and protection
all Everything

Optimising everything at once creates a huge search space. A better order is: entry and exit logic first, then ROI and stoploss, then trailing separately, which is also what the freqtrade docs recommend for the trailing space.

Choosing a loss function

The loss function defines what "best" means. Freqtrade includes several, among them:

Loss function Prefers
SharpeHyperOptLossDaily Smooth daily returns relative to volatility
SortinoHyperOptLossDaily Like Sharpe, but only penalises downside volatility
CalmarHyperOptLoss Return relative to max drawdown
MaxDrawDownRelativeHyperOptLoss Low drawdown
ProfitDrawDownHyperOptLoss Profit with a drawdown penalty
MultiMetricHyperOptLoss A balance of profit, drawdown, profit factor, expectancy and win rate, with a penalty for too few trades
OnlyProfitHyperOptLoss Profit only

Avoid OnlyProfitHyperOptLoss for anything you plan to run. It happily selects strategies with huge drawdowns. Risk-adjusted functions such as Sharpe, Sortino or Calmar usually generalise better.

Apply the results

When hyperopt finishes, it prints the best parameters and writes them to a JSON file next to your strategy (for MyStrategy.py, the file is MyStrategy.json). Freqtrade loads that file automatically next time the strategy runs. You can also paste the printed buy_params and sell_params blocks into the class.

Review other good results with:

freqtrade hyperopt-list --best
freqtrade hyperopt-show -n 25

Check for over-fitting

This is the step most people skip. Do all three:

  1. Out-of-sample test. Optimise on one period, then backtest the result on a later period hyperopt never saw. In the command above we optimised on 2023, so test on 2024:

    bash freqtrade backtesting --strategy MyStrategy --timerange 20240101-20250101

    If performance collapses, the parameters fitted noise.

  2. Sanity-check the values. If the best RSI entry is 90, or a rule compares price to volume, the optimiser found a coincidence, not a pattern.

  3. Look at neighbouring values. Good parameters sit on a plateau: nearby values perform similarly. If changing RSI from 28 to 30 turns profit into loss, the result is fragile.

Signs of an over-fitted strategy

  • Very few trades with a very high win rate.
  • Oddly precise numbers, such as a stoploss of −34.338%.
  • Rules with no market logic behind them.
  • Excellent results on one pair and losses on others.
  • A smooth in-sample equity curve followed by an immediate drawdown out of sample.

Next steps

  • Compare the hand-built and hyperopt-generated strategies in our leaderboard.
  • Dry-run any optimised strategy for several weeks before using real money.

Ready to connect an exchange?

Freqtrade needs an exchange account with API access. Bybit supports both spot and futures in freqtrade and offers a demo mode for testing.

Affiliate link: we may earn a commission if you sign up, at no cost to you.

Related guides