myTestFreqAI/chat/result14.md
zhangkun9038@dingtalk.com c167bf5df0 XGBoostRegressorMultiTarget
2025-06-03 09:45:51 +00:00

23 KiB
Raw Blame History

  • Datetime: 2025-06-03 02:21:39

  • Model: _qwen3/qwen-plus-latest

  • Selected files:

    • result/backtest-result-2025-06-03_01-41-33_FreqaiPrimer.py
    • result/analytic.log
    • result/backtest-result-2025-06-03_01-41-33.json
    • result/backtest-result-2025-06-03_01-41-33.meta.json
    • result/backtest-result-2025-06-03_01-41-33_FreqaiPrimer.json
    • result/backtest-result-2025-06-03_01-41-33_config.json
    • result/backtest_trades.csv
    • result/output.log

当前策略的配置,代码,执行结果都在上下文中, 结合官方文档, 请给出对于执行结果的评价以及修改建议

自定义策略: https://www.freqtrade.io/en/stable/strategy-customization/ freqai 特征工程 : https://www.freqtrade.io/en/stable/freqai-feature-engineering/ freqai 参数表: https://www.freqtrade.io/en/stable/freqai-parameter-table/ freqai 配置: https://www.freqtrade.io/en/stable/freqai-configuration/ freaai 运行: https://www.freqtrade.io/en/stable/freqai-running/ freqai 开发手册: https://www.freqtrade.io/en/stable/freqai-developers/ freqtrade 策略例子: https://github.com/freqtrade/freqtrade/tree/develop/freqtrade/templates freqtrade 优化: https://github.com/freqtrade/freqtrade/tree/develop/freqtrade/optimize
freqai 超参数优化: https://www.freqtrade.io/en/stable/hyperopt/

策略执行结果分析与优化建议

一、执行结果关键指标分析

总体表现

  • 总交易次数8次
  • 盈利交易4次 (50%胜率)
  • 总利润8.87 USDT (+0.89%)
  • 平均持仓时间21分钟
  • 最大连续亏损2次
  • 利润因子2.15

分币种表现

币种 交易次数 平均利润 胜率
KAITO/USDT 4 +0.77% 50%
TRUMP/USDT 3 +0.95% 66.7%
WCT/USDT 1 0% 0%

分退出原因表现

原因 交易次数 平均利润 胜率
ROI 7 +1.58% 100%
止损 1 -5.15% 0%

二、策略配置分析

1. FreqAI配置

"freqai": {
  "enabled": true,
  "data_kitchen": {"fillna": "ffill"},
  "freqaimodel": "LightGBMMultiTargetRegressor",
  "purge_old_models": 2,
  "identifier": "test58",
  "train_period_days": 7,
  "backtest_period_days": 1,
  "live_retrain_hours": 2,
  "outlier_detection": {"method": "IsolationForest", "contamination": 0.1},
  "feature_selection": {"method": "recursive_elimination"},
  "feature_parameters": {
    "include_timeframes": ["3m","15m","1h"],
    "include_corr_pairlist": ["BTC/USDT","SOL/USDT"],
    "outlier_protection_percentage": 0.1,
    "label_period_candles": 24,
    "include_shifted_candles": 3,
    "DI_threshold": 0.7,
    "weight_factor": 0.9,
    "principal_component_analysis": false,
    "use_SVM_to_remove_outliers": true,
    "indicator_periods_candles": [10,20,50],
    "plot_feature_importances": 10
  },
  "data_split_parameters": {"test_size": 0.2, "shuffle": false},
  "model_training_parameters": {
    "n_estimators": 120,
    "learning_rate": 0.05,
    "num_leaves": 31,
    "verbose": -1,
    "max_depth": 8
  }
}

2. 策略参数

minimal_roi = {
    "0": 0.02,
    "30": 0.01,
    "60": 0
}

stoploss = -0.015

