本页为你介绍 Freqtrade 的基本概念及其工作原理。
Freqtrade 术语¶
- 策略(Strategy):你的交易策略,告诉机器人该做什么。
- 交易(Trade):已开仓的持仓。
- 挂单(Open Order):当前已在交易所下单但尚未成交的订单。
- 交易对(Pair):可交易的币对,通常格式为 Base/Quote(如现货的
XRP/USDT
,合约的XRP/USDT:USDT
)。 - 周期(Timeframe):K 线的时间长度(如
"5m"
、"1h"
等)。 - 指标(Indicators):技术指标(SMA、EMA、RSI 等)。
- 限价单(Limit order):以指定价格或更优价格成交的限价订单。
- 市价单(Market order):保证成交,但可能因订单量影响价格。
- 当前利润(Current Profit):该交易当前的浮动(未实现)利润。主要用于机器人和 UI。
- 已实现利润(Realized Profit):已实现的利润。仅在部分出场时相关,具体计算逻辑见该文档。
- 总利润(Total Profit):已实现和未实现利润之和。相对数值(%)以该交易总投资为基准计算。
手续费处理¶
Freqtrade 的所有利润计算均包含手续费。
- 回测 / 超参数优化 / 模拟盘模式下,使用交易所默认手续费(最低档)。
- 实盘时,使用交易所实际手续费(包括 BNB 折扣等)。
交易对命名¶
Freqtrade 遵循 ccxt 命名规范。
在错误的市场使用错误的命名方式,通常会导致机器人无法识别该交易对,报错 "this pair is not available"
。
现货交易对命名¶
现货交易对命名为 base/quote
(如 ETH/USDT
)。
合约交易对命名¶
合约交易对命名为 base/quote:settle
(如 ETH/USDT:USDT
)。
机器人执行逻辑¶
以 dry-run
或实盘模式启动 freqtrade(使用 freqtrade trade
)会启动机器人并进入主循环。
这也会运行 bot_start()
回调。
默认情况下,机器人循环每隔几秒运行一次(由 internals.process_throttle_secs
控制),执行以下操作:
- 从持久化存储获取已开仓交易
- 计算当前可交易的交易对列表
- 下载交易对及所有信息性交易对的 OHLCV 数据 该步骤每根 K 线只执行一次,以避免不必要的网络流量
- 调用策略的
bot_loop_start()
回调 - 按交易对分析策略
- 调用
populate_indicators()
- 调用
populate_entry_trend()
- 调用
populate_exit_trend()
- 调用
- 更新交易的挂单状态
- 对已成交订单调用策略的
order_filled()
回调 - 检查挂单超时
- 对未成交进场单调用
check_entry_timeout()
回调 - 对未成交出场单调用
check_exit_timeout()
回调 - 对所有挂单调用
adjust_order_price()
回调- 对未成交进场单调用
adjust_entry_price()
(仅当未实现adjust_order_price()
时调用) - 对未成交出场单调用
adjust_exit_price()
(仅当未实现adjust_order_price()
时调用)
- 对未成交进场单调用
- 对未成交进场单调用
- 对已成交订单调用策略的
- 检查已持仓并视情况下出场单
- 考虑止损、ROI、出场信号、
custom_exit()
和custom_stoploss()
- 根据
exit_pricing
配置或custom_exit_price()
回调确定出场价格 - 下出场单前调用策略的
confirm_trade_exit()
回调
- 考虑止损、ROI、出场信号、
- 若启用,检查已开仓交易的持仓调整,调用
adjust_trade_position()
并视情况下补仓单 - 检查交易槽位是否可用(是否已达
max_open_trades
) - 检查进场信号,尝试开新仓
- 根据
entry_pricing
配置或custom_entry_price()
回调确定进场价格 - 在杠杆和合约模式下,调用
leverage()
回调确定杠杆倍数 - 调用
custom_stake_amount()
回调确定下单金额 - 下进场单前调用策略的
confirm_trade_entry()
回调
- 根据
该循环会不断重复,直到机器人被停止。
Freqtrade 机器人主循环流程图¶
主循环执行流程¶
关键步骤说明¶
1. 数据准备阶段¶
- 获取已开仓交易: 从数据库或文件系统读取当前持仓状态
- 计算交易对列表: 根据配置和策略确定可交易的交易对
- 下载 OHLCV 数据: 获取最新的价格和交易量数据
2. 策略分析阶段¶
- populate_indicators(): 计算技术指标
- populate_entry_trend(): 生成进场信号
- populate_exit_trend(): 生成出场信号
3. 订单管理阶段¶
- 更新挂单状态: 检查订单是否成交
- 处理超时订单: 对未成交订单进行调整或取消
- 价格调整: 根据市场情况调整订单价格
4. 持仓管理阶段¶
- 检查出场条件: 止损、ROI、出场信号等
- 持仓调整: 根据策略调整现有持仓
- 确认出场: 执行出场操作
5. 开仓管理阶段¶
- 检查槽位: 确认是否还有可用的交易槽位
- 信号检查: 寻找新的进场机会
- 确认开仓: 执行开仓操作
6. 循环控制¶
- 循环间隔: 由
internals.process_throttle_secs
控制 - 停止检查: 检查是否需要停止机器人
重要回调函数¶
回调函数 | 执行时机 | 用途 |
---|---|---|
bot_loop_start() | 每次循环开始 | 初始化或清理工作 |
populate_indicators() | 策略分析时 | 计算技术指标 |
populate_entry_trend() | 策略分析时 | 生成进场信号 |
populate_exit_trend() | 策略分析时 | 生成出场信号 |
order_filled() | 订单成交时 | 处理成交事件 |
adjust_order_price() | 订单超时时 | 调整订单价格 |
confirm_trade_entry() | 开仓前 | 确认开仓操作 |
confirm_trade_exit() | 出场前 | 确认出场操作 |
adjust_trade_position() | 持仓调整时 | 调整持仓大小 |
配置参数¶
internals.process_throttle_secs
: 控制循环间隔时间max_open_trades
: 最大同时开仓数量entry_pricing
: 进场价格策略exit_pricing
: 出场价格策略
这个流程图清晰地展示了 Freqtrade 机器人如何通过持续的主循环来管理交易,确保策略能够及时响应市场变化并执行相应的交易操作。
回测 / 超参数优化执行逻辑¶
回测 或 超参数优化 只执行上述部分逻辑,因为大多数交易操作都是完全模拟的。
- 加载配置交易对的历史数据。
- 调用一次
bot_start()
。 - 计算指标(每个交易对调用一次
populate_indicators()
)。 - 计算进出场信号(每个交易对调用一次
populate_entry_trend()
和populate_exit_trend()
)。 - 按 K 线循环,模拟进出场点。
- 调用策略的
bot_loop_start()
回调。 - 检查订单超时,通过
unfilledtimeout
配置或check_entry_timeout()
/check_exit_timeout()
回调。 - 对所有挂单调用
adjust_order_price()
回调。- 对未成交进场单调用
adjust_entry_price()
(仅当未实现adjust_order_price()
时调用!) - 对未成交出场单调用
adjust_exit_price()
(仅当未实现adjust_order_price()
时调用!)
- 对未成交进场单调用
- 检查进场信号(
enter_long
/enter_short
列)。 - 确认进出场(如策略实现则调用
confirm_trade_entry()
和confirm_trade_exit()
)。 - 调用
custom_entry_price()
(如策略实现)确定进场价格(价格会调整到开盘 K 线内)。 - 在杠杆和合约模式下,调用
leverage()
回调确定杠杆倍数。 - 调用
custom_stake_amount()
回调确定下单金额。 - 若启用,检查已开仓交易的持仓调整,调用
adjust_trade_position()
判断是否需补仓。 - 对已成交进场单调用
order_filled()
回调。 - 调用
custom_stoploss()
和custom_exit()
寻找自定义出场点。 - 基于出场信号、自定义出场和部分出场的退出:调用
custom_exit_price()
确定出场价格(价格会调整到收盘 K 线内)。 - 对已成交出场单调用
order_filled()
回调。
- 调用策略的
- 生成回测报告输出
实盘或 DryRun 与回测的区别¶
通过对比回测逻辑和正常主循环逻辑,我发现了以下主要差异:
主要差异分析¶
1. 数据加载方式¶
- 回测: 一次性加载配置交易对的历史数据
- 正常循环: 每次循环都下载最新的 OHLCV 数据
2. 初始化调用¶
- 回测: 调用一次
bot_start()
- 正常循环: 每次循环调用
bot_loop_start()
3. 指标计算频率¶
- 回测: 每个交易对调用一次
populate_indicators()
- 正常循环: 每次循环都重新计算指标
4. 信号计算频率¶
- 回测: 每个交易对调用一次
populate_entry_trend()
和populate_exit_trend()
- 正常循环: 每次循环都重新计算信号
5. 时间处理方式¶
- 回测: 按 K 线循环,模拟进出场点
- 正常循环: 实时处理,基于实际时间间隔
6. 订单处理¶
- 回测: 模拟订单成交,基于历史数据
- 正常循环: 实际下单到交易所,处理真实订单状态
7. 价格确定¶
- 回测: 价格调整到开盘/收盘 K 线内
- 正常循环: 基于实时市场价格
8. 回调函数调用时机¶
- 回测: 在模拟的 K 线时间点调用
- 正常循环: 在真实事件发生时调用
关键差异总结¶
方面 | 回测模式 | 正常循环模式 |
---|---|---|
数据来源 | 历史数据 | 实时数据 |
处理频率 | 按 K 线 | 按时间间隔 |
订单执行 | 模拟成交 | 真实成交 |
价格机制 | 基于 K 线价格 | 基于实时价格 |
时间精度 | K 线级别 | 毫秒级别 |
资源消耗 | 一次性计算 | 持续计算 |
重要影响¶
- 性能差异: 回测一次性处理所有数据,而正常循环持续处理
- 准确性差异: 回测基于历史数据,正常循环基于实时市场
- 延迟差异: 回测无网络延迟,正常循环有网络和交易所延迟
- 滑点差异: 回测通常假设无滑点,正常循环有真实滑点
这些差异解释了为什么回测结果与实际交易结果可能存在显著差异。