258 lines
8.3 KiB
Markdown
258 lines
8.3 KiB
Markdown
根据当前策略 `OKXRegressionStrategy.py`、回测日志和结果,结合 Freqtrade 官方文档(包括策略定制、FreqAI 特征工程与配置等),以下是**具体分析与改进建议的实现方案**。
|
||
|
||
---
|
||
|
||
## 🔍 一、当前策略表现分析
|
||
|
||
### 📈 回测结果摘要
|
||
- **交易对**: OKB/USDT
|
||
- **总交易数**: 18 笔
|
||
- **胜率**: 33.3%
|
||
- **平均盈利**: -1.61%
|
||
- **总亏损**: -5.798 USDT
|
||
- **最大回撤**: -7.341 USDT (0.73%)
|
||
- **退出方式**:
|
||
- `trailing_stop_loss`: 17 笔(其中 5 赚,12 亏)
|
||
- `force_exit`: 1 笔(盈利)
|
||
|
||
### ⚠️ 关键问题
|
||
1. **模型预测信号不稳定**:
|
||
- 模型预测价格变化 (`&-s_close`) 多次低于阈值(0.005)触发卖出。
|
||
- RSI > 70 的条件也频繁出现,但未有效识别顶部。
|
||
|
||
2. **特征工程不足**:
|
||
- 当前仅使用了基础指标(RSI, MACD, BBANDS),缺乏趋势强度、波动率、市场状态等高级特征。
|
||
- 缺乏时间序列交叉验证机制,导致模型在不同周期下表现差异大。
|
||
|
||
3. **退出逻辑过于依赖单一信号**:
|
||
- `exit_signal` 基于两个静态条件,容易误判。
|
||
- 没有动态调整机制来适应市场状态(如震荡 vs 趋势)。
|
||
|
||
4. **模型训练参数固定**:
|
||
- 使用统一的 `ATR_14` 和固定乘数,未考虑币种特性或波动率变化。
|
||
|
||
---
|
||
|
||
## ✅ 二、基于官方文档的优化建议与实现
|
||
|
||
### ✅ 1. 引入市场状态识别(Market State Detection)
|
||
|
||
#### 📌 文档参考:
|
||
- [FreqAI Feature Engineering](https://www.freqtrade.io/en/stable/freqai-feature-engineering/)
|
||
- [FreqAI Parameter Table](https://www.freqtrade.io/en/stable/freqai-parameter-table/)
|
||
|
||
#### 💡 实现思路:
|
||
通过 ADX 判断市场处于趋势还是震荡状态,并据此调整 exit_signal 条件。
|
||
|
||
```python
|
||
# 在 feature_engineering_expand_all 中添加 ADX
|
||
dataframe[f"%-%-adx-{period}"] = ta.ADX(dataframe["high"], dataframe["low"], dataframe["close"], timeperiod=period)
|
||
|
||
# 在 set_freqai_targets 中设置 market_state
|
||
dataframe["market_state"] = np.where(
|
||
dataframe["adx"] > 25, "trend",
|
||
np.where(dataframe["adx"] < 20, "oscillation", "neutral")
|
||
)
|
||
```
|
||
|
||
#### 🛠️ populate_exit_trend 改进:
|
||
|
||
```python
|
||
def populate_exit_trend(self, dataframe: DataFrame, metadata: Dict) -> DataFrame:
|
||
pair = metadata['pair']
|
||
dataframe['exit_signal'] = 0
|
||
|
||
# 根据市场状态调整 exit 阈值
|
||
trend_condition = (dataframe["&-s_close"] < 0.005) & (dataframe["%-%-rsi-14"] > 70)
|
||
oscillation_condition = (dataframe["&-s_close"] < 0.01) & (dataframe["%-%-rsi-14"] > 65)
|
||
|
||
dataframe.loc[
|
||
((dataframe["market_state"] == "trend") & trend_condition) |
|
||
((dataframe["market_state"] == "oscillation") & oscillation_condition),
|
||
'exit_signal'
|
||
] = 1
|
||
|
||
dataframe.loc[dataframe['exit_signal'] == 1, 'exit_long'] = 1
|
||
return dataframe
|
||
```
|
||
|
||
---
|
||
|
||
### ✅ 2. 动态调整 ATR 倍数(Stop Loss / Take Profit)
|
||
|
||
#### 📌 文档参考:
|
||
- [FreqAI Running](https://www.freqtrade.io/en/stable/freqai-running/)
|
||
- [Custom Stoploss](https://www.freqtrade.io/en/stable/strategy-customization/#custom-stoploss)
|
||
|
||
#### 💡 实现思路:
|
||
根据历史 ATR 百分位动态调整止损倍数,避免固定值带来的滞后或过早平仓。
|
||
|
||
```python
|
||
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
|
||
current_rate: float, profit_percent: float,
|
||
after_fill: bool, **kwargs) -> Optional[float]:
|
||
if trade.enter_tag != 'long':
|
||
return None
|
||
|
||
dataframe = self.dp.get_pair_dataframe(pair, timeframe=self.timeframe)
|
||
atr_col = 'ATR_14'
|
||
|
||
if atr_col not in dataframe.columns:
|
||
dataframe[atr_col] = ta.ATR(dataframe['high'], dataframe['low'], dataframe['close'], timeperiod=14)
|
||
|
||
latest_row = dataframe.iloc[-1]
|
||
historical_atr = dataframe[atr_col].rolling(window=20).mean().dropna().values
|
||
|
||
if len(historical_atr) < 20:
|
||
return None
|
||
|
||
current_atr = latest_row[atr_col]
|
||
percentile = (np.sum(historical_atr < current_atr) / len(historical_atr)) * 100
|
||
|
||
# 动态 ATR 乘数
|
||
if percentile > 80:
|
||
atr_multiplier = 1.5 # 高波动 → 更紧止损
|
||
elif percentile < 20:
|
||
atr_multiplier = 2.5 # 低波动 → 更松止损
|
||
else:
|
||
atr_multiplier = 2.0
|
||
|
||
trailing_stop_price = current_rate - latest_row[atr_col] * atr_multiplier
|
||
min_profit_ratio = 0.005 # 至少盈利 0.5%
|
||
|
||
final_stop_price = max(trailing_stop_price, trade.open_rate * (1 + min_profit_ratio))
|
||
return final_stop_price / current_rate - 1
|
||
```
|
||
|
||
---
|
||
|
||
### ✅ 3. 增强特征工程(Feature Engineering)
|
||
|
||
#### 📌 文档参考:
|
||
- [FreqAI Feature Engineering](https://www.freqtrade.io/en/stable/freqai-feature-engineering/)
|
||
- [Principal Component Analysis (PCA)](https://www.freqtrade.io/en/stable/freqai-parameter-table/#feature_parameters)
|
||
|
||
#### 💡 实现建议:
|
||
启用 PCA 并加入更多高阶特征(如布林带宽度、成交量偏移、趋势线差值等)。
|
||
|
||
```python
|
||
# 在 freqai_config 中启用 PCA
|
||
"feature_parameters": {
|
||
"include_timeframes": ["5m", "15m", "1h"],
|
||
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
|
||
"label_period_candles": 12,
|
||
"include_shifted_candles": 2,
|
||
"principal_component_analysis": True,
|
||
"DI_threshold": 0.5,
|
||
"weight_factor": 0.9
|
||
}
|
||
```
|
||
|
||
#### 新增特征示例:
|
||
|
||
```python
|
||
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: Dict, **kwargs) -> DataFrame:
|
||
# 布林带宽度
|
||
upper, middle, lower = ta.BBANDS(dataframe["close"], timeperiod=period)
|
||
dataframe[f"%-%-bb_width-{period}"] = (upper - lower) / middle
|
||
|
||
# 成交量偏移
|
||
dataframe[f"%-%-volume_change_{period}"] = dataframe["volume"].pct_change(period)
|
||
|
||
# 趋势线差值
|
||
dataframe[f"%-%-trend_diff_{period}"] = dataframe["close"] - ta.SMA(dataframe["close"], timeperiod=period)
|
||
|
||
return dataframe
|
||
```
|
||
|
||
---
|
||
|
||
### ✅ 4. 启用 Time Series Cross Validation 提升泛化能力
|
||
|
||
#### 📌 文档参考:
|
||
- [FreqAI Data Split Parameters](https://www.freqtrade.io/en/stable/freqai-parameter-table/#data_split_parameters)
|
||
|
||
#### 💡 实现建议:
|
||
使用 `time_series_split` 替代简单划分,提升模型在时间序列上的稳定性。
|
||
|
||
```json
|
||
{
|
||
"data_split_parameters": {
|
||
"test_size": 0.2,
|
||
"shuffle": false,
|
||
"stratify": false,
|
||
"time_series_split": true,
|
||
"n_splits": 5
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### ✅ 5. 加入模型预测置信度过滤
|
||
|
||
#### 📌 文档参考:
|
||
- [Model Training Parameters](https://www.freqtrade.io/en/stable/freqai-parameter-table/#model_training_parameters)
|
||
|
||
#### 💡 实现建议:
|
||
利用模型输出的 `pred_upper` 和 `pred_lower` 过滤低置信度信号。
|
||
|
||
```python
|
||
def populate_entry_trend(self, dataframe: DataFrame, metadata: Dict) -> DataFrame:
|
||
dataframe.loc[
|
||
(
|
||
(dataframe["&-s_close"] > 0.01) &
|
||
(dataframe["do_predict"] == 1) &
|
||
(dataframe["%-%-rsi-14"] < dataframe["&-buy_rsi_pred"]) &
|
||
(dataframe["pred_upper"] - dataframe["pred_lower"] > 0.02) # 置信区间大于 2%
|
||
),
|
||
"enter_long"
|
||
] = 1
|
||
return dataframe
|
||
```
|
||
|
||
---
|
||
|
||
## 🧠 三、下一步行动建议
|
||
|
||
| 步骤 | 内容 | 目标 |
|
||
|------|------|------|
|
||
| 1 | 启用 PCA + 时间序列交叉验证 | 提升模型泛化能力 |
|
||
| 2 | 动态 ATR stop loss | 减少误止损 |
|
||
| 3 | 市场状态识别 + 分级 exit signal | 提高胜率 |
|
||
| 4 | 置信区间过滤 entry/exit | 减少低质量信号 |
|
||
| 5 | 重新运行 backtest | 验证改进效果 |
|
||
|
||
---
|
||
|
||
## 📁 四、推荐修改文件结构
|
||
|
||
```bash
|
||
freqtrade/
|
||
├── templates/
|
||
│ └── OKXRegressionStrategy.py # 主策略文件
|
||
├── user_data/
|
||
│ └── models/
|
||
│ └── test175/ # 存放模型缓存
|
||
└── config_examples/
|
||
└── config_freqai.okx.json # 启用 PCA、TS CV 等配置
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 总结
|
||
|
||
| 问题 | 解决方案 |
|
||
|------|----------|
|
||
| Exit Signal 不稳定 | 引入 Market State + 分级条件 |
|
||
| 模型泛化能力弱 | 启用 PCA + TimeSeriesSplit |
|
||
| 特征维度低 | 添加 BB Width、Volume Change、Trend Diff |
|
||
| 固定止损不灵活 | 动态 ATR Multiplier |
|
||
| 低质量信号多 | 加入 pred_upper/pred_lower 区间过滤 |
|
||
|
||
---
|
||
|
||
是否需要我为你生成完整的优化后策略文件?或者我们继续逐步实现这些改动?
|
||
|
||
|