fix: 修复因子前向填充不生效的 bug
问题根因: - reindex(method='ffill') 不会填充已存在的 NaN 值 - 当 factor_df 中已有 NaN(境外市场放假),reindex 无法填充 修复方案: - 改为两步操作:reindex() 然后 ffill() - ffill() 会填充所有 NaN,包括已存在的 影响范围: - rotation.py: positions 对齐到 A 股日历 - export_backtest_detail.py: 因子对齐到展示日历 验证结果: - 2026-04-30 HSI: nan → 0.2388 ✅ - 2026-05-08 HSI: nan → 0.1144 ✅
This commit is contained in:
@@ -155,12 +155,21 @@ def main():
|
||||
|
||||
# 将因子对齐到实际展示日历(前向填充)
|
||||
# 因子已经在原始数据上计算完成,这里只是将结果对齐到展示日历
|
||||
factor_df_aligned = factor_df.reindex(common_dates, method='ffill')
|
||||
# 注意:必须先 reindex 再 ffill,因为 reindex(method='ffill') 不会填充已有的 NaN
|
||||
factor_df_aligned = factor_df.reindex(common_dates)
|
||||
factor_df_aligned = factor_df_aligned.ffill()
|
||||
|
||||
# 调试:检查 2026-04-30 的值
|
||||
if '2026-04-30' in common_dates:
|
||||
hsi_val = factor_df_aligned.loc['2026-04-30', 'HSI'] if 'HSI' in factor_df_aligned.columns else 'NO COLUMN'
|
||||
print(f"[DEBUG] factor_df_aligned['2026-04-30', 'HSI']: {hsi_val}")
|
||||
|
||||
# 检查 factor_df 中 HSI 的最后几个有效值
|
||||
if 'HSI' in factor_df.columns:
|
||||
hsi_last_valid = factor_df['HSI'].dropna()
|
||||
if len(hsi_last_valid) > 0:
|
||||
print(f"[DEBUG] factor_df['HSI'] 最后3个有效值:")
|
||||
print(hsi_last_valid.tail(3))
|
||||
|
||||
# 持仓状态跟踪
|
||||
holdings_state = {} # {code: {'entry_date': str, 'entry_price': float}}
|
||||
|
||||
@@ -177,6 +177,19 @@ class GlobalRotationStrategy(StrategyBase):
|
||||
# 对齐所有因子的日期
|
||||
factor_df = pd.DataFrame(factors)
|
||||
|
||||
# 调试输出
|
||||
print(f"\n [DEBUG] generate_signals - factor_df 信息:")
|
||||
print(f" 索引类型: {type(factor_df.index)}")
|
||||
print(f" 总行数: {len(factor_df)}")
|
||||
print(f" 日期范围: {factor_df.index[0]} ~ {factor_df.index[-1]}")
|
||||
|
||||
# 检查 HSI 的有效数据
|
||||
if 'HSI' in factor_df.columns:
|
||||
hsi_valid = factor_df['HSI'].dropna()
|
||||
print(f" HSI 有效数据: {len(hsi_valid)} 天")
|
||||
print(f" HSI 最后3个有效值:")
|
||||
print(f" {hsi_valid.tail(3).to_dict()}")
|
||||
|
||||
# 获取动态短债阈值(如果使用)
|
||||
bond_threshold = None
|
||||
if self.use_dynamic_threshold and self.bond_code and self.bond_code in factors:
|
||||
@@ -326,7 +339,9 @@ class GlobalRotationStrategy(StrategyBase):
|
||||
print(f" [对齐] 收益率数据: {len(returns_df)} 天, {len(returns_df.columns)} 个标的")
|
||||
|
||||
# 对齐 positions 到 A 股日历
|
||||
positions = positions.reindex(trading_calendar, method='ffill')
|
||||
# 注意:必须先 reindex 再 ffill,因为 reindex(method='ffill') 不会填充已有的 NaN
|
||||
positions = positions.reindex(trading_calendar)
|
||||
positions = positions.ffill()
|
||||
|
||||
# 计算策略收益(仓位加权,T+1 执行)
|
||||
positions_delayed = positions.shift(1).fillna(0)
|
||||
|
||||
Reference in New Issue
Block a user