9.8 KiB
9.8 KiB
adjust-trade-position 回调函数详细翻译与解释
该回调函数是 Freqtrade 交易策略中用于动态调整持仓的核心功能,需手动开启才能使用,支持通过加仓( DCA 策略)或减仓优化风险与收益,但需注意其对性能的影响及特殊计算规则。
一、基础配置与启用
要使用 adjust_trade_position(),必须先在策略类中启用相关配置,否则函数不会被调用。
-
核心启用参数
- 需在策略类中添加
position_adjustment_enable = True,默认值为False(禁用)。 - 启用后,Freqtrade 启动时会显示警告,提示该功能可能影响性能,需合理设计逻辑。
- 需在策略类中添加
-
关键限制参数
max_entry_position_adjustment:限制单次交易的额外加仓次数(初始开仓不计入)。- 默认值为
-1,表示无限制。 - 示例设置
max_entry_position_adjustment = 3,意味着初始开仓后最多可额外加仓 3 次。
- 默认值为
max_dca_multiplier:(常用于 DCA 策略)控制单次交易的总资金占用倍数,需配合custom_stake_amount()使用,避免初始开仓占用过多资金导致无法加仓。
二、函数作用与调用时机
该函数的核心作用是在交易存续期间动态调整持仓规模,包括加仓和减仓,其调用时机和频率需特别注意,避免引发不必要的重复操作。
-
核心作用
- 加仓:返回正数(以基础货币计价的金额),对多头仓位触发额外买入,对空头仓位触发额外卖出。
- 减仓:返回负数,对多头仓位触发部分卖出,对空头仓位触发部分买入;返回
-trade.stake_amount时触发全额平仓。
-
调用时机与频率
- 实盘/模拟盘(dry_run):每
throttle_process_secs秒调用一次(默认 5 秒),频率极高。 - 回测(backtesting):每个蜡烛周期(
timeframe或timeframe_detail)调用一次,与实盘行为存在差异,可能导致回测结果与实盘偏差。 - 特殊场景:若存在未成交的挂单(买入或卖出),函数会先取消现有挂单,再根据返回值生成新挂单;部分成交的挂单也会被取消并重新计算金额。
- 实盘/模拟盘(dry_run):每
三、函数参数说明
函数接收多个与当前交易、市场状态相关的参数,用于判断是否调整及调整幅度,关键参数含义如下:
| 参数名 | 类型 | 说明 |
|---|---|---|
trade |
Trade 对象 | 当前交易的完整信息,包括持仓金额(trade.stake_amount)、开仓时间(trade.open_date_utc)等 |
current_time |
datetime | 当前时间,用于时间相关逻辑(如“开仓 1 小时后减仓”) |
current_rate |
float | 当前市场价格,用于计算收益和调整金额 |
current_profit |
float | 当前收益比率(如 0.05 表示 5% 收益,-0.03 表示 3% 亏损) |
min_stake |
float/None | 交易所允许的最小下单金额,返回值需大于此值才有效 |
max_stake |
float | 最大可下单金额(受钱包余额、交易所限制影响),返回值需小于此值才有效 |
current_entry_rate |
float | 基于开仓定价规则计算的当前开仓参考价 |
current_exit_rate |
float | 基于平仓定价规则计算的当前平仓参考价 |
四、关键逻辑规则
使用该函数时需严格遵守 Freqtrade 的内置规则,否则调整信号会被忽略,常见规则如下:
-
加仓规则
- 返回值必须为正数,且在
min_stake与max_stake之间,否则信号无效。 - 需确保钱包有足够余额,若返回值超过
max_stake(可用余额上限),加仓会失败。 - 加仓次数受
max_entry_position_adjustment限制,达到上限后不再接受加仓信号,但仍会检查减仓逻辑。
- 返回值必须为正数,且在
-
减仓规则
- 返回值必须为负数,且绝对值不能超过当前持仓金额(
trade.stake_amount),否则会导致剩余持仓金额为负,信号被忽略。 - 部分减仓金额计算方式:
需减仓的币种数量 = (-返回值) * trade.amount / trade.stake_amount。- 示例:持仓 2 个 SHITCOIN/USDT,开仓金额 100 USDT(
trade.stake_amount=100),若返回-50,则减仓 1 个 SHITCOIN(50 * 2 / 100 = 1)。
- 示例:持仓 2 个 SHITCOIN/USDT,开仓金额 100 USDT(
- 返回值必须为负数,且绝对值不能超过当前持仓金额(
-
止损计算规则
- 止损价格始终基于初始开仓价计算,而非平均开仓价,即使多次加仓,止损逻辑也不改变。
- 常规止损规则仍适用:止损价格只能上移(收紧),不能下移(放宽)。
五、示例代码解析(DCA 策略)
以下是一个典型的“下跌加仓(DCA)+ 盈利减仓”策略示例,关键逻辑已标注:
# 导入默认模块
class DigDeeperStrategy(IStrategy):
# 启用持仓调整功能
position_adjustment_enable = True
# 宽松止损,为DCA加仓留出空间
stoploss = -0.30
# 最多额外加仓3次(初始开仓+3次加仓,共4次)
max_entry_position_adjustment = 3
# 总资金占用倍数(初始开仓+3次加仓的资金总和为初始单的5.5倍)
max_dca_multiplier = 5.5
# 初始开仓时计算单次开仓金额(为后续加仓留资金)
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float | None, max_stake: float,
leverage: float, entry_tag: str | None, side: str,
**kwargs) -> float:
# 初始开仓金额 = 建议金额 / 总倍数,确保后续加仓有足够资金
return proposed_stake / self.max_dca_multiplier
# 核心持仓调整逻辑
def adjust_trade_position(self, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float,
min_stake: float | None, max_stake: float,
current_entry_rate: float, current_exit_rate: float,
current_entry_profit: float, current_exit_profit: float,
**kwargs
) -> float | None | tuple[float | None, str | None]:
# 1. 若有未成交挂单,先不操作(避免重复取消/挂单)
if trade.has_open_orders:
return
# 2. 盈利5%且未减仓过,卖出一半持仓锁定利润
if current_profit > 0.05 and trade.nr_of_successful_exits == 0:
return -(trade.stake_amount / 2), "half_profit_5%" # 返回元组,第二个元素为操作标签
# 3. 亏损小于5%时,不调整(避免频繁加仓)
if current_profit > -0.05:
return None
# 4. 获取K线数据,确保价格未持续下跌时才加仓
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() # 最新K线
previous_candle = dataframe.iloc[-2].squeeze() # 上一根K线
if last_candle["close"] < previous_candle["close"]: # 最新K线收盘价低于上一根,不加仓
return None
# 5. 计算加仓金额(每次加仓幅度递增25%)
filled_entries = trade.select_filled_orders(trade.entry_side) # 已成交的开仓订单
count_of_entries = trade.nr_of_successful_entries # 已成功开仓次数(初始+加仓)
try:
# 初始开仓金额 = 第一笔成交订单的金额
stake_amount = filled_entries[0].stake_amount_filled
# 加仓金额 = 初始金额 * (1 + 已开仓次数 * 0.25),实现递增加仓
stake_amount = stake_amount * (1 + (count_of_entries * 0.25))
return stake_amount, "1/3rd_increase" # 返回加仓金额和标签
except Exception as exception:
return None # 计算失败时不操作
return None
示例逻辑说明
- 初始开仓金额控制:通过
custom_stake_amount()将初始开仓金额设为“建议金额 / 5.5”,预留 4.5 倍资金用于后续 3 次加仓。 - 盈利减仓:当收益超过 5% 且未减仓过时,卖出一半持仓,锁定部分利润。
- 下跌加仓:仅当亏损超过 5% 且最新 K 线未持续下跌时才加仓,每次加仓金额递增 25%(如初始 100 USDT,第一次加仓 125 USDT,第二次 150 USDT,第三次 175 USDT),总资金占用为 100+125+150+175=550 USDT,即初始单的 5.5 倍。
六、注意事项与性能优化
-
避免频繁操作
- 实盘每 5 秒调用一次,需在函数内添加严格条件(如“仅当价格下跌 5% 且距离上次加仓 1 小时”),避免重复加仓/减仓导致高额手续费或资金浪费。
- 示例中通过
trade.has_open_orders检查挂单状态,避免取消/挂单循环。
-
回测与实盘差异
- 回测中每个蜡烛周期仅调用一次,无法模拟实盘“5 秒一次”的高频调整,可能导致回测收益虚高,需在回测后进行实盘小资金验证。
-
内存与性能
- 每次调整都会生成新订单并附加到
trade对象中,长期持仓且多次调整会占用大量内存,建议定期平仓(如盈利达目标或持仓超 24 小时),避免性能下降。
- 每次调整都会生成新订单并附加到
-
与其他函数的配合
- 若使用 DCA 策略,需配合
custom_stake_amount()控制初始开仓金额,否则初始开仓占用全部资金,后续无法加仓。 - 减仓后若需调整止损,可在
custom_stoploss()中处理,但需注意止损仍基于初始开仓价计算。
- 若使用 DCA 策略,需配合
结尾交付物提议
要不要我帮你整理一份adjust-trade-position 核心参数与常见错误排查表?表格会汇总关键参数的使用场景、常见错误(如加仓金额超出限制、减仓导致持仓为负)及解决方案,方便你在实际开发中快速参考。