Freqtrade 回测与优化

本章详细介绍如何使用 Freqtrade 进行策略回测和参数优化,涵盖回测命令的使用、参数配置、结果分析以及基于 Hyperopt 的策略自动化调优,帮助读者科学评估策略表现。

回测基本命令

backtesting 命令

Freqtrade 的回测功能通过 backtesting 子命令实现:

# 基本回测命令
freqtrade backtesting --strategy MyStrategy

# 指定配置文件和交易对
freqtrade backtesting --strategy MyStrategy \
    --config user_data/config.json \
    --pairs BTC/USDT ETH/USDT

# 指定时间范围
freqtrade backtesting --strategy MyStrategy \
    --timerange 20240101-20240601

# 指定时间周期
freqtrade backtesting --strategy MyStrategy \
    --timeframe 1h

回测参数详解

参数说明示例
--strategy策略名称MyStrategy
--config配置文件路径user_data/config.json
--pairs交易对列表BTC/USDT ETH/USDT
--timerange回测时间范围20240101-
--timeframeK 线周期5m, 1h, 4h
--max-open-trades最大同时持仓数3
--stake-amount每笔投入金额100
--export导出交易记录trades
--dry-run-wallet模拟钱包余额10000
--fee自定义手续费率0.001
--cache缓存模式none, day, week

完整回测示例

# 完整回测命令
freqtrade backtesting \
    --config user_data/config.json \
    --strategy SmaCrossStrategy \
    --pairs BTC/USDT ETH/USDT SOL/USDT \
    --timerange 20231101-20240601 \
    --timeframe 1h \
    --max-open-trades 5 \
    --stake-amount 50 \
    --dry-run-wallet 10000 \
    --fee 0.001 \
    --export trades \
    --export-filename user_data/backtest_results/sma_cross_result

回测配置参数

配置文件中的回测设置

config.json 中预配置回测参数:

{
    "max_open_trades": 3,
    "stake_currency": "USDT",
    "stake_amount": 100,
    "tradable_balance_ratio": 0.99,
    "dry_run_wallet": 10000,
    "timeframe": "5m",
    "fiat_display_currency": "USD",
    "trading_mode": "spot",
    "backtest_breakdown": ["day", "week", "month"],
    "backtest_cache": "day"
}

时间范围指定

# 多种时间范围格式
--timerange 20240101-          # 从 2024-01-01 至今
--timerange -20240601           # 从最早到 2024-06-01
--timerange 20240101-20240601   # 指定起止日期
--timerange 20240101-20240131   # 单月回测
--timerange 20240101-20240107   # 单周回测

# 使用天数偏移
--timerange 365d                # 最近 365 天
--timerange 30d                 # 最近 30 天

多周期回测

使用 --timeframe-detail 参数获取更精细的回测数据:

# 策略使用 1h,但用 5m 数据精细化回测
freqtrade backtesting --strategy MyStrategy \
    --timeframe 1h \
    --timeframe-detail 5m

回测结果分析

结果输出解读

回测完成后,Freqtrade 会输出详细的统计信息:

========================================= SUMMARY METRICS =========================================
| Metric                      | Value                  |
|-----------------------------+------------------------|
| Pair(s)                     | BTC/USDT, ETH/USDT     |
| Timeframe                   | 1h                     |
| Strategy                    | SmaCrossStrategy       |
|                             |                        |
| Backtesting from            | 2024-01-01 00:00:00    |
| Backtesting to              | 2024-06-01 00:00:00    |
|                             |                        |
| Market change               | 45.23%                 |
| Profit (total)              | 12.34%                 |
| Profit (daily avg)          | 0.08%                  |
| Profit (annualized)         | 28.95%                 |
|                             |                        |
| Total trades                | 156                    |
| Trades per day              | 1.04                   |
| Started with                | 10000 USDT             |
| End value                   | 11234.00 USDT          |
|                             |                        |
| Win / Loss                  | 95 / 61                |
| Winrate                     | 60.90%                 |
|                             |                        |
| Max drawdown                | 8.45%                  |
| Drawdown (max)              | 845 USDT               |
| Drawdown (high)             | 11250 USDT             |
| Drawdown (low)              | 10405 USDT             |
| Drawdown (start)            | 2024-03-15 12:00:00    |
| Drawdown (end)              | 2024-04-10 08:00:00    |
|                             |                        |
| Avg duration                | 4:35:00                |
| Avg profit                  | 0.08%                  |
| Avg profit trade            | 7.91 USDT              |
|                             |                        |
| Best trade                  | 145.32 USDT            |
| Worst trade                 | -89.50 USDT            |
|                             |                        |
| Avg open trades             | 2.34                   |
| Max open trades             | 5                      |
|                             |                        |
| Avg realized P&L            | 0.08%                  |
| Avg realized P&L (USDT)     | 7.91                   |
| Avg total kept (USDT)       | 10007.91               |
|                             |                        |
| Profit factor               | 1.85                   |
| Expectancy                  | 0.06%                  |
| Expectancy (USDT)           | 7.91                   |
|                             |                        |
| Sharpe ratio                | 1.52                   |
| Sortino ratio               | 2.13                   |
| Calmar ratio                | 3.43                   |
|                             |                        |
| Stoploss                    | 12 (7.69%)             |
| ROI                         | 100 (64.10%)           |
| Exit signal                 | 44 (28.21%)            |
|                             |                        |
| Tag: sma_cross_bull         | 85 (54.49%)            |
| Tag: sma_cross_bear         | 71 (45.51%)            |
==================================================================================================

