myTestFreqAI/doc/adjust_trade_position.md
2025-10-17 19:09:35 +00:00

147 lines
9.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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