diff --git a/sanguo_factor/batch_eval.py b/sanguo_factor/batch_eval.py index d522c94..c0815ab 100644 --- a/sanguo_factor/batch_eval.py +++ b/sanguo_factor/batch_eval.py @@ -62,7 +62,7 @@ def run_batch_eval( raise ValueError(f"股票池为空: vnpy_db={vnpy_db} window={start}~{end}") alpha_df = bars.select(["vt_symbol", "datetime", "open", "high", "low", "close", - "volume", "turnover", "open_interest", "vwap"]) + "volume", "turnover", "vwap"]) # Pre-compute per-symbol warmup cutoff dates (bar_idx >= WARMUP_BARS 的首日) # 用于替代 per-factor hash join,改为 pivot 后 pandas 广播掩码置 NaN cutoffs = ( @@ -81,12 +81,20 @@ def run_batch_eval( close_wide.index = pd.to_datetime(close_wide.index) rets = _forward_return_matrices(close_wide) + # 保存symbols_count(删除bars前) + symbols_count = bars["vt_symbol"].n_unique() + + # 内存减负:bars(原始+bar_idx ~1G)派生完毕即释放——NAS 8G 盒防 OOM 周期性被杀 + import gc + del bars + gc.collect() + universe_label = universe if symbols is None else "custom" eval_store.init_db(eval_db) if run_id is None: run_id = eval_store.create_run( eval_db, label=label, universe=universe_label, - symbols_count=bars["vt_symbol"].n_unique(), factors_total=len(factor_names), + symbols_count=symbols_count, factors_total=len(factor_names), start=start, end=end, params={"limit": limit, "symbols": symbols[:20] if symbols else None}, # 截断防 4400 只全量塞 JSON ) done_before = set() @@ -104,7 +112,7 @@ def run_batch_eval( "factors_done": len(done_before), "errors": [], "elapsed_sec": round(time.time() - t0, 1), - "symbols_count": int(bars["vt_symbol"].n_unique()), + "symbols_count": int(symbols_count), } errors: list[str] = [] @@ -130,7 +138,7 @@ def run_batch_eval( "factors_done": len(done_before) + done, "errors": errors, "elapsed_sec": round(time.time() - t0, 1), - "symbols_count": int(bars["vt_symbol"].n_unique()), + "symbols_count": int(symbols_count), }