核心指标解读

指标含义优秀标准
Profit (total)总收益率> 10%(回测期)
Winrate胜率> 55%
Max drawdown最大回撤< 15%
Sharpe ratio夏普比率(风险调整收益)> 1.5
Sortino ratio索提诺比率(下行风险调整)> 2.0
Profit factor总盈利 / 总亏损> 1.5
Expectancy每笔交易期望收益正值
Avg duration平均持仓时间与策略预期一致
Calmar ratio年化收益 / 最大回撤> 3.0

导出详细交易记录

# 导出回测结果为 JSON
freqtrade backtesting --strategy MyStrategy \
    --export trades \
    --export-filename user_data/backtest_results/my_result

# 查看导出的交易明细
cat user_data/backtest_results/my_result.json

导出的 JSON 文件包含每笔交易的详细信息:

{
    "trades": [
        {
            "pair": "BTC/USDT",
            "stake_amount": 100,
            "open_date": "2024-01-15 08:00:00",
            "close_date": "2024-01-15 12:00:00",
            "open_rate": 42000.00,
            "close_rate": 43500.00,
            "profit_ratio": 0.0357,
            "profit_abs": 357.00,
            "enter_tag": "sma_cross_bull",
            "exit_reason": "exit_signal"
        }
    ],
    "locks": [],
    "best_pair": "BTC/USDT",
    "worst_pair": "ETH/USDT",
    "best_trade": {
        "pair": "SOL/USDT",
        "profit_ratio": 0.089
    }
}

回测分析命令

# 查看多个回测结果对比
freqtrade backtesting --strategy-list Strategy1 Strategy2 Strategy3

# 生成回测图表(需安装 plotly)
freqtrade backtesting --strategy MyStrategy --export trades
# 然后使用 plot_dataframe 查看
freqtrade plot-dataframe --strategy MyStrategy --pairs BTC/USDT

策略优化 (Hyperopt)

Hyperopt 概述

Hyperopt 是 Freqtrade 内置的参数自动优化工具,通过机器学习算法在参数空间中搜索最优组合:

# 运行 hyperopt 优化
freqtrade hyperopt --strategy MyStrategy \
    --hyperopt-loss SharpeHyperOptLoss \
    --spaces buy sell roi stoploss \
    --epochs 100

损失函数选择

损失函数优化目标适用场景
SharpeHyperOptLoss最大化夏普比率风险调整收益(推荐)
SortinoHyperOptLoss最大化索提诺比率关注下行风险
MaxDrawDownHyperOptLoss控制最大回撤保守型策略
CalmarHyperOptLoss最大化 Calmar 比率收益回撤平衡
ShortTradeDurHyperOptLoss短持仓时间短线策略
OnlyProfitHyperOptLoss仅最大化利润激进型策略
Custom自定义损失函数高级用户

优化空间配置

在策略中定义需要优化的参数空间:

from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter, BooleanParameter

