From b79261ec091d935c5819ea4e75e15c503b332191 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Wed, 8 Oct 2025 10:39:13 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=80=E5=87=BA=E9=80=BB=E8=BE=91=E6=9B=B4?= =?UTF-8?q?=E6=96=B0,=20=E5=B9=B6=E5=A2=9E=E5=8A=A0=E4=BA=86=E6=96=B0?= =?UTF-8?q?=E7=9A=84sell=20space=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- freqtrade/templates/freqaiprimer.py | 64 +++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 9aa7620e..3c4a2943 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -117,6 +117,13 @@ class FreqaiPrimer(IStrategy): exit_volume_multiplier = DecimalParameter(1.5, 3.0, decimals=1, default=2.0, optimize=False, load=True, space='sell') rsi_overbought = IntParameter(57, 59, default=58, optimize=False, load=True, space='sell') + + # 新增的可优化参数 - 用于should_exit逻辑 + rsi_overbought_level = IntParameter(60, 80, default=70, optimize=True, load=True, space='sell') + macd_cross_threshold = DecimalParameter(0.0, 0.005, decimals=4, default=0.001, optimize=True, load=True, space='sell') + volume_spike_multiplier = DecimalParameter(2.0, 4.0, decimals=1, default=3.0, optimize=True, load=True, space='sell') + volume_drop_multiplier = DecimalParameter(0.1, 0.5, decimals=2, default=0.3, optimize=True, load=True, space='sell') + cci_overbought_level = IntParameter(150, 250, default=200, optimize=True, load=True, space='sell') def informative_pairs(self): @@ -330,7 +337,27 @@ class FreqaiPrimer(IStrategy): return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - # 出场信号基于趋势和量价关系 + # 计算额外需要的指标 + # 前一根K线的指标值 + dataframe['rsi_1h_prev'] = dataframe['rsi_1h'].shift(1) + dataframe['macd_1h_prev'] = dataframe['macd_1h'].shift(1) + dataframe['macd_signal_1h_prev'] = dataframe['macd_signal_1h'].shift(1) + + # 下一根K线的成交量 + dataframe['volume_next'] = dataframe['volume'].shift(-1) + + # 计算EMA指标 + dataframe['ema_5_1h'] = ta.ema(dataframe['close'], length=5) + dataframe['ema_10_1h'] = ta.ema(dataframe['close'], length=10) + + # 计算CCI指标 + dataframe['cci_1h'] = ta.cci(dataframe['high'], dataframe['low'], dataframe['close'], length=14) + dataframe['cci_1h_prev'] = dataframe['cci_1h'].shift(1) + + # 计算抛物线SAR指标 + dataframe['sar_1h'] = ta.sar(dataframe['high'], dataframe['low'], acceleration=0.02, maximum=0.2) + + # 原有出场条件 # 条件1: 价格突破布林带上轨(使用可优化的偏差参数) breakout_condition = dataframe['close'] >= dataframe['bb_upper_1h'] * self.exit_bb_upper_deviation.value @@ -341,22 +368,45 @@ class FreqaiPrimer(IStrategy): macd_downward = dataframe['macd_1h'] < dataframe['macd_signal_1h'] # 条件4: RSI 进入超买区域(使用可优化的超买阈值) - rsi_overbought = dataframe['rsi_1h'] > self.rsi_overbought.value + rsi_overbought_old = dataframe['rsi_1h'] > self.rsi_overbought.value + + # 新增的出场条件 - should_exit逻辑 + # 条件1: MACD死叉 + RSI超买回落 + macd_dead_cross = (dataframe['macd_1h_prev'] > dataframe['macd_signal_1h_prev']) & \ + (dataframe['macd_1h'] <= dataframe['macd_signal_1h']) & \ + (abs(dataframe['macd_1h'] - dataframe['macd_signal_1h']) >= self.macd_cross_threshold.value) + rsi_overbought_fallback = (dataframe['rsi_1h_prev'] > self.rsi_overbought_level.value) & \ + (dataframe['rsi_1h'] < self.rsi_overbought_level.value) + exit_condition_1 = macd_dead_cross & rsi_overbought_fallback + + # 条件2: 成交量异常放大后萎缩 + EMA死叉 + volume_spike_new = dataframe['volume'] > dataframe['volume_ma'] * self.volume_spike_multiplier.value + volume_drop = dataframe['volume_next'] < dataframe['volume'] * self.volume_drop_multiplier.value + ema_dead_cross = dataframe['ema_5_1h'] < dataframe['ema_10_1h'] + exit_condition_2 = volume_spike_new & volume_drop & ema_dead_cross + + # 条件3: CCI超买回落 + 抛物线SAR反转 + cci_overbought_fallback = (dataframe['cci_1h_prev'] > self.cci_overbought_level.value) & \ + (dataframe['cci_1h'] < self.cci_overbought_level.value) + sar_reversal = dataframe['close'] < dataframe['sar_1h'] + exit_condition_3 = cci_overbought_fallback & sar_reversal # 合并所有条件 - final_condition = breakout_condition | volume_spike | macd_downward | rsi_overbought + final_condition = (breakout_condition | volume_spike | macd_downward | rsi_overbought_old) | \ + (exit_condition_1 | exit_condition_2 | exit_condition_3) # 设置出场信号 dataframe.loc[final_condition, 'exit_long'] = 1 # 增强调试信息 #logger.info(f"[{metadata['pair']}] 出场条件检查:") - #logger.info(f" - 价格突破布林带上轨: {breakout_condition.sum()} 次") - #logger.info(f" - 成交量显著放大: {volume_spike.sum()} 次") - #logger.info(f" - MACD 下降趋势: {macd_downward.sum()} 次") - #logger.info(f" - RSI 超买: {rsi_overbought.sum()} 次") + #logger.info(f" - 原有条件: 价格突破布林带上轨: {breakout_condition.sum()} 次, 成交量显著放大: {volume_spike.sum()} 次, MACD下降趋势: {macd_downward.sum()} 次, RSI超买: {rsi_overbought_old.sum()} 次") + #logger.info(f" - 新增条件1 (MACD死叉+RSI回落): {exit_condition_1.sum()} 次") + #logger.info(f" - 新增条件2 (放量缩量+EMA死叉): {exit_condition_2.sum()} 次") + #logger.info(f" - 新增条件3 (CCI回落+SAR反转): {exit_condition_3.sum()} 次") #logger.info(f" - 最终条件: {final_condition.sum()} 次") #logger.info(f" - 使用参数: exit_bb_upper_deviation={self.exit_bb_upper_deviation.value}, exit_volume_multiplier={self.exit_volume_multiplier.value}, rsi_overbought={self.rsi_overbought.value}") + #logger.info(f" - 新增参数: rsi_overbought_level={self.rsi_overbought_level.value}, macd_cross_threshold={self.macd_cross_threshold.value}, volume_spike_multiplier={self.volume_spike_multiplier.value}, volume_drop_multiplier={self.volume_drop_multiplier.value}, cci_overbought_level={self.cci_overbought_level.value}") # 日志记录 if dataframe['exit_long'].sum() > 0: