myTestFreqAI/chat/report2.md
zhangkun9038@dingtalk.com 6b365f3107 log
2025-05-05 21:33:46 +08:00

8.3 KiB
Raw Blame History

根据当前策略 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

📌 文档参考:

💡 实现思路:

通过 ADX 判断市场处于趋势还是震荡状态,并据此调整 exit_signal 条件。

# 在 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 改进:

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

📌 文档参考:

💡 实现思路:

根据历史 ATR 百分位动态调整止损倍数,避免固定值带来的滞后或过早平仓。

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

📌 文档参考:

💡 实现建议:

启用 PCA 并加入更多高阶特征(如布林带宽度、成交量偏移、趋势线差值等)。

# 在 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
}

新增特征示例:

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 提升泛化能力

📌 文档参考:

💡 实现建议:

使用 time_series_split 替代简单划分,提升模型在时间序列上的稳定性。

{
  "data_split_parameters": {
    "test_size": 0.2,
    "shuffle": false,
    "stratify": false,
    "time_series_split": true,
    "n_splits": 5
  }
}

5. 加入模型预测置信度过滤

📌 文档参考:

💡 实现建议:

利用模型输出的 pred_upperpred_lower 过滤低置信度信号。

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 验证改进效果

📁 四、推荐修改文件结构

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 区间过滤

是否需要我为你生成完整的优化后策略文件?或者我们继续逐步实现这些改动?