Skip to content

Commit 4483e9b

Browse files
committed
upd: 更新了数据库下载组件获取未来成分股的 bug,修改了 IC threshold
1 parent e1df369 commit 4483e9b

3 files changed

Lines changed: 32 additions & 9 deletions

File tree

Instruction.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@
361361
| 1 | 载入 `prices.parquet``factors_clean.parquet` |
362362
| 2 | 调用 `calc_forward_return(prices_df, d=5)` 生成 target |
363363
| 3 | 遍历每个 alpha 列,依次计算 IC 时间序列、IC metrics,展示图表 |
364-
| 4 | 筛选满足 `abs(IC mean) > 0.015``abs(ICIR) > 0.15` 的因子并输出列表 |
364+
| 4 | 筛选满足 `abs(IC mean) > 0.01``abs(ICIR) > 0.15` 的因子并输出列表 |
365365

366366
- **使用**
367367
```bash
@@ -374,7 +374,7 @@
374374
| 变量 | 默认值 | 说明 |
375375
|------|--------|------|
376376
| `FORWARD_DAYS` | `5` | 未来收益率天数 |
377-
| `IC_MEAN_THRESHOLD` | `0.015` | IC 均值绝对值阈值 |
377+
| `IC_MEAN_THRESHOLD` | `0.01` | IC 均值绝对值阈值 |
378378
| `ICIR_THRESHOLD` | `0.15` | ICIR 绝对值阈值 |
379379
| `SHOW_PLOTS` | `False` | 是否交互展示 IC 图表 |
380380

analyze_main.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
DATA_DIR = ROOT / "data"
3434
PLOTS_DIR = ROOT / "plots"
3535
FORWARD_DAYS = 5 # d-day forward return
36-
IC_MEAN_THRESHOLD = 0.015 # minimum |IC mean| to keep a factor
36+
IC_MEAN_THRESHOLD = 0.01 # minimum |IC mean| to keep a factor
3737
ICIR_THRESHOLD = 0.15 # minimum |ICIR| to keep a factor
3838
SHOW_PLOTS = False # set False to suppress interactive charts
3939
COMBINE_WINDOW = 3 # rolling OLS training window (trading days)
@@ -214,6 +214,21 @@ def main() -> None:
214214
_ok(f"Synthetic factor : {synth_df.shape[0]:>7,} rows "
215215
f"(dates: {synth_df['trade_date'].nunique()})")
216216

217+
# Apply a 3-day rolling mean per stock to smooth the signal and
218+
# reduce day-to-day portfolio turnover. Rows with fewer than 3
219+
# history points (first 2 days per stock) are dropped so the
220+
# backtester only operates on fully-smoothed scores.
221+
'''
222+
synth_df = synth_df.sort_values(["ts_code", "trade_date"]).reset_index(drop=True)
223+
synth_df["synthetic_factor"] = (
224+
synth_df.groupby("ts_code")["synthetic_factor"]
225+
.transform(lambda s: s.rolling(window=3, min_periods=3).mean())
226+
)
227+
synth_df = synth_df.dropna(subset=["synthetic_factor"]).reset_index(drop=True)
228+
_info(f" After 3-day smoothing : {synth_df.shape[0]:,} rows "
229+
f"(dates: {synth_df['trade_date'].nunique()})")
230+
'''
231+
217232
bt_synth = LayeredBacktester(synth_df, target_df, forward_days=FORWARD_DAYS, plots_dir=PLOTS_DIR)
218233
perf_synth = bt_synth.run_backtest()
219234
_info(" Backtest metrics (synthetic factor):")

src/data_loader.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,25 @@ def init_db(self) -> None:
131131
# ------------------------------------------------------------------
132132

133133
def _get_constituents(self) -> List[str]:
134-
"""Return list of ts_codes for the configured universe index."""
135-
end = datetime.now()
136-
start = end - timedelta(days=31)
134+
"""Return the index constituents as of the backtest start date.
135+
136+
Queries a 31-day window anchored at config.START_DATE so that the
137+
universe reflects the index composition at the *beginning* of the
138+
study period. Using today's constituents would introduce look-ahead
139+
bias because the CSI 300 continuously replaces weaker stocks with
140+
stronger ones, leaking future information into the stock universe.
141+
"""
142+
start_dt = datetime.strptime(config.START_DATE, "%Y%m%d")
143+
end_dt = start_dt + timedelta(days=31)
137144
df = self.pro.index_weight(
138145
index_code=config.UNIVERSE_INDEX,
139-
start_date=start.strftime("%Y%m%d"),
140-
end_date=end.strftime("%Y%m%d"),
146+
start_date=start_dt.strftime("%Y%m%d"),
147+
end_date=end_dt.strftime("%Y%m%d"),
141148
)
142149
if df is None or df.empty:
143150
raise RuntimeError(
144-
f"No constituents returned for index '{config.UNIVERSE_INDEX}'. "
151+
f"No constituents returned for index '{config.UNIVERSE_INDEX}' "
152+
f"around start date {config.START_DATE}. "
145153
"Check Tushare permissions (index_weight requires ~2000 points) "
146154
"or try '399300.SZ' instead of '000300.SH' in config.py."
147155
)

0 commit comments

Comments
 (0)