最近用 Freqtrade 实现了一个经典的 MACD 策略——金叉做多、死叉做空,配合固定比例的止盈止损。跑了一遍回测后发现收益出乎意料地不错,趁热把整个过程记录下来,方便以后复盘和迭代。
策略的核心逻辑非常简洁:
- 入场信号:MACD 金叉(DIF 上穿 DEA)做多,死叉(DIF 下穿 DEA)做空,同时配合趋势过滤条件;
- 止盈止损出场:固定 8% 止盈(
minimal_roi = {"0": 0.08})、-3% 止损(stoploss = -0.03),不使用移动止损。注意代码中虽然定义了populate_exit_trend(反向交叉平仓逻辑),但use_exit_signal = False意味着出场信号并未启用——所有仓位均由 ROI 止盈或止损触发平仓; - 趋势过滤:做多要求 EMA15 > EMA30(短期均线在长期均线上方),做空则相反;同时要求 ADX(14) 的 20 周期均线 > 25 且当前 ADX 高于其自身均线,确保市场处于趋势状态而非横盘震荡。
下面按照”策略代码 → 回测配置 → 结果分析 → 可视化”的顺序,完整走一遍流程。
策略代码
完整策略文件如下。几个值得注意的细节:
- 多空双向:
can_short = True,同时处理做多和做空逻辑; - 出场方式:
use_exit_signal = False,出场不依赖自定义信号,完全由 ROI(+8% 止盈)和 stoploss(-3% 止损)接管。populate_exit_trend中的反向交叉逻辑在回测中并未实际生效; - 入场趋势过滤:做多要求 EMA15 > EMA30(短期均线在长期均线上方),做空则相反;ADX 过滤采用双重条件——ADX(14) 当前值高于其 20 周期均线(表明趋势强度在上升),且该均线本身 > 25(表明整体处于趋势市而非震荡市),两层过滤叠加能更有效地避开横盘噪音;
- 15 分钟K线:在信号频率和稳定性之间取了一个平衡;
- 参数可优化:MACD 的快慢线周期和信号线周期均设为
IntParameter,方便后续用 Hyperopt 调参。
1 | """ |
回测
Freqtrade 的回测只需要一行命令,--strategy 参数传入策略类名即可:
1 | docker exec freqtrade freqtrade backtesting --strategy MACDStrategy --timerange 20250101-20260705 |
回测结果分析
回测区间为 2025 年 1 月 1 日至 2026 年 7 月 5 日,共计约 550 天。以下是完整回测报告:
1 | 2026-07-07 09:42:28,610 - freqtrade.optimize.backtesting - INFO - Backtesting with data from 2025-01-01 00:00:00 up to 2026-07-05 00:00:00 (550 days). |
从回测数据中可以看出几个关键点:
收益概览
- 初始资金 1000 USDT,最终资金 1186.5 USDT,总收益率 18.65%,年化收益率(CAGR)12.02%。
- 值得注意的是,同期 BTC 市场整体下跌了 32.69%,策略在熊市中依然实现了正收益,说明做空端贡献了可观的 alpha。
多空表现差异明显
- 做多 30 笔,亏损 -8.21%;做空 37 笔,盈利 26.86%。这与同期市场下跌的大背景高度吻合——空头策略在熊市中天然占优。
盈亏比分析
- 胜率仅 31.3%(21 胜 / 46 负),但盈利单平均收益 8.0%,亏损单平均亏损仅 -3.11%(被止损截断),盈亏比高达 2.57:1。
- 这是一个典型的”低胜率、高盈亏比”策略——靠少数大盈利覆盖多次小亏损,最终实现整体盈利。Profit Factor 为 1.14,意味着每亏 1 元能赚回 1.14 元。
回撤风险
- 最大回撤 22.66%(约 274 USDT),回撤持续了 92 天(2026 年 2 月至 5 月),这段时间账户从盈利 210 USDT 跌至亏损 63 USDT。
- 最大连续亏损 9 笔,对心态是不小的考验。
改进方向
- 降低回撤:考虑加入 ATR 动态仓位管理或波动率过滤器,在波动剧烈时减小头寸;
- 提升胜率:代码中已有注释掉的 EMA200 趋势过滤和 ATR 蜡烛实体过滤,可以尝试开启后对比效果;
- 参数优化:MACD 的三个周期参数已设为可超参优化,后续可以通过 Hyperopt 寻找更优组合;
- 多交易对:目前仅回测了 BTC/USDT,扩展到 ETH 等其他主流币种可能提升策略稳健性。
Web UI 可视化
除了命令行输出,Freqtrade 还支持通过 Web UI 在浏览器中查看回测结果。在 K 线图上直接标注买卖点(三角图标),对于分析策略的入场出场时机非常有帮助。
首先在 user_data/config.json 中启用 API 服务器:
1 | "api_server": { |
这里 CORS_origins 决定了允许哪些来源访问 Web UI,需要与实际访问地址一致。
对应的 docker-compose.yml 配置:
1 |
|
注意 network_mode: "host" 让容器直接使用宿主机网络,省去了端口映射的麻烦。
启动命令:
1 | # --no-deps多个服务避免重复启动 |
如果服务部署在远程机器上,通过 SSH 隧道将端口转发到本地即可:
1 | ssh -L 8081:localhost:8081 user@remote-host |
然后在浏览器访问 http://127.0.0.1:8081 就能看到 Web 界面了。K 线上的三角标记清晰标注了每一笔交易的进出场点,对于复盘策略表现、发现潜在问题非常有价值。
