LightGBMRegressor

This commit is contained in:
zhangkun9038@dingtalk.com 2025-06-01 02:54:43 +00:00
parent ef4a828678
commit 677914e3ca

View File

@ -69,17 +69,19 @@ class FreqaiPrimer(IStrategy):
"verbose": -1,
},
"fit_live_predictions_candles": 100,
"live_retrain_candles": 100,
}
def __init__(self, config: dict, *args, **kwargs):
super().__init__(config, *args, **kwargs)
logger.setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG) # 保持 DEBUG 级别以查看更多日志
logger.debug("✅ 策略已初始化,日志级别设置为 DEBUG")
self.trailing_stop_enabled = False
self.trailing_stop_start = 0.03
self.trailing_stop_distance = 0.01
self.pair_stats = {}
self.stats_logged = False
self.fit_live_predictions_candles = self.freqai_info.get("fit_live_predictions_candles", 100)
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
@ -165,27 +167,31 @@ class FreqaiPrimer(IStrategy):
for col in ["ema200", "bb_upperband", "bb_middleband", "bb_lowerband", "rsi", "volume_z_score", "&-price_value_divergence", "price_value_divergence"]:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0).ffill().fillna(0)
# 添加调试日志:打印关键指标
logger.debug(f"[{pair}] 最新数据 - close{dataframe['close'].iloc[-1]:.6f}, "
f"rsi{dataframe['rsi'].iloc[-1]:.2f}, "
f"&-price_value_divergence{dataframe['&-price_value_divergence'].iloc[-1]:.6f}, "
f"volume_z_score{dataframe['volume_z_score'].iloc[-1]:.2f}, "
f"bb_lowerband{dataframe['bb_lowerband'].iloc[-1]:.6f}")
# 获取 labels_mean 和 labels_std
labels_mean = None
labels_std = None
# 调试:打印 freqai_info 和 user_data_dir
logger.debug(f"freqai_info identifier{self.freqai_info['identifier']}")
logger.debug(f"user_data_dir{self.config['user_data_dir']}")
# 从最新的子目录读取 metadata.json
try:
model_base_dir = os.path.join(self.config["user_data_dir"], "models", self.freqai_info["identifier"])
pair_base = pair.split('/')[0] if '/' in pair else pair # 取币对基础部分,例如 "TRUMP/USDT" -> "TRUMP"
pair_base = pair.split('/')[0] if '/' in pair else pair
sub_dirs = glob.glob(os.path.join(model_base_dir, f"sub-train-{pair_base}_*"))
if not sub_dirs:
logger.warning(f"[{pair}] 未找到任何子目录:{model_base_dir}/sub-train-{pair_base}_*")
else:
# 按时间戳排序,获取最新的子目录
latest_sub_dir = max(sub_dirs, key=lambda x: int(x.split('_')[-1]))
pair_base_lower = pair_base.lower() # 用于 metadata.json 文件名,例如 "TRUMP" -> "trump"
timestamp = latest_sub_dir.split('_')[-1] # 提取时间戳,例如 "1748743825"
pair_base_lower = pair_base.lower()
timestamp = latest_sub_dir.split('_')[-1]
metadata_file = os.path.join(latest_sub_dir, f"cb_{pair_base_lower}_{timestamp}_metadata.json")
if os.path.exists(metadata_file):
@ -199,22 +205,19 @@ class FreqaiPrimer(IStrategy):
except Exception as e:
logger.warning(f"[{pair}] 无法从子目录读取 labels_mean 和 labels_std{e},重新计算")
# 回退:如果无法从文件读取,则重新计算
if labels_mean is None or labels_std is None:
logger.warning(f"[{pair}] 无法获取 labels_mean 和 labels_std重新计算")
dataframe["&-price_value_divergence_actual"] = (dataframe["close"] - dataframe["ema200"]) / dataframe["ema200"]
dataframe["&-price_value_divergence_actual"] = dataframe["&-price_value_divergence_actual"].replace([np.inf, -np.inf], 0).ffill().fillna(0)
recent_data = dataframe["&-price_value_divergence_actual"].tail(self.freqai_info["fit_live_predictions_candles"])
recent_data = dataframe["&-price_value_divergence_actual"].tail(self.fit_live_predictions_candles)
labels_mean = recent_data.mean()
labels_std = recent_data.std()
if np.isnan(labels_std) or labels_std == 0:
labels_std = 0.01
logger.warning(f"[{pair}] labels_std 计算异常,使用默认值 0.01")
# 存储统计信息
self.pair_stats[pair] = {"labels_mean": labels_mean, "labels_std": labels_std}
# 计算动态阈值
if labels_std > 0.015:
k_buy = 1.2
k_sell = 1.5
@ -249,8 +252,6 @@ class FreqaiPrimer(IStrategy):
logger.info("==============================================")
self.stats_logged = True
# 移除问题日志行,避免 KeyError
# logger.info(f"[{metadata['pair']}] 指标计算完成,列:{list(dataframe.columns)}")
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
@ -258,17 +259,31 @@ class FreqaiPrimer(IStrategy):
conditions = []
if "&-price_value_divergence" in dataframe.columns:
buy_condition = (dataframe["&-price_value_divergence"] < self.buy_threshold)
buy_condition &= (dataframe["volume_z_score"] > 1.5)
buy_condition &= (dataframe["rsi"] < 40)
buy_condition &= (dataframe["close"] <= dataframe["bb_lowerband"])
# 逐个检查买入条件
cond1 = (dataframe["&-price_value_divergence"] < self.buy_threshold)
cond2 = (dataframe["volume_z_score"] > 1.5)
cond3 = (dataframe["rsi"] < 40)
cond4 = (dataframe["close"] <= dataframe["bb_lowerband"])
buy_condition = cond1 & cond2 & cond3 & cond4
conditions.append(buy_condition)
# 添加调试日志:打印条件是否满足
logger.debug(f"[{pair}] 买入条件检查 - "
f"&-price_value_divergence < {self.buy_threshold:.6f}: {cond1.iloc[-1]}, "
f"volume_z_score > 1.5: {cond2.iloc[-1]}, "
f"rsi < 40: {cond3.iloc[-1]}, "
f"close <= bb_lowerband: {cond4.iloc[-1]}")
else:
logger.warning(f"[{pair}] ⚠️ &-price_value_divergence 列缺失,跳过该条件")
if len(conditions) > 0:
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'enter_long'] = 1
logger.info(f"[{pair}] 入场信号触发,条件满足")
# 检查是否同时有卖出信号
if 'exit_long' in dataframe.columns and (dataframe["exit_long"] == 1).any():
logger.warning(f"[{pair}] 同时检测到买入和卖出信号,忽略买入信号")
dataframe['enter_long'] = 0
else:
logger.debug(f"[{pair}] 入场信号触发,条件满足") # 改为 DEBUG 级别
return dataframe
@ -277,15 +292,22 @@ class FreqaiPrimer(IStrategy):
conditions = []
if "&-price_value_divergence" in dataframe.columns:
sell_condition = (dataframe["&-price_value_divergence"] > self.sell_threshold)
sell_condition |= (dataframe["rsi"] > 75)
# 逐个检查卖出条件
cond1 = (dataframe["&-price_value_divergence"] > self.sell_threshold)
cond2 = (dataframe["rsi"] > 75)
sell_condition = cond1 | cond2
conditions.append(sell_condition)
# 添加调试日志:打印条件是否满足
logger.debug(f"[{pair}] 卖出条件检查 - "
f"&-price_value_divergence > {self.sell_threshold:.6f}: {cond1.iloc[-1]}, "
f"rsi > 75: {cond2.iloc[-1]}")
else:
logger.warning(f"[{pair}] ⚠️ &-price_value_divergence 列缺失,跳过该条件")
if len(conditions) > 0:
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'exit_long'] = 1
logger.info(f"[{pair}] 出场信号触发,条件满足")
logger.debug(f"[{pair}] 出场信号触发,条件满足") # 改为 DEBUG 级别
return dataframe
@ -319,14 +341,18 @@ class FreqaiPrimer(IStrategy):
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time: datetime, **kwargs) -> bool:
# 添加调试日志:检查是否允许买入
recent_trades = Trade.get_trades(
pair=pair,
is_open=False,
close_date=current_time - datetime.timedelta(minutes=5)
).all()
if len(recent_trades) > 0:
logger.info(f"[{pair}] 5分钟内有近期交易,跳过本次入场")
logger.info(f"[{pair}] 5分钟内有近期交易{len(recent_trades)} 笔),跳过本次入场")
return False
# 检查其他限制(例如资金、仓位等)
logger.debug(f"[{pair}] 允许买入 - 订单类型:{order_type}, 数量:{amount:.2f}, 价格:{rate:.6f}, 时间:{current_time}")
self.trailing_stop_enabled = False
return True