重构 detect_h1_rapid_rise 解决回测, dryrun 和 live 表现不一致的问题, live频繁交易, 其他则不是
This commit is contained in:
parent
f7c8065bb9
commit
7d022752de
@ -1,61 +1,61 @@
|
||||
{
|
||||
"strategy_name": "FreqaiPrimer",
|
||||
"params": {
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.0125,
|
||||
"trailing_stop_positive_offset": 0.045,
|
||||
"trailing_only_offset_is_reached": false
|
||||
},
|
||||
"max_open_trades": {
|
||||
"max_open_trades": 5
|
||||
},
|
||||
"buy": {
|
||||
"add_position_callback": 0.035,
|
||||
"h1_max_candles": 246,
|
||||
"h1_max_consecutive_candles": 2,
|
||||
"h1_rapid_rise_threshold": 0.147,
|
||||
"add_bb_lower_proximity": 0.873,
|
||||
"add_position_decrease_ratio": 0.37,
|
||||
"add_rsi_oversold_threshold": 20,
|
||||
"add_stochrsi_oversold": 48,
|
||||
"adjust_multiplier": 1.13,
|
||||
"bb_length": 31,
|
||||
"bb_lower_deviation": 0.99,
|
||||
"bb_std": 3.0,
|
||||
"bb_width_threshold": 0.043,
|
||||
"max_entry_adjustments": 3,
|
||||
"min_condition_count": 3,
|
||||
"add_bb_lower_proximity": 1.161,
|
||||
"add_position_callback": 0.082,
|
||||
"add_position_decrease_ratio": 0.68,
|
||||
"add_rsi_oversold_threshold": 40,
|
||||
"add_stochrsi_oversold": 6,
|
||||
"adjust_multiplier": 1.9,
|
||||
"bb_length": 50,
|
||||
"bb_lower_deviation": 1.0,
|
||||
"bb_std": 2.9,
|
||||
"bb_width_threshold": 0.024,
|
||||
"h1_max_candles": 238,
|
||||
"h1_max_consecutive_candles": 3,
|
||||
"h1_rapid_rise_threshold": 0.068,
|
||||
"max_entry_adjustments": 11,
|
||||
"min_condition_count": 1,
|
||||
"rsi_bull_threshold": 36,
|
||||
"rsi_length": 23,
|
||||
"rsi_oversold": 62,
|
||||
"stochrsi_bull_threshold": 55,
|
||||
"stochrsi_neutral_threshold": 7,
|
||||
"volume_multiplier": 2.9
|
||||
"rsi_length": 19,
|
||||
"rsi_oversold": 16,
|
||||
"stochrsi_bull_threshold": 46,
|
||||
"stochrsi_neutral_threshold": 8,
|
||||
"volume_multiplier": 0.8
|
||||
},
|
||||
"sell": {
|
||||
"exit_bb_upper_deviation": 1.21,
|
||||
"exit_profit_tier1": 0.118,
|
||||
"exit_profit_tier2": 0.344,
|
||||
"exit_reduce_tier1": 0.6,
|
||||
"exit_reduce_tier2": 0.49,
|
||||
"exit_rsi_threshold": 41,
|
||||
"exit_volume_multiplier": 2.3,
|
||||
"exit_bb_upper_deviation": 0.92,
|
||||
"exit_profit_tier1": 0.047,
|
||||
"exit_profit_tier2": 0.076,
|
||||
"exit_reduce_tier1": 0.84,
|
||||
"exit_reduce_tier2": 0.14,
|
||||
"exit_rsi_threshold": 59,
|
||||
"exit_volume_multiplier": 4.3,
|
||||
"max_reduce_adjustments": 1,
|
||||
"reduce_coefficient": 0.467,
|
||||
"reduce_profit_base": 0.172
|
||||
"reduce_coefficient": 0.143,
|
||||
"reduce_profit_base": 0.203
|
||||
},
|
||||
"protection": {},
|
||||
"roi": {
|
||||
"0": 0.13,
|
||||
"12": 0.046,
|
||||
"24": 0.008,
|
||||
"71": 0
|
||||
"0": 0.103,
|
||||
"17": 0.072,
|
||||
"44": 0.027,
|
||||
"63": 0
|
||||
},
|
||||
"stoploss": {
|
||||
"stoploss": -0.194
|
||||
"stoploss": -0.336
|
||||
},
|
||||
"trailing": {
|
||||
"trailing_stop": true,
|
||||
"trailing_stop_positive": 0.09,
|
||||
"trailing_stop_positive_offset": 0.124,
|
||||
"trailing_only_offset_is_reached": true
|
||||
}
|
||||
},
|
||||
"ft_stratparam_v": 1,
|
||||
"export_time": "2025-11-22 11:58:03.496751+00:00"
|
||||
"export_time": "2025-11-23 06:59:43.783164+00:00"
|
||||
}
|
||||
@ -28,6 +28,7 @@ class FreqaiPrimer(IStrategy):
|
||||
def __init__(self, config=None):
|
||||
"""初始化策略参数,调用父类初始化方法并接受config参数"""
|
||||
super().__init__(config) # 调用父类的初始化方法并传递config
|
||||
assert self.h1_max_candles.value <= 50, f"h1_max_candles={self.h1_max_candles.value} 超出安全范围!"
|
||||
|
||||
@property
|
||||
def protections(self):
|
||||
@ -92,13 +93,13 @@ class FreqaiPrimer(IStrategy):
|
||||
rsi_bull_threshold = IntParameter(30, 70, default=51, optimize=True, load=True, space='buy') # 极致放宽:30-70
|
||||
stochrsi_neutral_threshold = IntParameter(5, 45, default=36, optimize=True, load=True, space='buy') # 极致放宽:5-45
|
||||
bb_width_threshold = DecimalParameter(0.001, 0.060, decimals=3, default=0.01, optimize=True, load=True, space='buy') # 极致放宽:0.001-0.060
|
||||
h1_max_candles = IntParameter(100, 300, default=246, optimize=False, load=True, space='buy')
|
||||
h1_rapid_rise_threshold = DecimalParameter(0.05, 0.15, decimals=3, default=0.147, optimize=False, load=True, space='buy')
|
||||
h1_max_consecutive_candles = IntParameter(1, 4, default=2, optimize=False, load=True, space='buy')
|
||||
h1_max_candles = IntParameter(16, 50, default=35, optimize=True, load=True, space='buy')
|
||||
h1_rapid_rise_threshold = DecimalParameter(0.05, 0.15, decimals=3, default=0.147, optimize=True, load=True, space='buy')
|
||||
h1_max_consecutive_candles = IntParameter(1, 4, default=2, optimize=True, load=True, space='buy')
|
||||
# [/propertiesGrp]
|
||||
|
||||
# [propertiesGrp step="3" name="第三轮优化" epochs="120" space="buy roi stoploss" description="剧烈拉升检测与加仓策略优化,加仓精准度与金额管理"]
|
||||
add_position_callback = DecimalParameter(0.055, 0.125, decimals=3, default=0.035, optimize=False, load=True, space='buy') # 加仓回调百分比
|
||||
# [propertiesGrp id="3" name="第三轮优化" epochs="120" space="buy roi stoploss" description="剧烈拉升检测与加仓策略优化,加仓精准度与金额管理"]
|
||||
add_position_callback = DecimalParameter(0.055, 0.125, decimals=3, default=0.083, optimize=True, load=True, space='buy') # 加仓回调百分比
|
||||
add_rsi_oversold_threshold = IntParameter(5, 65, default=16, optimize=True, load=True, space='buy') # 极致放宽:5-65
|
||||
add_stochrsi_oversold = IntParameter(1, 55, default=16, optimize=True, load=True, space='buy') # 极致放宽:1-55
|
||||
add_bb_lower_proximity = DecimalParameter(0.70, 1.35, decimals=3, default=1.065, optimize=True, load=True, space='buy') # 极致放宽:0.70-1.35
|
||||
@ -149,7 +150,7 @@ class FreqaiPrimer(IStrategy):
|
||||
return proposed_rate if proposed_rate > 0 else 0.0
|
||||
|
||||
# 入场价格折扣:98折(降低2%)
|
||||
discounted_rate = proposed_rate * 0.985
|
||||
discounted_rate = proposed_rate * 0.995
|
||||
return discounted_rate
|
||||
|
||||
def custom_stake_amount(self, pair: str, current_time: pd.Timestamp,
|
||||
@ -481,58 +482,38 @@ class FreqaiPrimer(IStrategy):
|
||||
|
||||
def detect_h1_rapid_rise(self, pair: str) -> bool:
|
||||
"""
|
||||
检测1小时K线图上的剧烈拉升情况(轻量级版本,用于confirm_trade_entry)
|
||||
参数:
|
||||
- pair: 交易对
|
||||
返回:
|
||||
- bool: 是否处于不稳固区域
|
||||
修复版剧烈拉升检测 —— 同时兼容 backtest / dry-run / live
|
||||
关键改进:
|
||||
- 强制排除最后一根未闭合的 1h K线(解决 dry-run 误杀)
|
||||
- 只看最近 N 根完整K线(N 可 hyperopt,安全范围 16-50)
|
||||
- 历史污点终身制彻底废除
|
||||
"""
|
||||
try:
|
||||
# 获取1小时K线数据
|
||||
df_1h = self.dp.get_pair_dataframe(pair=pair, timeframe='1h')
|
||||
|
||||
# 获取当前优化参数值
|
||||
max_candles = self.h1_max_candles.value
|
||||
rapid_rise_threshold = self.h1_rapid_rise_threshold.value
|
||||
max_consecutive_candles = self.h1_max_consecutive_candles.value
|
||||
|
||||
# 确保有足够的K线数据
|
||||
if len(df_1h) < max_candles:
|
||||
logger.warning(f"[{pair}] 1h K线数据不足 {max_candles} 根,当前只有 {len(df_1h)} 根,无法完整检测剧烈拉升")
|
||||
|
||||
lookback = self.h1_max_candles.value # ← 这里用你的超参数!安全范围 16-50
|
||||
|
||||
# 必须有足够数据
|
||||
if len(df_1h) < lookback + 5: # 留点余量
|
||||
return False
|
||||
|
||||
# 获取最近的K线
|
||||
recent_data = df_1h.iloc[-max_candles:].copy()
|
||||
|
||||
# 检查连续最多几根K线内的最大涨幅
|
||||
rapid_rise_detected = False
|
||||
max_rise = 0
|
||||
|
||||
for i in range(len(recent_data) - max_consecutive_candles + 1):
|
||||
window_data = recent_data.iloc[i:i + max_consecutive_candles]
|
||||
window_low = window_data['low'].min()
|
||||
window_high = window_data['high'].max()
|
||||
|
||||
# 计算区间内的最大涨幅
|
||||
if window_low > 0:
|
||||
rise_percentage = (window_high - window_low) / window_low
|
||||
if rise_percentage > max_rise:
|
||||
max_rise = rise_percentage
|
||||
|
||||
# 检查是否超过阈值
|
||||
if rise_percentage >= rapid_rise_threshold:
|
||||
rapid_rise_detected = True
|
||||
#logger.info(f"[{pair}] 检测到剧烈拉升: 从 {window_low:.2f} 到 {window_high:.2f} ({rise_percentage:.2%}) 在 {max_consecutive_candles} 根K线内")
|
||||
break
|
||||
|
||||
current_price = recent_data['close'].iloc[-1]
|
||||
#logger.info(f"[{pair}] 剧烈拉升检测结果: {'不稳固' if rapid_rise_detected else '稳固'}")
|
||||
#logger.info(f"[{pair}] 最近最大涨幅: {max_rise:.2%}")
|
||||
|
||||
return rapid_rise_detected
|
||||
|
||||
|
||||
# 关键:只看已闭合的K线!干掉最后一根正在形成的蜡烛
|
||||
closed_candles = df_1h.iloc[-lookback-1:-1] # 取最近 lookback 根完整K线
|
||||
|
||||
# 计算这段时间内从最低点到最高点的最大涨幅
|
||||
low_price = closed_candles['low'].min()
|
||||
high_price = closed_candles['high'].max()
|
||||
|
||||
if low_price <= 0:
|
||||
return False
|
||||
|
||||
rise_ratio = (high_price - low_price) / low_price
|
||||
|
||||
# 是否触发剧烈拉升阈值
|
||||
return rise_ratio >= self.h1_rapid_rise_threshold.value
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[{pair}] 剧烈拉升检测过程中发生错误: {str(e)}")
|
||||
logger.debug(f"[{pair}] 剧烈拉升检测异常: {e}")
|
||||
return False
|
||||
|
||||
def confirm_trade_entry(
|
||||
|
||||
1
tools/hyper.sh
Executable file
1
tools/hyper.sh
Executable file
@ -0,0 +1 @@
|
||||
./hyperopt_org.sh 20250610 20250625 --spaces buy --spaces sell --spaces roi --spaces trailing --spaces stoploss --jobs 8 --epochs 500
|
||||
Loading…
x
Reference in New Issue
Block a user