trailing_stop = True
trailing_stop_positive = 0.053
trailing_stop_positive_offset = 0.152

三、执行结果评价

1. 优势

  • 快速交易特性平均持仓时间仅21分钟适合高频交易
  • ROI设置合理:最终盈利交易都实现了正收益
  • 止损机制有效:唯一亏损交易及时止损(-5.15%)

2. 存在的问题

  • 交易机会少整个回测期间仅有8次交易交易频率过低
  • 过度依赖FreqAI预测:当&-price_value_divergence缺失时,策略几乎无法产生信号
  • 动态阈值调整不足虽然有labels_mean和labels_std的动态计算但实际买卖点分布较集中
  • 特征工程冗余:生成了大量技术指标,但很多未被使用
  • 日志记录过多DEBUG级别日志可能影响性能
  • 自定义价格机制效果有限买入价降低0.5%、卖出价提高0.25%,对整体收益贡献较小

四、优化建议

1. 提高交易频率

  • 缩小fit_live_predictions_candles从100到50增加交易机会
  • 降低入场条件门槛:
    cond2 = (dataframe["volume_z_score"] > 1.0)  # 原为1.5
    cond3 = (dataframe["rsi"] < 45)           # 原为40
    

2. 增强入场信号

  • 添加备用信号源当FreqAI数据不可用时
    if "&-price_value_divergence" not in dataframe.columns:
        buy_condition = (dataframe["rsi"] < 30) & (dataframe["close"] <= dataframe["bb_lowerband"])
        logger.warning(f"[{pair}] 使用备用策略: RSI+布林带")
    

3. 优化动态阈值计算

  • 引入时间衰减因子,使阈值随市场波动自动调节:
    volatility = dataframe["bb_upperband-period"] / dataframe["bb_lowerband-period"] - 1
    k_volatility = 1 + (volatility.iloc[-1] * 10)  # 波动率越高k值越大
    
    self.buy_threshold = labels_mean - k_buy * labels_std * k_volatility
    self.sell_threshold = labels_mean + k_sell * labels_std * k_volatility
    

4. 简化特征工程

  • 移除未使用的指标:
    # 删除以下未被使用的指标
    del dataframe["%-sma-period"]
    del dataframe["%-mfi-period"]
    del dataframe["%-adx-period"]
    

5. 改进Trailing Stop逻辑

  • 实现动态追踪止损:
    def adjust_trade_position(self, trade: Trade, current_time: datetime,
                            current_rate: float, current_profit: float,
                            min_roi: Dict[float, float], max_profit: float):
        # 动态调整追踪止损参数
        hold_time = (current_time - trade.open_date_utc).total_seconds() / 60
    
        # 持仓前5分钟使用保守止损
        if hold_time < 5:
            trailing_stop_start = 0.02
            trailing_stop_distance = 0.008
        # 持仓5-15分钟使用激进追涨
        elif hold_time < 15:
            trailing_stop_start = 0.03
            trailing_stop_distance = 0.01
        # 持仓超过15分钟后使用保守追踪
        else:
            trailing_stop_start = 0.015
            trailing_stop_distance = 0.005
    
        # 剩余代码保持不变...
    

6. 优化Hyperopt参数空间用于后续优化

# ROI 参数空间
def roi_space():
    return [
        Integer(0, 60, name='roi_t1'),      
        Integer(30, 120, name='roi_t2'),    
        Integer(60, 180, name='roi_t3'),    
        Real(0.01, 0.05, name='roi_p1'),   
        Real(0.005, 0.03, name='roi_p2'),  
        Real(0.0, 0.02, name='roi_p3'),    
    ]

# Trailing Stop 参数空间
def trailing_space():
    return [
        Real(0.01, 0.05, name='trailing_stop_start'),     
        Real(0.005, 0.02, name='trailing_stop_distance'), 
    ]

