修复实盘开仓频繁问题:添加入场间隔/冷启动保护/提高入场条件严格度

This commit is contained in:
zhangkun9038@dingtalk.com 2026-02-24 00:52:21 +08:00
parent e903e2c0ab
commit 369a3e7b8a

View File

@ -388,7 +388,7 @@ class FreqaiPrimer(IStrategy):
stochrsi_neutral_threshold = IntParameter(20, 30, default=25, optimize=True, load=True, space='buy') stochrsi_neutral_threshold = IntParameter(20, 30, default=25, optimize=True, load=True, space='buy')
volume_multiplier = DecimalParameter(1.2, 2.0, decimals=1, default=1.5, optimize=True, load=True, space='buy') volume_multiplier = DecimalParameter(1.2, 2.0, decimals=1, default=1.5, optimize=True, load=True, space='buy')
bb_width_threshold = DecimalParameter(0.01, 0.03, decimals=3, default=0.02, optimize=True, load=True, space='buy') bb_width_threshold = DecimalParameter(0.01, 0.03, decimals=3, default=0.02, optimize=True, load=True, space='buy')
min_condition_count = IntParameter(2, 4, default=3, optimize=True, load=True, space='buy') min_condition_count = IntParameter(3, 5, default=4, optimize=True, load=True, space='buy')
# 剧烈拉升检测参数 - 使用Hyperopt可优化参数 # 剧烈拉升检测参数 - 使用Hyperopt可优化参数
h1_max_candles = IntParameter(100, 300, default=200, optimize=True, load=True, space='buy') h1_max_candles = IntParameter(100, 300, default=200, optimize=True, load=True, space='buy')
@ -396,7 +396,7 @@ class FreqaiPrimer(IStrategy):
h1_max_consecutive_candles = IntParameter(1, 4, default=2, optimize=True, load=True, space='buy') h1_max_consecutive_candles = IntParameter(1, 4, default=2, optimize=True, load=True, space='buy')
# 入场间隔控制参数(分钟) # 入场间隔控制参数(分钟)
entry_interval_minutes = IntParameter(20, 200, default=42, optimize=True, load=True, space='buy') entry_interval_minutes = IntParameter(60, 240, default=90, optimize=True, load=True, space='buy')
# EMA20斜率阈值参数用于趋势强度过滤 # EMA20斜率阈值参数用于趋势强度过滤
ema20_slope_threshold = DecimalParameter(0.0005, 0.005, decimals=4, default=0.001, optimize=True, load=True, space='buy') ema20_slope_threshold = DecimalParameter(0.0005, 0.005, decimals=4, default=0.001, optimize=True, load=True, space='buy')
@ -1342,7 +1342,7 @@ class FreqaiPrimer(IStrategy):
) -> bool: ) -> bool:
""" """
交易买入前的确认函数用于最终决定是否执行交易 交易买入前的确认函数用于最终决定是否执行交易
此处实现从API获取数据高波动禁止入场时间戳和RMSE检查逻辑 包含入场间隔控制基础保护机制
""" """
self.strategy_log(f"[{pair}] confirm_trade_entry 被调用 - 价格: {rate:.8f}, 时间: {current_time}") self.strategy_log(f"[{pair}] confirm_trade_entry 被调用 - 价格: {rate:.8f}, 时间: {current_time}")
@ -1351,6 +1351,42 @@ class FreqaiPrimer(IStrategy):
self.strategy_log(f"[{pair}] 非多头交易,跳过入场检查") self.strategy_log(f"[{pair}] 非多头交易,跳过入场检查")
return False return False
# ========== 基础保护1入场间隔控制 ==========
if pair in self._last_entry_time:
last_entry = self._last_entry_time[pair]
time_since_last_entry = (current_time - last_entry).total_seconds() / 60
interval_minutes = self.entry_interval_minutes.value
if time_since_last_entry < interval_minutes:
self.strategy_log(
f"[{pair}] 入场间隔不足: 距离上次入场 {time_since_last_entry:.1f}分钟, "
f"需要 {interval_minutes}分钟, 拒绝入场"
)
return False
# ========== 基础保护2冷启动保护 ==========
time_since_start = (current_time - self._strategy_start_time).total_seconds()
if time_since_start < 300: # 5分钟冷启动保护
self.strategy_log(f"[{pair}] 冷启动保护中: 策略启动 {time_since_start:.0f}秒, 拒绝入场")
return False
# ========== 基础保护3检查当前技术指标 ==========
try:
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
if len(dataframe) < 10:
self.strategy_log(f"[{pair}] 数据不足,拒绝入场")
return False
last_candle = dataframe.iloc[-1]
# 检查RSI是否过高避免追高
if 'rsi' in last_candle and last_candle['rsi'] > 65:
self.strategy_log(f"[{pair}] RSI过高({last_candle['rsi']:.1f} > 65),拒绝入场")
return False
except Exception as e:
self.strategy_log(f"[{pair}] 技术指标检查出错: {str(e)}")
# 获取虚机名字 # 获取虚机名字
import os import os
virtual_host_name = os.environ.get('VIRTUAL_HOST_NAME') virtual_host_name = os.environ.get('VIRTUAL_HOST_NAME')
@ -1434,6 +1470,9 @@ class FreqaiPrimer(IStrategy):
self.strategy_log(f" - 入场信号: {values.get('&s-entry_signal')}") self.strategy_log(f" - 入场信号: {values.get('&s-entry_signal')}")
self.strategy_log(f" - 出场信号: {values.get('&s-exit_signal')}") self.strategy_log(f" - 出场信号: {values.get('&s-exit_signal')}")
# 记录入场时间
self._last_entry_time[pair] = current_time
return True return True
except requests.RequestException as e: except requests.RequestException as e:
@ -1443,8 +1482,12 @@ class FreqaiPrimer(IStrategy):
self.strategy_log(f"[{pair}] 检查过程中发生错误: {str(e)}") self.strategy_log(f"[{pair}] 检查过程中发生错误: {str(e)}")
return False return False
else: else:
# 虚机名字不是kiko跳过外部数据获取和RMSE限制直接允许入场 # 虚机名字不是kiko只使用基础保护机制
self.strategy_log(f"[{pair}] 虚机名字不是kiko跳过外部数据获取和RMSE限制直接允许入场") self.strategy_log(f"[{pair}] 虚机名字不是kiko使用基础保护机制允许入场")
# 记录入场时间
self._last_entry_time[pair] = current_time
return True return True