hyperopted

This commit is contained in:
zhangkun9038@dingtalk.com 2025-09-07 23:07:37 +08:00
parent ca1b2595a6
commit 3785332155

View File

@ -2,7 +2,7 @@ import warnings
warnings.filterwarnings("ignore", category=UserWarning, module="pandas_ta")
import logging
from freqtrade.strategy import IStrategy
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
from pandas import DataFrame
import pandas_ta as ta
from freqtrade.persistence import Trade
@ -80,17 +80,17 @@ class FreqaiPrimer(IStrategy):
timeframe = "3m" # 主时间框架为 3 分钟
can_short = False # 禁用做空
# 自定义指标参数
bb_length = 20
bb_std = 2.0
rsi_length = 14
rsi_overbought = 58 # 超买阈值
rsi_oversold = 42 # 放宽超卖阈值,增加入场信号
# 自定义指标参数 - 使用Hyperopt可优化参数
bb_length = IntParameter(10, 30, default=20, optimize=True, load=True, name='bb_length', space='buy')
bb_std = DecimalParameter(1.5, 3.0, decimals=1, default=2.0, optimize=True, load=True, name='bb_std', space='buy')
rsi_length = IntParameter(7, 21, default=14, optimize=True, load=True, name='rsi_length', space='buy')
rsi_overbought = IntParameter(50, 70, default=58, optimize=True, load=True, name='rsi_overbought', space='buy')
rsi_oversold = IntParameter(30, 50, default=42, optimize=True, load=True, name='rsi_oversold', space='buy')
# 剧烈拉升检测参数
H1_MAX_CANDLES = 200 # 检查最近200根1h K线
H1_RAPID_RISE_THRESHOLD = 0.11 # 5%的抬升阈值
H1_MAX_CONSECUTIVE_CANDLES = 2 # 最多连续3根K线内检查
# 剧烈拉升检测参数 - 使用Hyperopt可优化参数
h1_max_candles = IntParameter(100, 300, default=200, optimize=True, load=True, name='h1_max_candles', space='buy')
h1_rapid_rise_threshold = DecimalParameter(0.05, 0.15, decimals=3, default=0.11, optimize=True, load=True, name='h1_rapid_rise_threshold', space='buy')
h1_max_consecutive_candles = IntParameter(1, 4, default=2, optimize=True, load=True, name='h1_max_consecutive_candles', space='buy')
def informative_pairs(self):
pairs = self.dp.current_whitelist()
@ -107,10 +107,14 @@ class FreqaiPrimer(IStrategy):
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# 计算 3m 周期的指标
bb_3m = ta.bbands(dataframe['close'], length=self.bb_length, std=self.bb_std)
dataframe['bb_lower_3m'] = bb_3m[f'BBL_{self.bb_length}_{self.bb_std}']
dataframe['bb_upper_3m'] = bb_3m[f'BBU_{self.bb_length}_{self.bb_std}']
dataframe['rsi_3m'] = ta.rsi(dataframe['close'], length=self.rsi_length)
bb_length_value = self.bb_length.value
bb_std_value = self.bb_std.value
rsi_length_value = self.rsi_length.value
bb_3m = ta.bbands(dataframe['close'], length=bb_length_value, std=bb_std_value)
dataframe['bb_lower_3m'] = bb_3m[f'BBL_{bb_length_value}_{bb_std_value}']
dataframe['bb_upper_3m'] = bb_3m[f'BBU_{bb_length_value}_{bb_std_value}']
dataframe['rsi_3m'] = ta.rsi(dataframe['close'], length=rsi_length_value)
# 新增 StochRSI 指标
stochrsi_3m = ta.stochrsi(dataframe['close'], length=14, rsi_length=14)
@ -141,9 +145,9 @@ class FreqaiPrimer(IStrategy):
df_15m['ema_200_15m'] = ta.ema(df_15m['close'], length=200)
# 新增 StochRSI 指标
stochrsi_15m = ta.stochrsi(df_15m['close'], length=14, rsi_length=14)
df_15m['stochrsi_k_15m'] = stochrsi_15m['STOCHRSIk_14_14_3_3']
df_15m['stochrsi_d_15m'] = stochrsi_15m['STOCHRSId_14_14_3_3']
stochrsi_15m = ta.stochrsi(df_15m['close'], length=rsi_length_value, rsi_length=rsi_length_value)
df_15m['stochrsi_k_15m'] = stochrsi_15m[f'STOCHRSIk_{rsi_length_value}_{rsi_length_value}_3_3']
df_15m['stochrsi_d_15m'] = stochrsi_15m[f'STOCHRSId_{rsi_length_value}_{rsi_length_value}_3_3']
# 新增 MACD 指标
macd_15m = ta.macd(df_15m['close'], fast=12, slow=26, signal=9)
@ -163,20 +167,20 @@ class FreqaiPrimer(IStrategy):
df_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1h')
# 计算 1h 布林带
bb_1h = ta.bbands(df_1h['close'], length=self.bb_length, std=self.bb_std)
df_1h['bb_lower_1h'] = bb_1h[f'BBL_{self.bb_length}_{self.bb_std}']
df_1h['bb_upper_1h'] = bb_1h[f'BBU_{self.bb_length}_{self.bb_std}']
bb_1h = ta.bbands(df_1h['close'], length=bb_length_value, std=bb_std_value)
df_1h['bb_lower_1h'] = bb_1h[f'BBL_{bb_length_value}_{bb_std_value}']
df_1h['bb_upper_1h'] = bb_1h[f'BBU_{bb_length_value}_{bb_std_value}']
# 计算 1h RSI 和 EMA
df_1h['rsi_1h'] = ta.rsi(df_1h['close'], length=self.rsi_length)
df_1h['rsi_1h'] = ta.rsi(df_1h['close'], length=rsi_length_value)
df_1h['ema_50_1h'] = ta.ema(df_1h['close'], length=50) # 1h 50周期EMA
df_1h['ema_200_1h'] = ta.ema(df_1h['close'], length=200) # 1h 200周期EMA
df_1h['trend_1h'] = df_1h['close'] > df_1h['ema_50_1h'] # 1h上涨趋势
# 新增 StochRSI 指标
stochrsi_1h = ta.stochrsi(df_1h['close'], length=14, rsi_length=14)
df_1h['stochrsi_k_1h'] = stochrsi_1h['STOCHRSIk_14_14_3_3']
df_1h['stochrsi_d_1h'] = stochrsi_1h['STOCHRSId_14_14_3_3']
stochrsi_1h = ta.stochrsi(df_1h['close'], length=rsi_length_value, rsi_length=rsi_length_value)
df_1h['stochrsi_k_1h'] = stochrsi_1h[f'STOCHRSIk_{rsi_length_value}_{rsi_length_value}_3_3']
df_1h['stochrsi_d_1h'] = stochrsi_1h[f'STOCHRSId_{rsi_length_value}_{rsi_length_value}_3_3']
# 新增 MACD 指标
macd_1h = ta.macd(df_1h['close'], fast=12, slow=26, signal=9)
@ -187,11 +191,7 @@ class FreqaiPrimer(IStrategy):
# 验证 MACD 列是否正确生成
logger.info(f"[{metadata['pair']}] 1小时 MACD 列: {list(macd_1h.columns)}")
# 新增 StochRSI 指标
stochrsi_1h = ta.stochrsi(df_1h['close'], length=14, rsi_length=14)
df_1h['stochrsi_k_1h'] = stochrsi_1h['STOCHRSIk_14_14_3_3']
df_1h['stochrsi_d_1h'] = stochrsi_1h['STOCHRSId_14_14_3_3']
# 确保 StochRSI 指标已正确计算
# 将 1h 数据重新索引到主时间框架 (3m),并填充缺失值
df_1h = df_1h.set_index('date').reindex(dataframe['date']).ffill().bfill().reset_index()
df_1h = df_1h.rename(columns={'index': 'date'})
@ -420,20 +420,25 @@ class FreqaiPrimer(IStrategy):
# 获取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) < self.H1_MAX_CANDLES:
logger.warning(f"[{pair}] 1h K线数据不足 {self.H1_MAX_CANDLES} 根,当前只有 {len(df_1h)} 根,无法完整检测剧烈拉升")
if len(df_1h) < max_candles:
logger.warning(f"[{pair}] 1h K线数据不足 {max_candles} 根,当前只有 {len(df_1h)} 根,无法完整检测剧烈拉升")
return False
# 获取最近的K线
recent_data = df_1h.iloc[-self.H1_MAX_CANDLES:].copy()
recent_data = df_1h.iloc[-max_candles:].copy()
# 检查连续最多3根K线内的最大涨幅
# 检查连续最多根K线内的最大涨幅
rapid_rise_detected = False
max_rise = 0
for i in range(len(recent_data) - self.H1_MAX_CONSECUTIVE_CANDLES + 1):
window_data = recent_data.iloc[i:i + self.H1_MAX_CONSECUTIVE_CANDLES]
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()
@ -444,9 +449,9 @@ class FreqaiPrimer(IStrategy):
max_rise = rise_percentage
# 检查是否超过阈值
if rise_percentage >= self.H1_RAPID_RISE_THRESHOLD:
if rise_percentage >= rapid_rise_threshold:
rapid_rise_detected = True
logger.info(f"[{pair}] 检测到剧烈拉升: 从 {window_low:.2f}{window_high:.2f} ({rise_percentage:.2%}) 在 {self.H1_MAX_CONSECUTIVE_CANDLES} 根K线内")
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]