7. 风险控制增强

  • 添加最大单日亏损限制:
    def custom_stake_amount(self, pair, current_time, current_rate, proposed_stake, min_stake, max_stake):
        # 计算当日已实现亏损
        daily_loss = sum(trade.calc_profit() for trade in Trade.get_trades() 
                        if trade.close_date and trade.close_date.date() == current_time.date() and trade.loss)
    
        if daily_loss < -100:  # 当日亏损超过$100停止交易
            return 0
    
        return proposed_stake * 0.5  # 默认使用50%推荐仓位
    

五、FreqAI专项优化建议

1. 特征工程优化

  • 根据官方文档FreqAI特征工程建议:
    def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs):
        # 保留核心特征
        dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
    
        # 添加趋势特征
        dataframe[f"%-sma-period-ratio"] = (dataframe["close"] / ta.SMA(dataframe, timeperiod=period)) - 1
    
        # 添加波动率特征
        dataframe[f"%-volatility"] = (ta.ATR(dataframe, timeperiod=period) / dataframe["close"])
    
        # 清理NaN值
        dataframe.fillna(method='ffill', inplace=True)
        dataframe.fillna(0, inplace=True)
    
        return dataframe
    

2. 标签(Label)优化

  • 根据官方建议,可以尝试更复杂的标签:
    def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
        # 多目标回归
        dataframe["&-target-profit"] = (dataframe["close"].shift(-self.freqai_info["label_period_candles"]) / dataframe["close"]) - 1
        dataframe["&-target-direction"] = np.where(
            dataframe["close"].shift(-self.freqai_info["label_period_candles"]) > dataframe["close"], 1, 0
        )
    
        # 数据清理
        dataframe.replace([np.inf, -np.inf], 0, inplace=True)
        dataframe.fillna(0, inplace=True)
    
        return dataframe
    

六、具体修改建议

1. 修改后的__init__方法

def __init__(self, config: dict, *args, **kwargs):
    super().__init__(config, *args, **kwargs)
    logger.setLevel(logging.INFO)  # 降低默认日志级别
    logger.info("✅ 策略已初始化,日志级别设置为 INFO")
    self.trailing_stop_enabled = False
    self.pair_stats = {}
    self.stats_logged = False
    self.fit_live_predictions_candles = self.freqai_info.get("fit_live_predictions_candles", 50)  # 减少到50根K线

2. 修改后的confirm_trade_entry方法

def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
                       time_in_force: str, current_time: datetime, **kwargs) -> bool:
    # 在 Hyperopt 或 Dry Run 模式下避免数据库查询
    if 'hyperopt' in self.config.get('runmode', '') or not hasattr(Trade, 'query') or Trade.query is None:
        return True

    # 降低检查窗口到2分钟
    recent_trades = Trade.query.filter(
        Trade.pair == pair,
        Trade.is_open == False,  # noqa: E712
        Trade.close_date > current_time - datetime.timedelta(minutes=2)
    ).all()

    if len(recent_trades) > 0:
        logger.debug(f"[{pair}] 2分钟内有{len(recent_trades)}笔近期交易,跳过本次入场")
        return False

    self.trailing_stop_enabled = False
    return True

3. 修改后的adjust_trade_position方法

