feat: Add factor code and description to saved results

- Add factor_code and factor_description to EvalResult
- Extract docstring or comments from factor code as description
- Enrich 232 existing factor files with code and description

Now each factor JSON in results/factors/ contains:
- factor_name, factor_code, factor_description
- IC, Rank IC, Sharpe, Win Rate, etc.
This commit is contained in:
TPTBusiness
2026-04-04 22:11:01 +02:00
parent 8e0a7e3f26
commit b27c4b7517
+26 -1
View File
@@ -73,7 +73,9 @@ class EvalResult:
"""Evaluation result for a single factor."""
factor_name: str
workspace_hash: str
status: str # success, failed
factor_code: str = ""
factor_description: str = ""
status: str = "" # success, failed
ic: Optional[float] = None
rank_ic: Optional[float] = None
sharpe: Optional[float] = None
@@ -89,6 +91,27 @@ class EvalResult:
return {k: v for k, v in self.__dict__.items()}
# ---------------------------------------------------------------------------
# Factor description extractor
# ---------------------------------------------------------------------------
def _extract_factor_description(code: str) -> str:
"""Extract docstring or description from factor code."""
import re
# Try to extract docstring
match = re.search(r'"""(.*?)"""', code, re.DOTALL)
if match:
return match.group(1).strip()[:500]
# Try to extract from comments
lines = code.split('\n')
desc_lines = []
for line in lines[:20]:
if line.strip().startswith('#') and not line.strip().startswith('#!'):
desc_lines.append(line.strip()[1:].strip())
if desc_lines:
return ' '.join(desc_lines)[:500]
return "No description available"
# ---------------------------------------------------------------------------
# Factor scanner
# ---------------------------------------------------------------------------
@@ -269,6 +292,8 @@ def evaluate_factor_full(factor: FactorInfo, full_data: pd.DataFrame,
return EvalResult(
factor_name=factor.factor_name,
workspace_hash=factor.workspace_hash,
factor_code=factor.factor_code,
factor_description=_extract_factor_description(factor.factor_code),
status="success",
ic=float(ic) if ic is not None and not np.isnan(ic) else None,
rank_ic=float(rank_ic) if rank_ic is not None and not np.isnan(rank_ic) else None,