@@ -195,6 +195,46 @@ def main() -> None:
195195 print (perf_synth .to_string ())
196196 bt_synth .plot (show = SHOW_PLOTS )
197197 _info (" Synthetic backtest plot saved." )
198+ '''
199+ else:
200+ _info(f"Combining {len(effective_alphas)} factors with equal weights: {effective_alphas}")
201+
202+ # --- Step 5: equal-weight combination ---
203+ sub = factors_df[["trade_date", "ts_code"] + effective_alphas].copy()
204+
205+ # 1. Cross-sectional z-score normalisation per date
206+ def _zscore(x: pd.Series) -> pd.Series:
207+ std = x.std()
208+ return (x - x.mean()) / std if std > 0 else pd.Series(0.0, index=x.index)
209+
210+ for col in effective_alphas:
211+ sub[col] = sub.groupby("trade_date")[col].transform(_zscore)
212+
213+ # 2. Flip sign for reverse factors so high score => high expected return
214+ for col in effective_alphas:
215+ if effective_alphas_ic_mean[col] < 0:
216+ _info(f" Reverse factor ({col}): negating values.")
217+ sub[col] = -sub[col]
218+
219+ # 3. Equal-weight average
220+ sub["synthetic_factor"] = sub[effective_alphas].mean(axis=1)
221+
222+ # 4. Drop rows where synthetic_factor is NaN
223+ sub = sub.dropna(subset=["synthetic_factor"])
224+
225+ synth_df = sub[["trade_date", "ts_code", "synthetic_factor"]].copy()
226+
227+ _ok(f"Synthetic factor : {synth_df.shape[0]:>7,} rows "
228+ f"(dates: {synth_df['trade_date'].nunique()})")
229+
230+ bt_synth = LayeredBacktester(synth_df, target_df, forward_days=FORWARD_DAYS, plots_dir=PLOTS_DIR)
231+ perf_synth = bt_synth.run_backtest()
232+ _info(" Backtest metrics (synthetic factor):")
233+ print(perf_synth.to_string())
234+ bt_synth.plot(show=SHOW_PLOTS)
235+ _info(" Synthetic backtest plot saved.")
236+
237+ '''
198238
199239 # ------------------------------------------------------------------
200240 # Step 6: Net-return backtest with transaction costs
0 commit comments