diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 80ff8615..158aed13 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -22,9 +22,23 @@ class FreqaiPrimer(IStrategy): stoploss = -0.01 # 固定止损 -1% trailing_stop = True - trailing_stop_positive = 0.005 # 价格上涨 0.5% 后开始追踪 trailing_stop_positive_offset = 0.008 # 追踪止损偏移量 0.8% + # 用于跟踪市场状态的数据框缓存 + _dataframe_cache = None + + @property + def trailing_stop_positive(self): + """根据市场状态动态调整跟踪止盈参数""" + # 获取当前市场状态 + if self._dataframe_cache is not None and len(self._dataframe_cache) > 0: + current_state = self._dataframe_cache['market_state'].iloc[-1] + if current_state == 'strong_bull': + return 0.01 # 强劲牛市中放宽跟踪止盈 + elif current_state == 'weak_bull': + return 0.007 + return 0.005 # 默认值 + timeframe = "3m" # 主时间框架为 3 分钟 can_short = False # 禁用做空 @@ -203,14 +217,46 @@ class FreqaiPrimer(IStrategy): return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - # 做多退出(优化以减少亏损) - dataframe.loc[ - ( - (dataframe['close'] >= dataframe['bb_upper_3m']) | - (dataframe['rsi_3m'] > self.rsi_overbought) | - (dataframe['close'] > dataframe['open'] + dataframe['atr'] * 2) # 获利2倍ATR - ), - 'exit_long'] = 1 + # 缓存数据框以便在trailing_stop_positive属性中使用 + self._dataframe_cache = dataframe + + # 基础退出条件 + basic_exit = ( + (dataframe['close'] >= dataframe['bb_upper_3m']) | + (dataframe['rsi_3m'] > self.rsi_overbought) + ) + + # 强劲趋势条件:1h趋势向上 + 熊牛得分>70 + strong_trend = (dataframe['trend_1h_ema'] == 1) & (dataframe['market_score'] > 70) + + # 一般趋势条件:熊牛得分50-70 + normal_trend = (dataframe['market_score'] >= 50) & (dataframe['market_score'] <= 70) + + # 获取15m数据进行趋势确认 + df_15m = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='15m') + df_15m = df_15m.rename(columns={'date': 'date_15m'}) + merged_data = dataframe.merge(df_15m[['date_15m', 'rsi_15m']], how='left', left_on='date', right_on='date_15m') + merged_data = merged_data.fillna(method='ffill') + + # 趋势反转信号:15m RSI超买 + trend_reversal = merged_data['rsi_15m'] > 75 + + # 动态调整退出条件 + # 强劲趋势中:只有获利达到3倍ATR才退出,或出现明确的趋势反转信号 + dataframe.loc[strong_trend & ((dataframe['close'] > dataframe['open'] + dataframe['atr'] * 3) | (basic_exit & trend_reversal)), 'exit_long'] = 1 + + # 一般趋势中:保持原有2倍ATR退出 + dataframe.loc[normal_trend & ((dataframe['close'] > dataframe['open'] + dataframe['atr'] * 2) | basic_exit), 'exit_long'] = 1 + + # 非趋势或弱势:使用基础条件+1.5倍ATR + dataframe.loc[~strong_trend & ~normal_trend & (basic_exit | (dataframe['close'] > dataframe['open'] + dataframe['atr'] * 1.5)), 'exit_long'] = 1 + + # 记录退出决策日志 + if len(dataframe[dataframe['exit_long'] == 1]) > 0: + last_exit = dataframe[dataframe['exit_long'] == 1].iloc[-1] + current_state = dataframe['market_state'].iloc[-1] + logger.info(f"[{metadata['pair']}] 触发退出信号,市场状态: {current_state}, 价格: {last_exit['close']:.2f}") + return dataframe def detect_h1_rapid_rise(self, pair: str, dataframe: DataFrame, metadata: dict) -> tuple[bool, float]: @@ -278,12 +324,54 @@ class FreqaiPrimer(IStrategy): logger.error(f"[{pair}] 剧烈拉升检测过程中发生错误: {str(e)}") return False, 0.0 - def custom_stoploss(self, pair: str, trade: 'Trade', current_time, current_rate: float, + def custom_stoploss(self, pair: str, trade: 'Trade', current_time, current_rate: float, current_profit: float, **kwargs) -> float: # 动态止损基于ATR dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) last_candle = dataframe.iloc[-1] atr = last_candle['atr'] + + # 渐进式止损策略 + if current_profit > 0.03: # 利润超过3%时 + return -1.5 * atr / current_rate # 扩大止损范围,让利润奔跑 + elif current_profit > 0.015: # 利润超过1.5%时 + return -1.2 * atr / current_rate # 轻微扩大止损范围 + if atr > 0: - return -1.0 * atr / current_rate # 收紧到1倍ATR + return -1.0 * atr / current_rate # 基础1倍ATR止损 return self.stoploss + + def custom_exit(self, pair: str, trade: 'Trade', current_time, current_rate: float, + current_profit: float, **kwargs) -> float: + """渐进式止盈逻辑""" + + # 获取当前市场状态 + dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) + current_state = dataframe['market_state'].iloc[-1] if 'market_state' in dataframe.columns else 'unknown' + + # 定义渐进式止盈水平 + profit_levels = { + # 状态: [(止盈触发利润, 止盈比例)] + 'strong_bull': [(0.02, 0.3), (0.04, 0.5), (0.06, 0.7), (0.08, 0.9)], # 强劲牛市的渐进止盈 + 'weak_bull': [(0.015, 0.3), (0.03, 0.5), (0.05, 0.8)], # 弱牛市的渐进止盈 + 'neutral': [(0.01, 0.4), (0.02, 0.7), (0.03, 0.9)], # 中性市场的渐进止盈 + 'bear': [(0.008, 0.5), (0.015, 0.8), (0.025, 1.0)] # 熊市的渐进止盈(更保守) + } + + # 默认使用中性市场的止盈设置 + levels = profit_levels.get(current_state, profit_levels['neutral']) + + # 确定当前应该止盈的比例 + exit_ratio = 0.0 + for profit_target, ratio in levels: + if current_profit >= profit_target: + exit_ratio = ratio + else: + break + + # 记录渐进式止盈决策 + if exit_ratio > 0: + logger.info(f"[{pair}] 渐进式止盈: 当前利润 {current_profit:.2%}, 市场状态 {current_state}, 止盈比例 {exit_ratio:.0%}") + + # 返回应退出的比例(0.0表示不退出,1.0表示全部退出) + return exit_ratio