def adjust_trade_position(self, trade: Trade, current_time: datetime,
                        current_rate: float, current_profit: float,
                        min_roi: Dict[float, float], max_profit: float):
    hold_time = (current_time - trade.open_date_utc).total_seconds() / 60
    
    # 动态调整追踪止损
    if hold_time < 5:
        trailing_stop_start = 0.02
        trailing_stop_distance = 0.008
    elif hold_time < 15:
        trailing_stop_start = 0.03
        trailing_stop_distance = 0.01
    else:
        trailing_stop_start = 0.015
        trailing_stop_distance = 0.005

    profit_ratio = (current_rate - trade.open_rate) / trade.open_rate
    
    if profit_ratio >= trailing_stop_start and not self.trailing_stop_enabled:
        self.trailing_stop_enabled = True
        trade.adjust_max_rate(current_rate)
        logger.info(f"[{trade.pair}] 价格上涨超过 {trailing_stop_start*100:.1f}%,启动 Trailing Stop")

    if self.trailing_stop_enabled:
        max_rate = trade.max_rate
        trailing_stop_price = max_rate * (1 - trailing_stop_distance)
        
        if current_rate < trailing_stop_price:
            logger.info(f"[{trade.pair}] 价格回落至 Trailing Stop 点 {trailing_stop_price:.6f},触发卖出")
            return -1
            
        trade.adjust_max_rate(current_rate)

    # 动态延长最大持仓时间
    if hold_time > 30 and current_profit < 0.005:  # 小于0.5%收益时强制平仓
        logger.info(f"[{trade.pair}] 持仓时间超过30分钟且无明显收益强制平仓")
        return -1
        
    return None

七、总结

该策略具有良好的风险控制能力特别是追踪止损机制有效防止了大幅亏损。然而策略过于保守导致交易机会较少且对FreqAI预测结果依赖过高。

建议优先改进方向:

  1. 增加备用交易信号以应对FreqAI数据缺失情况
  2. 优化特征工程,移除冗余指标
  3. 实施动态仓位管理
  4. 细化追踪止损逻辑,根据持仓时间动态调整参数
  5. 降低最小持仓时间要求,增加交易机会

下一步建议进行Hyperopt优化重点优化ROI和追踪止损参数同时考虑加入更多市场状态判断来动态调整策略行为。


  • Datetime: 2025-06-03 02:44:15

  • Model: _qwen3/qwen-plus-latest

  • Selected files:

    • result/backtest-result-2025-06-03_01-41-33_FreqaiPrimer.py
    • result/analytic.log
    • result/backtest-result-2025-06-03_01-41-33.json
    • result/backtest-result-2025-06-03_01-41-33.meta.json
    • result/backtest-result-2025-06-03_01-41-33_FreqaiPrimer.json
    • result/backtest-result-2025-06-03_01-41-33_config.json
    • result/backtest_trades.csv
    • result/output.log

实际使用中,本策略往往在某个下跌趋势的过程中给出多个买入信号, 虽然还没有跌入到谷底,但也差的不多, 然后趋势开始反转, 反转之前一些买入已经被止损了, 没被止损的订单,在小幅上升过程中也都roi了, 真正能获利超过1%的并不多

你描述的这个现象非常典型:策略在下跌趋势末期频繁尝试抄底,但多数交易因止损或小幅盈利退出,真正能捕捉到反转趋势的交易很少


📉 问题本质分析

现象总结:

  • 下跌趋势中频繁给出买入信号
  • 部分订单被止损stop_loss
  • 未止损的订单在小幅反弹后触发 ROI 卖出
  • 最终实现超过1%利润的交易很少

这说明:

问题类型 描述
过早入场 在趋势尚未明确反转时就开始抄底
止损设置不合理 在震荡行情中容易被洗出去
ROI 设置过紧 小幅反弹就卖出,错过后续上涨空间
缺乏趋势过滤机制 没有判断当前是下跌、震荡还是上升趋势

🔍 结合你的策略代码和回测结果分析

从你的原始策略来看:

buy_condition = (dataframe["&-price_value_divergence"] < self.buy_threshold) & \
                (dataframe["volume_z_score"] > 1.5) & \
                (dataframe["rsi"] < 40) & \
                (dataframe["close"] <= dataframe["bb_lowerband"])

这些条件在下跌趋势末端会频繁满足,因为:

  • &-price_value_divergence 偏离越来越大
  • RSI 经常低于 40
  • 价格经常触及布林带下轨

所以导致了频繁抄底失败


🛠️ 改进建议(实战级)

1. 添加趋势过滤器Trend Filter

避免在下跌趋势中盲目抄底,只允许在特定趋势中开仓。

示例:使用 EMA 判断趋势方向

def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    # ...原有指标计算...

    # 趋势判断
    dataframe['trend_ema'] = ta.EMA(dataframe, timeperiod=50)
    dataframe['trend_direction'] = np.where(
        dataframe['close'] > dataframe['trend_ema'], 'up', 
        np.where(dataframe['close'] < dataframe['trend_ema'], 'down', 'sideways')
    )

    return dataframe

然后在 populate_entry_trend 中加入趋势判断:

if "&-price_value_divergence" in dataframe.columns:
    buy_condition = (
        (dataframe["&-price_value_divergence"] < self.buy_threshold) &
        (dataframe["volume_z_score"] > 1.5) &
        (dataframe["rsi"] < 40) &
        (dataframe["close"] <= dataframe["bb_lowerband"]) &
        (dataframe['trend_direction'] != 'down')  # 避免在下降趋势中买入
    )

2. 动态调整止损和ROIAdaptive Exit

不要固定止损和ROI而是根据市场波动率动态调整。

示例基于ATR的动态止损

def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    # ...其他指标...
    
    # ATR用于动态止损
    dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
    dataframe['dynamic_stoploss'] = -0.01 - (dataframe['atr'] / dataframe['close']) * 1.5
    
    return dataframe

然后在策略中使用它:

def __init__(self, config: dict, *args, **kwargs):
    super().__init__(config, *args, **kwargs)
    self.stoploss = RealParameter(-0.03, -0.01, default=-0.015, space="all")

这样可以防止在波动大的时候被轻易止损。


3. 延迟入场Delay Entry Until Confirmation

不要一满足条件就入场,等待确认信号。

示例RSI + MACD 双重确认

def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    # ...其他指标...
    dataframe['macd'], dataframe['signal'], _ = ta.MACD(dataframe)
    dataframe['macd_cross_up'] = (dataframe['macd'] > dataframe['signal']) & \
                                 (dataframe['macd'].shift(1) <= dataframe['signal'].shift(1))
    return dataframe

然后修改入场逻辑:

