降低入场门槛,抬高出场门槛
This commit is contained in:
parent
f4bfa42e70
commit
b9d8ee0ebb
@ -697,45 +697,74 @@ class FreqaiPrimer(IStrategy):
|
||||
return dataframe
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 出场信号基于趋势和量价关系
|
||||
# 条件1: 价格突破布林带上轨(使用可优化的偏差参数)
|
||||
breakout_condition = dataframe['close'] >= dataframe['bb_upper_1h'] * self.exit_bb_upper_deviation.value
|
||||
# 出场信号基于趋势和量价关系 - 收紧条件减少过早出场 ⭐优化
|
||||
|
||||
# 条件2: 成交量显著放大(使用可优化的成交量乘数)
|
||||
volume_spike = dataframe['volume'] > dataframe['volume_ma'] * self.exit_volume_multiplier.value
|
||||
# 条件1: 价格显著突破布林带上轨(收紧:需要更明显的突破)
|
||||
breakout_condition = dataframe['close'] >= dataframe['bb_upper_1h'] * 1.02 # 收紧:需要超出BB上轨2%
|
||||
|
||||
# 条件3: MACD 下降趋势
|
||||
macd_downward = dataframe['macd_1h'] < dataframe['macd_signal_1h']
|
||||
# 条件2: 成交量剧烈放大(收紧:需要更大的放量)
|
||||
volume_spike = dataframe['volume'] > dataframe['volume_ma'] * 2.5 # 收紧:1.5倍 → 2.5倍
|
||||
|
||||
# 条件4: RSI 进入超买区域(使用可优化的超买阈值)
|
||||
rsi_overbought = dataframe['rsi_1h'] > self.rsi_overbought.value
|
||||
# 条件3: MACD 明确下降(收紧:需要更强的下跌确认)
|
||||
macd_downward = (
|
||||
(dataframe['macd_1h'] < dataframe['macd_signal_1h']) & # MACD < 信号线
|
||||
(dataframe['macd_hist_1h'] < 0) & # 新增:柱状图必须为负
|
||||
(dataframe['macd_hist_1h'] < dataframe['macd_hist_1h'].shift(1)) # 且递减
|
||||
)
|
||||
|
||||
# ========== KDJ 出场辅助判断 ==========
|
||||
# 3m KDJ 高位死叉:K > 80 且 K 下穿 D(部分止盈信号)
|
||||
# 条件4: RSI 极度超买(收紧:提高阈值)
|
||||
rsi_overbought = dataframe['rsi_1h'] > 75 # 收紧:70 → 75
|
||||
|
||||
# ========== KDJ 出场辅助判断(收紧条件)==========
|
||||
# 3m KDJ 极度高位死叉:K > 85 且 K 下穿 D(收紧:提高阈值)
|
||||
kdj_3m_exit = False
|
||||
if 'kdj_k_3m' in dataframe.columns and 'kdj_d_3m' in dataframe.columns:
|
||||
kdj_3m_death_cross = (dataframe['kdj_k_3m'] > 80) & (dataframe['kdj_k_3m'] < dataframe['kdj_d_3m']) & (dataframe['kdj_k_3m'].shift(1) >= dataframe['kdj_d_3m'].shift(1))
|
||||
kdj_3m_death_cross = (
|
||||
(dataframe['kdj_k_3m'] > 85) & # 收紧:80 → 85(更极端的高位)
|
||||
(dataframe['kdj_k_3m'] < dataframe['kdj_d_3m']) &
|
||||
(dataframe['kdj_k_3m'].shift(1) >= dataframe['kdj_d_3m'].shift(1))
|
||||
)
|
||||
kdj_3m_exit = kdj_3m_death_cross
|
||||
|
||||
# ========== SAR 出场辅助判断(趋势反转)==========
|
||||
# ========== SAR 出场辅助判断(保持不变)==========
|
||||
# SAR 反转是强信号,保持原逻辑
|
||||
sar_exit = False
|
||||
if 'sar_3m' in dataframe.columns:
|
||||
# SAR 反转:价格跌破 SAR 止损位(从上方穿到下方)
|
||||
# SAR 反转:价格跌破 SAR 止损位
|
||||
sar_reversal = (dataframe['close'] < dataframe['sar_3m']) & (dataframe['close'].shift(1) >= dataframe['sar_3m'].shift(1))
|
||||
sar_exit = sar_reversal
|
||||
|
||||
# ========== Ichimoku 出场辅助判断(云突破、TK死叉)==========
|
||||
# ========== Ichimoku 出场辅助判断(仅保留云突破)==========
|
||||
# 收紧:只用云突破,不用TK死叉(TK死叉太敏感)
|
||||
ichimoku_exit = False
|
||||
if 'ichimoku_price_vs_cloud_3m' in dataframe.columns and 'ichimoku_tk_cross_3m' in dataframe.columns:
|
||||
# 条件1:价格跌破云(从云上跌到云下或云中)
|
||||
price_below_cloud = (dataframe['ichimoku_price_vs_cloud_3m'] <= 0) & (dataframe['ichimoku_price_vs_cloud_3m'].shift(1) == 1)
|
||||
# 条件j:TK死叉(转换线下穿基准线)
|
||||
tk_death_cross = (dataframe['ichimoku_tk_cross_3m'] == -1) & (dataframe['ichimoku_tk_cross_3m'].shift(1) == 1)
|
||||
# 任一条件满足即触发
|
||||
ichimoku_exit = price_below_cloud | tk_death_cross
|
||||
if 'ichimoku_price_vs_cloud_3m' in dataframe.columns:
|
||||
# 仅条件1:价格跌破云(从云上跌到云下)
|
||||
price_below_cloud = (
|
||||
(dataframe['ichimoku_price_vs_cloud_3m'] == -1) & # 当前在云下
|
||||
(dataframe['ichimoku_price_vs_cloud_3m'].shift(1) == 1) # 前一根在云上
|
||||
)
|
||||
ichimoku_exit = price_below_cloud
|
||||
|
||||
# 合并所有条件(SAR、Ichimoku 作为可选信号,不强制)
|
||||
final_condition = breakout_condition | volume_spike | macd_downward | rsi_overbought | kdj_3m_exit | sar_exit | ichimoku_exit
|
||||
# ========== 合并出场条件(收紧逻辑:需要多重确认)⭐优化 ==========
|
||||
# 原逻辑:任一条件满足就出场(太敏感)
|
||||
# 新逻辑:需要满足以下任一组合
|
||||
|
||||
# 组合1:强制出场信号(单一强信号即可)
|
||||
strong_exit = sar_exit | ichimoku_exit # SAR反转或跌破云
|
||||
|
||||
# 组合2:多重技术指标确认(需要至少2个条件)
|
||||
tech_indicators = [
|
||||
breakout_condition, # 突破BB上轨
|
||||
volume_spike, # 放量
|
||||
macd_downward, # MACD下降
|
||||
rsi_overbought, # RSI超买
|
||||
kdj_3m_exit # KDJ死叉
|
||||
]
|
||||
tech_count = sum([cond.astype(int) for cond in tech_indicators])
|
||||
multi_tech_exit = tech_count >= 2 # 需要至少2个技术指标同时触发
|
||||
|
||||
# 最终出场条件:强制信号 或 多重技术确认
|
||||
final_condition = strong_exit | multi_tech_exit
|
||||
|
||||
# 设置出场信号
|
||||
dataframe.loc[final_condition, 'exit_long'] = 1
|
||||
@ -873,41 +902,42 @@ class FreqaiPrimer(IStrategy):
|
||||
|
||||
# === 底部识别(5种方法)===
|
||||
|
||||
# 方法1:传统双底识别(插针型)
|
||||
# 方法1:传统双底识别(插针型)- 放宽阈值
|
||||
recent_low_20 = dataframe['low'].rolling(window=20, min_periods=1).min()
|
||||
recent_high_20 = dataframe['high'].rolling(window=20, min_periods=1).max()
|
||||
|
||||
price_vs_recent_low = (dataframe['close'] - recent_low_20) / recent_low_20
|
||||
price_vs_recent_high = (recent_high_20 - dataframe['close']) / recent_high_20
|
||||
|
||||
near_low_traditional = price_vs_recent_low <= 0.03 # 距离低点 ≤ 3%
|
||||
near_low_traditional = price_vs_recent_low <= 0.05 # 放宽:3% → 5%(增加入场机会)
|
||||
away_from_high_traditional = price_vs_recent_high >= 0.02 # 距离高点 ≥ 2%
|
||||
|
||||
# 方法2:动量衰减识别(缓慢下跌底部)
|
||||
# 方法2:动量衰减识别(缓慢下跌底部)- 放宽条件
|
||||
price_change_5 = dataframe['close'].pct_change(5)
|
||||
price_change_10 = dataframe['close'].pct_change(10)
|
||||
|
||||
momentum_slowing_down = (
|
||||
(price_change_5 < 0) & # 仍在下跌
|
||||
(price_change_5 > price_change_10 / 2) & # 但跌幅变小
|
||||
(price_change_10 < -0.02) # 且之前有明显下跌
|
||||
(price_change_10 < -0.015) # 放宽:-2% → -1.5%(更早识别)
|
||||
)
|
||||
|
||||
# 方法3:RSI超卖识别
|
||||
# 方法3:RSI超卖识别 - 放宽阈值
|
||||
rsi_oversold = pd.Series(False, index=dataframe.index)
|
||||
if 'rsi_1h' in dataframe.columns:
|
||||
rsi_oversold = dataframe['rsi_1h'] < 35
|
||||
rsi_oversold = dataframe['rsi_1h'] < 40 # 放宽:35 → 40(更早识别超卖)
|
||||
|
||||
# 方法4:布林带下轨突破识别
|
||||
# 方法4:布林带下轨突破识别 - 放宽范围
|
||||
bb_oversold = pd.Series(False, index=dataframe.index)
|
||||
if 'bb_lower_1h' in dataframe.columns:
|
||||
bb_lower = dataframe['bb_lower_1h']
|
||||
bb_oversold = (dataframe['close'] <= bb_lower * 1.02) & (dataframe['close'] >= bb_lower * 0.98)
|
||||
# 放宽:±2% → ±5%(覆盖更多底部区域)
|
||||
bb_oversold = (dataframe['close'] <= bb_lower * 1.05) & (dataframe['close'] >= bb_lower * 0.95)
|
||||
|
||||
# 方法5:成交量萎缩识别(抛压减弱)
|
||||
# 方法5:成交量萎缩识别(抛压减弱)- 放宽条件
|
||||
volume_ma_20 = dataframe['volume'].rolling(window=20, min_periods=1).mean()
|
||||
volume_shrinking = (
|
||||
(dataframe['volume'] < volume_ma_20 * 0.7) &
|
||||
(dataframe['volume'] < volume_ma_20 * 0.8) & # 放宽:70% → 80%(更早识别)
|
||||
(price_change_5 < 0)
|
||||
)
|
||||
|
||||
@ -949,20 +979,26 @@ class FreqaiPrimer(IStrategy):
|
||||
(dataframe['macd_hist_3m'].shift(1) <= 0) # 前一根为负或零
|
||||
)
|
||||
|
||||
# === 方法7:3m StochRSI 超卖识别(比RSI更敏感)⭐新增 ===
|
||||
# === 方法7:3m StochRSI 超卖识别(比RSI更敏感)⭐新增 - 放宽阈值 ===
|
||||
stochrsi_oversold_3m = pd.Series(False, index=dataframe.index)
|
||||
if 'stochrsi_k_3m' in dataframe.columns:
|
||||
stochrsi_oversold_3m = dataframe['stochrsi_k_3m'] < 20 # 深度超卖
|
||||
stochrsi_oversold_3m = dataframe['stochrsi_k_3m'] < 30 # 放宽:20 → 30(更早识别)
|
||||
|
||||
# === 底部组合(允许入场)===
|
||||
# === 底部组合(允许入场)- 增加灵活组合 ===
|
||||
bottom_combo1 = near_low_traditional & away_from_high_traditional # 传统双底
|
||||
bottom_combo2 = momentum_slowing_down & rsi_oversold # 缓慢下跌见底
|
||||
bottom_combo3 = bb_oversold & volume_shrinking # 深度回调见底
|
||||
bottom_combo4 = rsi_oversold & away_from_high_traditional # 超卖回调
|
||||
bottom_combo5 = momentum_slowing_down & macd_turning_3m # 动量衰减+MACD反转 ⭐新增
|
||||
bottom_combo6 = stochrsi_oversold_3m & near_low_traditional # StochRSI超卖+接近低点 ⭐新增
|
||||
bottom_combo5 = momentum_slowing_down & macd_turning_3m # 动量衰减+MACD反转
|
||||
bottom_combo6 = stochrsi_oversold_3m & near_low_traditional # StochRSI超卖+接近低点
|
||||
|
||||
is_bottom = bottom_combo1 | bottom_combo2 | bottom_combo3 | bottom_combo4 | bottom_combo5 | bottom_combo6
|
||||
# === 新增:单一强信号也允许入场(提高入场频率)⭐ ===
|
||||
bottom_combo7 = near_low_traditional & rsi_oversold # 接近低点+RSI超卖(放宽组合)
|
||||
bottom_combo8 = bb_oversold & rsi_oversold # 布林带超卖+RSI超卖(双重确认)
|
||||
bottom_combo9 = stochrsi_oversold_3m & momentum_slowing_down # StochRSI+动量衰减
|
||||
|
||||
is_bottom = (bottom_combo1 | bottom_combo2 | bottom_combo3 | bottom_combo4 |
|
||||
bottom_combo5 | bottom_combo6 | bottom_combo7 | bottom_combo8 | bottom_combo9)
|
||||
|
||||
# === 顶部组合(禁止入场)⭐新增 ===
|
||||
top_combo1 = near_high_traditional # 接近历史高点(追高危险)
|
||||
@ -1199,7 +1235,7 @@ class FreqaiPrimer(IStrategy):
|
||||
self.strategy_log(f"[{pair}] 🚫 拉升后不稳固区域,取消入场")
|
||||
allow_trade = False
|
||||
|
||||
# 检查3:防止追高 - 简单规则:3m EMA20 之上拒绝入场
|
||||
# 检查3:防止追高 - 放宽规则:价格显著高于 EMA20 才拒绝(放宽条件)
|
||||
if allow_trade:
|
||||
try:
|
||||
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
@ -1210,12 +1246,12 @@ class FreqaiPrimer(IStrategy):
|
||||
# 检查 3m EMA20
|
||||
ema20_3m = float(last_row.get('ema_20_3m', current_close))
|
||||
|
||||
# 价格在 EMA20 之上 → 拒绝入场(追高)
|
||||
if current_close > ema20_3m:
|
||||
price_vs_ema20 = (current_close - ema20_3m) / ema20_3m
|
||||
# 放宽:价格高于 EMA20 超过 2% 才拒绝(之前是只要高于就拒绝)
|
||||
price_vs_ema20 = (current_close - ema20_3m) / ema20_3m
|
||||
if price_vs_ema20 > 0.02: # 新增:超过2%才算追高
|
||||
self.strategy_log(
|
||||
f"[{pair}] 🚫 追高过滤: 价格 {current_close:.6f} 高于3m EMA20 {ema20_3m:.6f} "
|
||||
f"({price_vs_ema20:+.2%}),取消入场"
|
||||
f"[{pair}] 🚫 追高过滤: 价格 {current_close:.6f} 显著高于3m EMA20 {ema20_3m:.6f} "
|
||||
f"({price_vs_ema20:+.2%} > +2%),取消入场"
|
||||
)
|
||||
allow_trade = False
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user