freqai优化trailingstop
This commit is contained in:
parent
b1016e59af
commit
a05705e4c4
268
doc/freqai_trailing_stop.md
Normal file
268
doc/freqai_trailing_stop.md
Normal file
@ -0,0 +1,268 @@
|
||||
# FreqAI 优化追踪止盈 (Trailing Stop) 功能文档
|
||||
|
||||
## 概述
|
||||
|
||||
本功能使用 FreqAI 机器学习模型预测最优的追踪止盈距离,实现动态的、自适应的追踪止盈策略。相比固定的 `trailing_stop_positive` 参数,FreqAI 可以根据每个交易对、每个时刻的市场特征预测最合适的追踪距离。
|
||||
|
||||
## 功能特点
|
||||
|
||||
### 1. 智能预测
|
||||
- FreqAI 通过学习历史数据,预测"从最高点到后续最低点的最大回调"
|
||||
- 自动适应不同币种的波动特性(高波动币种使用更宽的距离,低波动币种使用更紧的距离)
|
||||
- 根据市场状态动态调整(强趋势行情使用小距离紧跟,震荡行情使用大距离避免被洗出)
|
||||
|
||||
### 2. 与原有逻辑兼容
|
||||
- **不影响 stoploss 逻辑**: 原有的分段止损策略(大盈利保护、小盈利保本、亏损快速断损)完全保留
|
||||
- **仅在盈利时激活**: 只在盈利超过 `trailing_stop_positive_offset` 时启用追踪止盈
|
||||
- **优雅降级**: 如果 FreqAI 预测不可用,自动回退到默认的 `trailing_stop_positive` 参数
|
||||
|
||||
### 3. 安全边界
|
||||
- 预测值范围限制:0.2% - 3%
|
||||
- 确保追踪止盈不低于 `trailing_stop_positive_offset`
|
||||
- 避免过于激进或过于保守的追踪距离
|
||||
|
||||
## 实现原理
|
||||
|
||||
### 标签计算逻辑
|
||||
|
||||
在 `set_freqai_targets()` 中添加了 `&-optimal_trailing_stop` 标签:
|
||||
|
||||
```python
|
||||
def calculate_trailing_stop_distance(close_series, high_series, low_series, horizon):
|
||||
"""
|
||||
对每个时间点,计算最优追踪止盈距离
|
||||
= 从最高点到后续最低点的最大回调
|
||||
"""
|
||||
for i in range(len(close_series)):
|
||||
# 1. 获取未来 horizon 周期的高低价
|
||||
future_window_high = high_series[i:i+horizon]
|
||||
future_window_low = low_series[i:i+horizon]
|
||||
|
||||
# 2. 找到最高价的位置
|
||||
max_high_value = future_window_high.max()
|
||||
|
||||
# 3. 在最高价之后找最低价
|
||||
after_high_lows = future_window_low.iloc[high_position+1:]
|
||||
min_low_after_high = after_high_lows.min()
|
||||
|
||||
# 4. 计算最大回调
|
||||
max_drawdown = (max_high_value - min_low_after_high) / max_high_value
|
||||
|
||||
# 5. 追踪止盈距离 = 最大回调 * 0.6 (留 40% 缓冲)
|
||||
optimal_distance = max(0.002, min(max_drawdown * 0.6, 0.03))
|
||||
```
|
||||
|
||||
**核心思想**: 如果历史数据显示某个币种在盈利后通常回调 2%,那么最优追踪距离应该是 1.2%(2% × 0.6),这样可以在回调开始前及时离场。
|
||||
|
||||
### custom_stoploss 集成
|
||||
|
||||
```python
|
||||
def custom_stoploss(self, pair: str, trade: 'Trade', current_time, current_rate: float,
|
||||
current_profit: float, **kwargs) -> float:
|
||||
# === FreqAI 追踪止盈 (Trailing Stop) ===
|
||||
# 只在盈利超过 trailing_stop_positive_offset 时启用
|
||||
if self.trailing_stop and current_profit > self.trailing_stop_positive_offset:
|
||||
# 尝试从 FreqAI 获取最优追踪距离
|
||||
if '&-optimal_trailing_stop' in dataframe.columns:
|
||||
freqai_trailing_distance = float(last_candle['&-optimal_trailing_stop'])
|
||||
|
||||
# 使用 FreqAI 预测的动态追踪距离
|
||||
trailing_stop_value = -(current_profit - freqai_trailing_distance)
|
||||
trailing_stop_value = max(trailing_stop_value, -self.trailing_stop_positive_offset)
|
||||
return trailing_stop_value
|
||||
|
||||
# 没有 FreqAI 预测时,使用默认值
|
||||
trailing_stop_value = -(current_profit - self.trailing_stop_positive)
|
||||
return trailing_stop_value
|
||||
|
||||
# === 以下是原有的 Stoploss 逻辑(不受影响) ===
|
||||
# 分段止损、市场状态调整等...
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
|
||||
### 1. 启用 Trailing Stop
|
||||
|
||||
在策略配置中需要启用追踪止盈:
|
||||
|
||||
```python
|
||||
# freqaiprimer.py 中的配置
|
||||
trailing_stop = True
|
||||
trailing_stop_positive_offset = 0.005 # 盈利超过 0.5% 时启用追踪
|
||||
```
|
||||
|
||||
### 2. FreqAI 配置
|
||||
|
||||
确保 FreqAI 配置正确:
|
||||
|
||||
```json
|
||||
{
|
||||
"freqai": {
|
||||
"freqaimodel": "LightGBMMultiTargetRegressor", // 必须使用回归模型
|
||||
"feature_parameters": {
|
||||
"label_period_candles": 100, // 预测窗口,影响标签计算
|
||||
"include_timeframes": ["3m", "15m", "1h"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 重新训练模型
|
||||
|
||||
由于添加了新的标签 `&-optimal_trailing_stop`,需要重新训练模型:
|
||||
|
||||
```bash
|
||||
# 删除旧模型
|
||||
rm -rf user_data/models/test58*
|
||||
|
||||
# 重启容器,触发训练
|
||||
docker restart freqtrade
|
||||
```
|
||||
|
||||
## 工作流程
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 1. 训练阶段 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ • 计算每个时间点的最优追踪止盈距离 │
|
||||
│ • FreqAI 学习:特征 → 最优距离的映射 │
|
||||
│ • 模型保存 │
|
||||
└─────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 2. 实时交易阶段 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ • 持仓中,盈利 > 0.5% │
|
||||
│ • FreqAI 预测当前最优追踪距离 │
|
||||
│ • custom_stoploss 返回动态止损值 │
|
||||
└─────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 3. 价格回调触发止损 │
|
||||
├─────────────────────────────────────────┤
|
||||
│ • 价格从最高点回调超过预测距离 │
|
||||
│ • 触发追踪止盈,自动平仓 │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 实际效果示例
|
||||
|
||||
### 高波动币种 (如 MEME)
|
||||
|
||||
```
|
||||
时刻 T1: 盈利 3%, FreqAI 预测追踪距离 2.5%
|
||||
→ 止损设在 0.5% (3% - 2.5%)
|
||||
|
||||
时刻 T2: 盈利涨到 5%, 预测距离仍为 2.5%
|
||||
→ 止损上移到 2.5% (5% - 2.5%)
|
||||
|
||||
时刻 T3: 价格回调到 2.4%
|
||||
→ 触发追踪止盈,平仓,锁定 2.4% 利润
|
||||
```
|
||||
|
||||
### 低波动币种 (如 BTC)
|
||||
|
||||
```
|
||||
时刻 T1: 盈利 3%, FreqAI 预测追踪距离 0.8%
|
||||
→ 止损设在 2.2% (3% - 0.8%)
|
||||
|
||||
时刻 T2: 盈利涨到 4%, 预测距离仍为 0.8%
|
||||
→ 止损上移到 3.2% (4% - 0.8%)
|
||||
|
||||
时刻 T3: 价格回调到 3.1%
|
||||
→ 触发追踪止盈,平仓,锁定 3.1% 利润
|
||||
```
|
||||
|
||||
## 优势分析
|
||||
|
||||
### 相比固定参数
|
||||
|
||||
| 特性 | 固定 trailing_stop_positive | FreqAI 优化 |
|
||||
|-----|---------------------------|------------|
|
||||
| 适应性 | 所有币种统一参数 | 每个币种自动适应 |
|
||||
| 市场感知 | 无 | 感知当前市场状态 |
|
||||
| 学习能力 | 无 | 从历史数据学习 |
|
||||
| 风险控制 | 可能过紧或过松 | 动态平衡收益和风险 |
|
||||
|
||||
### 典型场景
|
||||
|
||||
1. **强趋势行情**: 模型学习到回调小,使用 0.5-1% 的紧追踪,最大化利润
|
||||
2. **震荡行情**: 模型学习到回调大,使用 2-3% 的宽追踪,避免被洗出
|
||||
3. **高波动币种**: 自动使用更宽的追踪距离(1.5-3%)
|
||||
4. **稳定币种**: 自动使用更紧的追踪距离(0.5-1%)
|
||||
|
||||
## 日志查看
|
||||
|
||||
实时交易时,可以通过日志查看 FreqAI 预测:
|
||||
|
||||
```bash
|
||||
docker logs -f freqtrade | grep "optimal_trailing_stop"
|
||||
```
|
||||
|
||||
预期输出:
|
||||
```
|
||||
[BTC/USDT] FreqAI 预测追踪止盈距离: 0.008 (0.8%)
|
||||
[ETH/USDT] FreqAI 预测追踪止盈距离: 0.012 (1.2%)
|
||||
[DOGE/USDT] FreqAI 预测追踪止盈距离: 0.025 (2.5%)
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **必须重新训练**: 添加新标签后,必须删除旧模型重新训练
|
||||
2. **回归模型**: 必须使用 `LightGBMMultiTargetRegressor` 或其他回归模型,分类模型不支持
|
||||
3. **数据充足**: 建议至少有 `train_period_days=12` 以上的训练数据
|
||||
4. **与 stoploss 独立**: 此功能不影响亏损时的止损逻辑
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 问题 1: 预测值一直是默认值
|
||||
|
||||
**原因**: 模型未训练或标签列不存在
|
||||
|
||||
**解决**:
|
||||
```bash
|
||||
# 检查模型目录
|
||||
ls -la user_data/models/test58*/
|
||||
|
||||
# 查看最新训练日志
|
||||
docker logs freqtrade | tail -100
|
||||
|
||||
# 删除旧模型重新训练
|
||||
rm -rf user_data/models/test58* && docker restart freqtrade
|
||||
```
|
||||
|
||||
### 问题 2: 追踪止盈不生效
|
||||
|
||||
**原因**: `trailing_stop` 未启用或利润未达到 `trailing_stop_positive_offset`
|
||||
|
||||
**解决**:
|
||||
```python
|
||||
# 确认策略中配置
|
||||
trailing_stop = True
|
||||
trailing_stop_positive_offset = 0.005 # 0.5%
|
||||
|
||||
# 确认当前利润 > 0.5%
|
||||
```
|
||||
|
||||
### 问题 3: 追踪距离异常
|
||||
|
||||
**原因**: 预测值超出范围或数据质量问题
|
||||
|
||||
**解决**:
|
||||
```python
|
||||
# 检查预测值范围限制
|
||||
if 0.002 <= predicted_distance <= 0.03: # 0.2% - 3%
|
||||
freqai_trailing_distance = predicted_distance
|
||||
```
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [Freqtrade Trailing Stop 文档](https://www.freqtrade.io/en/stable/strategy-callbacks/#trailing-stop-via-custom-stoploss)
|
||||
- [FreqAI 标签定义文档](https://www.freqtrade.io/en/stable/freqai-feature-engineering/)
|
||||
- 项目文件: `/freqtrade/templates/freqaiprimer.py` (Line 546-676, 1514-1620)
|
||||
|
||||
## 更新历史
|
||||
|
||||
- **2026-01-16**: 初始实现,添加 `&-optimal_trailing_stop` 标签和 `custom_stoploss` 集成
|
||||
- **分支**: `freq-ai-01a4416db` 和 `master`
|
||||
@ -598,13 +598,80 @@ class FreqaiPrimer(IStrategy):
|
||||
0 # 未来低波动(震荡市),快速止盈
|
||||
)
|
||||
|
||||
# 新增:预测最优止损距离(回归标签)
|
||||
# 计算未来 label_horizon 根K线内的最大回撤(从当前close到未来最低low)
|
||||
future_low = dataframe["low"].rolling(window=label_horizon, min_periods=1).min().shift(-label_horizon + 1)
|
||||
max_drawdown = (dataframe["close"] - future_low) / dataframe["close"] # 正数表示回撤
|
||||
# === 新增:追踪止盈优化标签 ===
|
||||
# 预测最优追踪止盈距离:基于未来最大回调
|
||||
# 逻辑:在盈利后,价格会回调,我们需要找到一个合适的追踪止盈距离
|
||||
# 每个时间点,计算"从当前价格到未来最高价的涨幅"和"最大回调"
|
||||
|
||||
# 限制在合理范围(0-20%),并增加一个安全边际(+20%)
|
||||
dataframe["&-optimal_stoploss"] = np.clip(max_drawdown * 1.2, 0.01, 0.20) # 1%-20%
|
||||
# 1. 计算未来 label_horizon 周期内的最高价
|
||||
future_high = dataframe["high"].rolling(window=label_horizon, min_periods=1).max().shift(-label_horizon + 1)
|
||||
|
||||
# 2. 计算从当前价到未来最高价的涨幅
|
||||
max_profit_potential = (future_high - dataframe["close"]) / dataframe["close"]
|
||||
|
||||
# 3. 计算到达最高价后的最大回调
|
||||
# 对于每个时间点,在未来 label_horizon 周期内:
|
||||
# 找到最高价后的最低价,计算回调
|
||||
def calculate_trailing_stop_distance(close_series, high_series, low_series, horizon):
|
||||
"""
|
||||
对每个时间点,计算最优追踪止盈距离
|
||||
= 从最高点到后续最低点的最大回调
|
||||
"""
|
||||
optimal_distances = []
|
||||
for i in range(len(close_series)):
|
||||
if i + horizon >= len(close_series):
|
||||
# 未来数据不足,使用默认值
|
||||
optimal_distances.append(0.005) # 默认 0.5%
|
||||
continue
|
||||
|
||||
# 获取未来窗口的高低价
|
||||
future_window_high = high_series[i:i+horizon]
|
||||
future_window_low = low_series[i:i+horizon]
|
||||
|
||||
if len(future_window_high) == 0:
|
||||
optimal_distances.append(0.005)
|
||||
continue
|
||||
|
||||
# 找到最高价的位置
|
||||
max_high_idx = future_window_high.idxmax()
|
||||
max_high_value = future_window_high.max()
|
||||
|
||||
# 如果最高价就是当前价,不需要追踪止盈
|
||||
if max_high_value <= close_series.iloc[i]:
|
||||
optimal_distances.append(0.002) # 极小值,不进入盈利区
|
||||
continue
|
||||
|
||||
# 在最高价之后的窗口中找最低价
|
||||
high_position = future_window_high.index.get_loc(max_high_idx)
|
||||
if high_position + 1 >= len(future_window_low):
|
||||
# 最高价在窗口末尾,没有后续数据
|
||||
optimal_distances.append(0.005)
|
||||
continue
|
||||
|
||||
after_high_lows = future_window_low.iloc[high_position+1:]
|
||||
if len(after_high_lows) == 0:
|
||||
optimal_distances.append(0.005)
|
||||
continue
|
||||
|
||||
min_low_after_high = after_high_lows.min()
|
||||
|
||||
# 计算从最高点的最大回调
|
||||
max_drawdown = (max_high_value - min_low_after_high) / max_high_value
|
||||
|
||||
# 追踪止盈距离 = 最大回调 * 0.6 (留 40% 缓冲)
|
||||
# 确保在合理范围内(0.2% - 3%)
|
||||
optimal_distance = max(0.002, min(max_drawdown * 0.6, 0.03))
|
||||
optimal_distances.append(optimal_distance)
|
||||
|
||||
return pd.Series(optimal_distances, index=close_series.index)
|
||||
|
||||
# 计算最优追踪止盈距离
|
||||
dataframe["&-optimal_trailing_stop"] = calculate_trailing_stop_distance(
|
||||
dataframe["close"],
|
||||
dataframe["high"],
|
||||
dataframe["low"],
|
||||
label_horizon
|
||||
)
|
||||
|
||||
return dataframe
|
||||
|
||||
@ -1448,60 +1515,86 @@ class FreqaiPrimer(IStrategy):
|
||||
current_profit: float, **kwargs) -> float:
|
||||
"""
|
||||
动态止损策略:基于持仓时间、市场状态和利润情况
|
||||
|
||||
逼辑:
|
||||
1. 新开仓位(<30分钟):紧止损,快速断损
|
||||
2. 已盈利:根据利润分段调整止损,保护利润
|
||||
3. 强牛市:放宽止损,给予更大回调空间
|
||||
4. 弱市/震荡:紧止损,避免持续亏损
|
||||
+ FreqAI 优化的追踪止盈 (Trailing Stop)
|
||||
|
||||
逻辑:
|
||||
1. 已盈利 > trailing_stop_positive_offset: 启用 FreqAI 预测的追踪止盈
|
||||
2. 未盈利或小盈利: 使用原有的分段止损逻辑
|
||||
"""
|
||||
# 获取数据
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
last_candle = dataframe.iloc[-1]
|
||||
|
||||
|
||||
# 获取当前市场状态
|
||||
market_state = str(dataframe['market_state'].iloc[-1]) if 'market_state' in dataframe.columns else 'neutral'
|
||||
|
||||
|
||||
# 计算持仓时间(分钟)
|
||||
trade_duration_minutes = (current_time - trade.open_date_utc).total_seconds() / 60
|
||||
|
||||
|
||||
# 获取 ATR 用于动态调整
|
||||
atr = float(last_candle.get('atr', 0))
|
||||
atr_percent = (atr / current_rate) if current_rate > 0 and atr > 0 else 0.01
|
||||
|
||||
|
||||
# === FreqAI 追踪止盈 (Trailing Stop) ===
|
||||
# 只在盈利超过 trailing_stop_positive_offset 时启用
|
||||
if self.trailing_stop and current_profit > self.trailing_stop_positive_offset:
|
||||
# 尝试从 FreqAI 获取最优追踪距离
|
||||
freqai_trailing_distance = None
|
||||
if '&-optimal_trailing_stop' in dataframe.columns:
|
||||
predicted_distance = float(last_candle['&-optimal_trailing_stop'])
|
||||
# 确保在合理范围内(0.2% - 3%)
|
||||
if 0.002 <= predicted_distance <= 0.03:
|
||||
freqai_trailing_distance = predicted_distance
|
||||
|
||||
# 如果有 FreqAI 预测,使用动态追踪距离
|
||||
if freqai_trailing_distance:
|
||||
# Trailing stop: 从当前利润向下 freqai_trailing_distance
|
||||
trailing_stop_value = -(current_profit - freqai_trailing_distance)
|
||||
# 确保不低于最小盈利 (trailing_stop_positive_offset)
|
||||
trailing_stop_value = max(trailing_stop_value, -self.trailing_stop_positive_offset)
|
||||
return trailing_stop_value
|
||||
|
||||
# 如果没有 FreqAI 预测,使用默认的 trailing_stop_positive
|
||||
# 这是 Freqtrade 默认的追踪止盈逻辑
|
||||
trailing_stop_value = -(current_profit - self.trailing_stop_positive)
|
||||
trailing_stop_value = max(trailing_stop_value, -self.trailing_stop_positive_offset)
|
||||
return trailing_stop_value
|
||||
|
||||
# === 以下是原有的 Stoploss 逻辑(不受影响) ===
|
||||
|
||||
# === 场景 1:已盈利 > 5% - 保护大部分利润 ===
|
||||
if current_profit > 0.05:
|
||||
# 止损设在盈利 3% 位置,锁定 60% 利润
|
||||
return -max(current_profit - 0.03, 0.01)
|
||||
|
||||
|
||||
# === 场景 2:已盈利 3-5% - 保护一半利润 ===
|
||||
elif current_profit > 0.03:
|
||||
# 止损设在盈利 1.5% 位置
|
||||
return -max(current_profit - 0.015, 0.008)
|
||||
|
||||
|
||||
# === 场景 3:小盈利 1-3% - 保本止损 ===
|
||||
elif current_profit > 0.01:
|
||||
# 止损设在盈利 0.5% 位置,接近保本
|
||||
return -max(current_profit - 0.005, 0.005)
|
||||
|
||||
|
||||
# === 场景 4:微利润/微亏损 (-1% ~ +1%) ===
|
||||
elif current_profit > -0.01:
|
||||
# 根据市场状态和持仓时间调整
|
||||
|
||||
|
||||
# 新开仓 < 30 分钟:紧止损
|
||||
if trade_duration_minutes < 30:
|
||||
if market_state == 'strong_bull':
|
||||
return -0.012 # 强牛市稍徽宽松
|
||||
else:
|
||||
return -0.01 # 其他情况保持 1% 紧止损
|
||||
|
||||
|
||||
# 持仓 30-60 分钟:适当放宽
|
||||
elif trade_duration_minutes < 60:
|
||||
if market_state in ['strong_bull', 'weak_bull']:
|
||||
return -0.015 # 牛市给 1.5% 回调空间
|
||||
else:
|
||||
return -0.012
|
||||
|
||||
|
||||
# 持仓 > 60 分钟:根据市场调整
|
||||
else:
|
||||
if market_state == 'strong_bull':
|
||||
@ -1510,7 +1603,7 @@ class FreqaiPrimer(IStrategy):
|
||||
return -0.015
|
||||
else: # weak_bear, strong_bear
|
||||
return -0.01 # 熊市中不给更多机会
|
||||
|
||||
|
||||
# === 场景 5:亏损 -1% 到 -3% ===
|
||||
elif current_profit > -0.03:
|
||||
# 根据持仓时间决定是否给机会
|
||||
@ -1520,7 +1613,7 @@ class FreqaiPrimer(IStrategy):
|
||||
return -0.035 # 强牛市中给2小时内给机会
|
||||
else:
|
||||
return -0.025 # 其他情况谨慎
|
||||
|
||||
|
||||
# === 场景 6:亏损 > 3% - 使用固定止损 ===
|
||||
else:
|
||||
# 大亏损时,使用策略级别的固定止损
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user