buy_condition = (
    (dataframe["&-price_value_divergence"] < self.buy_threshold) &
    (dataframe["volume_z_score"] > 1.5) &
    (data


Error: {
  exit = 56,
  message = 'post https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions - curl error exit_code=56 stderr={ "curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0" }',
  stderr = '{ "curl: (56) OpenSSL SSL_read: error:0A000126:SSL routines::unexpected eof while reading, errno 0" }'
}

-------

- Datetime: 2025-06-03 02:45:22

- Model: _qwen3/qwen-plus-latest

- Selected files:
  - result/backtest-result-2025-06-03_01-41-33_FreqaiPrimer.py
  - result/analytic.log
  - result/backtest-result-2025-06-03_01-41-33.json
  - result/backtest-result-2025-06-03_01-41-33.meta.json
  - result/backtest-result-2025-06-03_01-41-33_FreqaiPrimer.json
  - result/backtest-result-2025-06-03_01-41-33_config.json
  - result/backtest_trades.csv
  - result/output.log

> 输出中断了,请重新输出
> 


### ✅ 3. 延迟入场Delay Entry Until Confirmation

```python
    (dataframe["rsi"] < 40) &
    (dataframe["close"] <= dataframe["bb_lowerband"]) &
    (dataframe['trend_direction'] != 'down') &
    (dataframe['macd_cross_up'])  # MACD金叉作为确认信号
)

这样可以避免在下跌趋势中过早抄底。


4. 放宽 ROI 设置让利润奔跑Let Profits Run

你提到“小幅反弹就ROI了”说明 ROI 设置太紧。我们可以:

  • 延长 ROI 时间
  • 使用动态 ROI

示例:基于波动率的动态 ROI

def generate_roi_table(self, params: Dict) -> Dict[int, float]:
    base_roi = {
        "0": params.get('roi_p1', 0.02),
        "7": params.get('roi_t1', 0.015),
        "21": params.get('roi_t2', 0.008),
        "27": 0
    }
    
    # 根据市场波动率调整ROI
    volatility = self.current_volatility  # 来自历史ATR或标准差
    if volatility > 0.02:  # 高波动时放宽ROI
        base_roi["0"] *= 1.5
        base_roi["7"] *= 1.5
    
    return base_roi

或者直接设置更宽松的默认值:

minimal_roi = {
    "0": 0.092,
    "7": 0.056,
    "21": 0.024,
    "27": 0
}

5. 使用 FreqAI 的预测方向作为过滤器

既然你已经在用 FreqAI可以利用它的预测值来判断趋势方向

if "&-price_value_divergence" in dataframe.columns:
    # 只有当预测值开始上升时才允许买入
    dataframe["prediction_up"] = (dataframe["&-price_value_divergence"].diff() > 0)
    
    buy_condition = (
        (dataframe["&-price_value_divergence"] < self.buy_threshold) &
        (dataframe["volume_z_score"] > 1.5) &
        (dataframe["rsi"] < 40) &
        (dataframe["close"] <= dataframe["bb_lowerband"]) &
        (dataframe["prediction_up"])
    )

6. 加入“连续亏损”保护机制

防止在连续止损后继续交易,建议加入一个冷却期:

def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
                       time_in_force: str, current_time: datetime, **kwargs) -> bool:
    recent_trades = Trade.query.filter(
        Trade.pair == pair,
        Trade.is_open == False,
        Trade.close_date > current_time - datetime.timedelta(minutes=30)
    ).all()

    losing_trades = [t for t in recent_trades if t.calc_profit_ratio(rate) < 0]
    
    if len(losing_trades) >= 2:
        logger.info(f"[{pair}] 最近2次交易亏损暂停入场")
        return False
        
    self.trailing_stop_enabled = False
    return True

7. 自定义出场逻辑优化

目前你的出场逻辑是:

sell_condition = (dataframe["&-price_value_divergence"] > self.sell_threshold) | (dataframe["rsi"] > 75)

建议改为分阶段卖出,比如:

def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    if "&-price_value_divergence" in dataframe.columns:
        # 分阶段退出
        dataframe.loc[
            (dataframe["&-price_value_divergence"] > self.sell_threshold * 1.2), 
            'exit_long_partial'
        ] = 1  # 先卖一半
        
        dataframe.loc[
            (dataframe["&-price_value_divergence"] > self.sell_threshold) |
            (dataframe["rsi"] > 75),
            'exit_long_full'
        ] = 1  # 再卖另一半
        
    return dataframe

然后结合 custom_sell 实现部分卖出逻辑。


📊 总结:策略改进优先级建议

改进点 优先级 说明
添加趋势过滤器 避免在下降趋势中盲目抄底
动态止损和ROI 提高止损能力,让利润奔跑
延迟入场确认 等待MACD、RSI等指标确认反转
利用FreqAI预测方向 过滤掉预测值仍在下降的信号
分阶段出场 锁定部分利润,保留上涨空间
连续亏损保护 防止连败扩大回撤

🧪 下一步建议

你可以先从以下两个改动入手,快速验证效果:

🔧 修改1添加趋势过滤器

# 在 populate_indicators 中添加
dataframe['trend_ema'] = ta.EMA(dataframe, timeperiod=50)
dataframe['in_uptrend'] = dataframe['close'] > dataframe['trend_ema']

# 在 populate_entry_trend 中添加
buy_condition = buy_condition & (dataframe['in_uptrend'])

🔧 修改2放宽止损和ROI

minimal_roi = {
    "0": 0.092,
    "7": 0.056,
    "21": 0.024,
    "27": 0
}

stoploss = -0.05  # 原为 -0.015,提高容忍度

如果你希望我帮你生成完整的修改后策略代码文件,我可以直接输出一份优化后的完整策略文件供你测试。是否需要?