class OptimizedStrategy(IStrategy):
    # 买入参数空间
    buy_rsi = IntParameter(20, 40, default=30, space="buy")
    buy_bb_lower = DecimalParameter(0.95, 1.05, default=1.0, decimals=2, space="buy")
    use_volume_filter = BooleanParameter(default=True, space="buy")

    # 卖出参数空间
    sell_rsi = IntParameter(60, 80, default=70, space="sell")
    sell_profit = DecimalParameter(0.01, 0.05, default=0.02, space="sell")

    # ROI 参数空间
    minimal_roi = {
        "0": 0.10,
        "30": 0.05,
        "60": 0.02,
        "120": 0
    }

    # 止损参数空间
    stoploss = -0.10

    # 追踪止损参数空间
    trailing_stop = BooleanParameter(default=True, space="trailing")
    trailing_stop_positive = DecimalParameter(-0.05, -0.01, default=-0.02, decimals=2, space="trailing")
    trailing_stop_positive_offset = DecimalParameter(0.02, 0.08, default=0.03, decimals=2, space="trailing")

运行 Hyperopt

# 优化所有参数空间
freqtrade hyperopt \
    --config user_data/config.json \
    --strategy OptimizedStrategy \
    --hyperopt-loss SharpeHyperOptLoss \
    --spaces all \
    --epochs 1000 \
    --timerange 20230101-20240601

# 只优化买入参数
freqtrade hyperopt \
    --strategy OptimizedStrategy \
    --spaces buy \
    --epochs 200

# 多空间组合优化
freqtrade hyperopt \
    --strategy OptimizedStrategy \
    --spaces buy sell roi stoploss \
    --epochs 500 \
    --print-all \
    --no-details

优化结果解读

Hyperopt 每完成一批 epoch 就会输出当前最佳结果:

Best result:

  ✓ 145/1000 epochs.
  Best result:
  - Best epoch: 89
  - Objective: -2.15432
  - Parameters:
      buy_rsi: 27
      sell_rsi: 73
      stoploss: -0.082
      trailing_stop: True
      trailing_stop_positive: -0.015
      trailing_stop_positive_offset: 0.045
      minimal_roi: {
          "0": 0.124,
          "37": 0.062,
          "58": 0.018,
          "119": 0
      }

  Results:
  - Profit: 23.45%
  - Winrate: 62.3%
  - Max drawdown: 6.78%
  - Sharpe ratio: 1.89
  - Total trades: 234

自定义损失函数

from freqtrade.optimize.hyperopt import IHyperOptLoss
from datetime import datetime

class CustomHyperOptLoss(IHyperOptLoss):
    """
    自定义损失函数:平衡收益与回撤
    """
    @staticmethod
    def hyperopt_loss_function(
        results: DataFrame,
        trade_count: int,
        min_date: datetime,
        max_date: datetime,
        config: dict,
        processed: dict,
        backtest_stats: dict,
        **kwargs
    ) -> float:
        """
        返回需要最小化的数值
        """
        total_profit = backtest_stats["profit_total" ]
        max_drawdown = backtest_stats["max_drawdown"]

        # 如果亏损,直接返回大数值
        if total_profit <= 0:
            return 100

        # 自定义评分:收益 / (回撤 * 回撤)
        # 惩罚高回撤
        score = total_profit / (max_drawdown ** 1.5)

        # 负值因为我们需要最小化
        return -score

参数调优建议

优化策略

  1. 分批优化:先优化买入参数,再优化卖出参数,最后优化 ROI 和止损
  2. 逐步缩范围:先用大步长搜索大范围,找到最佳区域后缩小范围精细搜索
  3. 多阶段验证:使用不同时间段的数据验证优化结果的稳定性

过拟合防范

# 使用多个时间段交叉验证
# 时间段 1:训练
freqtrade hyperopt --strategy MyStrategy --timerange 20220101-20231231 --epochs 500

# 时间段 2:验证
freqtrade backtesting --strategy MyStrategy --timerange 20240101-20240601

# 时间段 3:样本外测试
freqtrade backtesting --strategy MyStrategy --timerange 20240601-20241231

常见问题

问题原因解决方案
过拟合优化轮次过多,参数过度适配历史减少 epoch,增加样本外验证
参数不稳定参数在不同时间段表现差异大使用更长的回测周期,多时间段验证
回测盈利但实盘亏损回测存在未来信息或过度优化检查是否有数据泄露,简化策略逻辑
优化时间过长参数空间太大减少参数数量,缩小搜索范围
胜率高但亏损胜率高但亏损单平均亏损大优化止损策略,控制单笔亏损