fix(factor): 因子任务持久化到 backtest_results.db(type=factor)

此前 FactorReport 无 id,_on_done 不存 DB → 因子任务不进任务列表、重启丢失
(用户:历史任务列表看不到因子分析)。_on_done 现对 FactorReport 调
_persist_factor 存 backtest_stats(type=factor, strategy=因子名, symbol=标的池,
statistics={ic_summary, report_paths})。FactorReport 加 symbols/start/end 字段。
This commit is contained in:
2026-07-17 17:06:57 +08:00
parent f4cf35a7d1
commit d6162d1928
2 changed files with 29 additions and 1 deletions
+7 -1
View File
@@ -54,6 +54,9 @@ class FactorReport:
output_dir: str output_dir: str
ic_summary: dict = field(default_factory=dict) ic_summary: dict = field(default_factory=dict)
report_paths: dict = field(default_factory=dict) report_paths: dict = field(default_factory=dict)
symbols: list[str] = field(default_factory=list)
start: str = ""
end: str = ""
def run_factor_analysis( def run_factor_analysis(
@@ -371,5 +374,8 @@ def run_factor_analysis(
factor_names=factor_names, factor_names=factor_names,
output_dir=output_dir, output_dir=output_dir,
ic_summary=ic_summary, ic_summary=ic_summary,
report_paths=report_paths report_paths=report_paths,
symbols=symbols,
start=start,
end=end,
) )
+22
View File
@@ -144,8 +144,30 @@ class Orchestrator:
# load_result(result.id). FactorReport (no .id) falls back to None until S2. # load_result(result.id). FactorReport (no .id) falls back to None until S2.
task.complete(result_id=getattr(result, "id", None)) task.complete(result_id=getattr(result, "id", None))
task.raw_result = result # S2: keep in-memory result (FactorReport) for ic-summary/report task.raw_result = result # S2: keep in-memory result (FactorReport) for ic-summary/report
# S2: persist factor result so it appears in task list & survives restart
if getattr(result, "ic_summary", None) and getattr(result, "factor_names", None) is not None:
self._persist_factor(task_id, result)
await self._notify_stage(task_id, "完成") await self._notify_stage(task_id, "完成")
def _persist_factor(self, task_id: str, fr) -> None:
"""Persist FactorReport to backtest_results.db (type=factor) so it shows
in task list and survives API restart. Mirrors cta/optimize persistence."""
from sanguo_backtest.result_store import save_result, BacktestResult
try:
save_result(BacktestResult(
task_id=task_id, type="factor", status="done",
strategy=",".join(fr.factor_names),
symbol=",".join(getattr(fr, "symbols", []) or []),
params={"factor_names": fr.factor_names},
start=getattr(fr, "start", "") or "",
end=getattr(fr, "end", "") or "",
statistics={"ic_summary": fr.ic_summary, "report_paths": fr.report_paths},
equity_curve=None, trades=None,
), db_path=self.db_path)
except Exception as e:
import logging
logging.getLogger(__name__).warning("persist factor %s failed: %s", task_id, e)
def get_status(self, task_id: str) -> TaskState | None: def get_status(self, task_id: str) -> TaskState | None:
"""Get task status by ID""" """Get task status by ID"""
return self.pool.get_status(task_id) return self.pool.get_status(task_id)