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- |
--timeframe | K 线周期 | 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
参数调优建议
优化策略
- 分批优化:先优化买入参数,再优化卖出参数,最后优化 ROI 和止损
- 逐步缩范围:先用大步长搜索大范围,找到最佳区域后缩小范围精细搜索
- 多阶段验证:使用不同时间段的数据验证优化结果的稳定性
过拟合防范
# 使用多个时间段交叉验证
# 时间段 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,增加样本外验证 |
| 参数不稳定 | 参数在不同时间段表现差异大 | 使用更长的回测周期,多时间段验证 |
| 回测盈利但实盘亏损 | 回测存在未来信息或过度优化 | 检查是否有数据泄露,简化策略逻辑 |
| 优化时间过长 | 参数空间太大 | 减少参数数量,缩小搜索范围 |
| 胜率高但亏损 | 胜率高但亏损单平均亏损大 | 优化止损策略,控制单笔亏损 |