训练时数据长度不匹配问题
This commit is contained in:
parent
c5b35e9c09
commit
dee9cdb16a
@ -411,7 +411,7 @@ class FreqaiPrimer(IStrategy):
|
||||
logger.warning(f"[{pair}] 1h 数据为空或不足({len(dataframe_1h)} 根K线),初始化空列")
|
||||
for col in ['open_1h', 'high_1h', 'low_1h', 'close_1h', 'stochrsi_k_1h', 'stochrsi_d_1h',
|
||||
'bb_upper_1h', 'bb_middle_1h', 'bb_lower_1h', 'volume_z_score_1h']:
|
||||
dataframe[col] = np.nan
|
||||
dataframe[col] = 0.0 # 使用0.0代替np.nan避免NaN值
|
||||
else:
|
||||
# 计算 1h 指标
|
||||
if len(dataframe_1h) >= 20: # 确保有足够数据计算 rolling(20)
|
||||
@ -430,7 +430,7 @@ class FreqaiPrimer(IStrategy):
|
||||
dataframe_1h['volume_z_score_1h'] = dataframe_1h['volume_z_score_1h'].replace([np.inf, -np.inf], 0).ffill().fillna(0)
|
||||
else:
|
||||
logger.warning(f"[{pair}] 1h 数据不足以计算 volume_z_score_1h({len(dataframe_1h)} 根K线,需至少20根)")
|
||||
dataframe_1h['volume_z_score_1h'] = np.nan
|
||||
dataframe_1h['volume_z_score_1h'] = 0.0
|
||||
|
||||
# 映射 1h 数据到主时间框架
|
||||
for col in ['open', 'high', 'low', 'close', 'stochrsi_k', 'stochrsi_d', 'bb_upper_1h', 'bb_middle_1h', 'bb_lower_1h', 'volume_z_score_1h']:
|
||||
@ -438,15 +438,30 @@ class FreqaiPrimer(IStrategy):
|
||||
dataframe[col if col.endswith('_1h') else f"{col}_1h"] = dataframe_1h[col].reindex(dataframe.index, method='ffill').bfill()
|
||||
else:
|
||||
logger.warning(f"[{pair}] 1h 数据缺少列 {col},初始化为空")
|
||||
dataframe[col if col.endswith('_1h') else f"{col}_1h"] = np.nan
|
||||
dataframe[col if col.endswith('_1h') else f"{col}_1h"] = 0.0
|
||||
|
||||
# 数据清理:处理 NaN 和无穷值
|
||||
for col in ["ema200", "bb_upperband", "bb_middleband", "bb_lowerband", "rsi", "volume_z_score",
|
||||
"&-price_value_divergence", "price_value_divergence", "open_1h", "high_1h", "low_1h",
|
||||
"close_1h", "stochrsi_k_1h", "stochrsi_d_1h", "bb_upper_1h", "bb_middle_1h", "bb_lower_1h",
|
||||
"volume_z_score_1h"]:
|
||||
# 数据清理:处理 NaN 和无穷值,确保数据完整性
|
||||
critical_columns = ["ema200", "bb_upperband", "bb_middleband", "bb_lowerband", "rsi", "volume_z_score",
|
||||
"&-price_value_divergence", "price_value_divergence", "open_1h", "high_1h", "low_1h",
|
||||
"close_1h", "stochrsi_k_1h", "stochrsi_d_1h", "bb_upper_1h", "bb_middle_1h", "bb_lower_1h",
|
||||
"volume_z_score_1h", "stochrsi_k", "stochrsi_d", "close", "volume"]
|
||||
|
||||
for col in critical_columns:
|
||||
if col in dataframe.columns:
|
||||
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0).ffill().fillna(0)
|
||||
# 处理无穷值和NaN值
|
||||
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
|
||||
# 前向填充,然后用0填充剩余NaN
|
||||
dataframe[col] = dataframe[col].ffill().fillna(0)
|
||||
# 确保数据类型正确
|
||||
dataframe[col] = pd.to_numeric(dataframe[col], errors='coerce').fillna(0)
|
||||
|
||||
# 验证数据长度一致性
|
||||
expected_length = len(dataframe)
|
||||
for col in critical_columns:
|
||||
if col in dataframe.columns and len(dataframe[col]) != expected_length:
|
||||
logger.warning(f"[{pair}] 列 {col} 长度不匹配: {len(dataframe[col])} != {expected_length}")
|
||||
# 重新索引确保长度一致
|
||||
dataframe[col] = dataframe[col].reindex(dataframe.index, method='ffill').fillna(0)
|
||||
|
||||
# 调用 FreqAI 预测 - 使用单一回归模型
|
||||
if not hasattr(self, 'freqai') or self.freqai is None:
|
||||
@ -723,7 +738,20 @@ class FreqaiPrimer(IStrategy):
|
||||
f"cond5: {cond5.mean():.2%}, "
|
||||
f"buy_condition: {buy_condition.mean():.2%}")
|
||||
# 记录 enter_long 信号统计
|
||||
logger.info(f"[{pair}] enter_long 信号总数:{dataframe['enter_long'].sum() if 'enter_long' in dataframe.columns else 0}")
|
||||
enter_long_count = dataframe['enter_long'].sum() if 'enter_long' in dataframe.columns else 0
|
||||
logger.info(f"[{pair}] enter_long 信号总数:{enter_long_count}")
|
||||
|
||||
# 数据完整性检查
|
||||
if len(dataframe) > 0:
|
||||
nan_columns = [col for col in dataframe.columns if dataframe[col].isna().any()]
|
||||
if nan_columns:
|
||||
logger.warning(f"[{pair}] 发现NaN值的列: {nan_columns}")
|
||||
for col in nan_columns:
|
||||
nan_count = dataframe[col].isna().sum()
|
||||
logger.warning(f"[{pair}] 列 {col} 有 {nan_count} 个NaN值")
|
||||
|
||||
# 验证数据长度
|
||||
logger.info(f"[{pair}] 最终数据行数: {len(dataframe)}, 列数: {len(dataframe.columns)}")
|
||||
|
||||
return dataframe
|
||||
|
||||
@ -738,6 +766,11 @@ class FreqaiPrimer(IStrategy):
|
||||
dataframe["adx"] = ta.ADX(dataframe, timeperiod=14)
|
||||
# 计算短期价格涨幅(最近 5 根 K 线,约 15 分钟)
|
||||
dataframe["short_term_return"] = dataframe["close"].pct_change(5, fill_method=None) * 100 # 百分比回报
|
||||
|
||||
# 清理新计算列的NaN值
|
||||
for col in ["stochrsi_k", "adx", "short_term_return"]:
|
||||
if col in dataframe.columns:
|
||||
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0).ffill().fillna(0)
|
||||
|
||||
# 获取市场趋势得分
|
||||
trend_score = self.get_market_trend(dataframe=dataframe, metadata={'pair': pair})
|
||||
@ -808,12 +841,12 @@ class FreqaiPrimer(IStrategy):
|
||||
|
||||
conditions.append(sell_condition)
|
||||
|
||||
# 调试日志
|
||||
divergence_value = dataframe["&-price_value_divergence"].iloc[-1] if not dataframe["&-price_value_divergence"].isna().all() else np.nan
|
||||
rsi_value = dataframe["rsi"].iloc[-1] if not dataframe["rsi"].isna().all() else np.nan
|
||||
stochrsi_value = dataframe["stochrsi_k"].iloc[-1] if not dataframe["stochrsi_k"].isna().all() else np.nan
|
||||
adx_value = dataframe["adx"].iloc[-1] if not dataframe["adx"].isna().all() else np.nan
|
||||
short_term_return = dataframe["short_term_return"].iloc[-1] if not dataframe["short_term_return"].isna().all() else np.nan
|
||||
# 调试日志 - 使用安全的值获取
|
||||
divergence_value = dataframe["&-price_value_divergence"].iloc[-1] if len(dataframe) > 0 and not dataframe["&-price_value_divergence"].isna().iloc[-1] else 0.0
|
||||
rsi_value = dataframe["rsi"].iloc[-1] if len(dataframe) > 0 and not dataframe["rsi"].isna().iloc[-1] else 0.0
|
||||
stochrsi_value = dataframe["stochrsi_k"].iloc[-1] if len(dataframe) > 0 and not dataframe["stochrsi_k"].isna().iloc[-1] else 0.0
|
||||
adx_value = dataframe["adx"].iloc[-1] if len(dataframe) > 0 and not dataframe["adx"].isna().iloc[-1] else 0.0
|
||||
short_term_return = dataframe["short_term_return"].iloc[-1] if len(dataframe) > 0 and not dataframe["short_term_return"].isna().iloc[-1] else 0.0
|
||||
logger.info(f"[{pair}] 卖出条件检查 - "
|
||||
f"&-price_value_divergence={divergence_value:.6f} > {self.sell_threshold * float(self.exit_divergence_multiplier.value):.6f}: {cond1.iloc[-1]}, "
|
||||
f"rsi={rsi_value:.2f} > {float(self.exit_rsi_threshold.value)} & stochrsi_k={stochrsi_value:.2f} > {float(self.exit_stochrsi_threshold.value)}: {cond2.iloc[-1]}, "
|
||||
@ -828,6 +861,26 @@ class FreqaiPrimer(IStrategy):
|
||||
else:
|
||||
logger.info(f"[{pair}] 无有效卖出条件")
|
||||
|
||||
# 数据完整性检查
|
||||
if len(dataframe) > 0:
|
||||
nan_columns = [col for col in dataframe.columns if dataframe[col].isna().any()]
|
||||
if nan_columns:
|
||||
logger.warning(f"[{pair}] 卖出检查 - 发现NaN值的列: {nan_columns}")
|
||||
for col in nan_columns:
|
||||
nan_count = dataframe[col].isna().sum()
|
||||
if nan_count > 0:
|
||||
logger.warning(f"[{pair}] 卖出检查 - 列 {col} 有 {nan_count} 个NaN值,已清理")
|
||||
dataframe[col] = dataframe[col].fillna(0)
|
||||
|
||||
# 验证数据长度一致性
|
||||
expected_length = len(dataframe)
|
||||
actual_length = len(dataframe.dropna())
|
||||
logger.info(f"[{pair}] 卖出检查 - 数据行数: {expected_length}, 有效行数: {actual_length}")
|
||||
|
||||
# 记录exit_long信号
|
||||
exit_long_count = dataframe['exit_long'].sum() if 'exit_long' in dataframe.columns else 0
|
||||
logger.info(f"[{pair}] exit_long 信号总数:{exit_long_count}")
|
||||
|
||||
return dataframe
|
||||
|
||||
def buy_space(self):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user