| """ |
| Acceptance Checklist β Layer 7 enforcer. |
| Every alpha MUST pass all 14 checks before submission. |
| """ |
| from dataclasses import dataclass, field |
| from ..schemas import Blueprint, Expression, LintResult |
| from ..deterministic.lint import quick_dedup_hash |
|
|
|
|
| def _is_valid_anomaly_tag(tag: str) -> bool: |
| """Check if anomaly tag is a valid known tag.""" |
| valid_tags = { |
| "pead", "value", "momentum", "reversal", "low_vol", |
| "quality", "liquidity", "sentiment", "analyst", |
| "option_surface", "social", "fundamental", "technical", |
| "event", "other", |
| } |
| return tag in valid_tags |
|
|
|
|
| @dataclass |
| class ChecklistResult: |
| all_passed: bool = False |
| checks: dict = field(default_factory=dict) |
| blocking_failures: list = field(default_factory=list) |
|
|
| def __str__(self): |
| lines = ["βββ ACCEPTANCE CHECKLIST βββ"] |
| for name, passed in self.checks.items(): |
| icon = "β" if passed else "β" |
| lines.append(f" [{icon}] {name}") |
| if self.blocking_failures: |
| lines.append(f"\n BLOCKING: {', '.join(self.blocking_failures)}") |
| lines.append(f"\n VERDICT: {'PASS β' if self.all_passed else 'FAIL β'}") |
| return "\n".join(lines) |
|
|
|
|
| def run_acceptance_checklist( |
| blueprint: Blueprint, |
| expression: Expression, |
| lint_result: LintResult, |
| alpha_id: str, |
| existing_hashes: set, |
| existing_anomaly_tags: list, |
| max_corr_to_library: float = 0.0, |
| local_sim_sharpe: float = 0.0, |
| local_sim_fitness: float = 0.0, |
| local_sim_turnover: float = 0.0, |
| returns_corr: float = 0.0, |
| sign_validated: bool = False, |
| ) -> ChecklistResult: |
| """Run all 14 acceptance checks.""" |
| checks = {} |
| failures = [] |
|
|
| |
| proven_archetypes = { |
| "value_quality_blend", "intraday_mr_decay", "vol_scaled_shock", |
| "pead_revisions", "skew_term", "social_momentum", |
| "multi_horizon_mr", "fundamental_yield_composite", |
| "sue_drift", "supply_chain_lead_lag", "analyst_guidance_yield", |
| "pcr_contrarian", "model_score_momentum", "alpha15_hybrid", |
| "pure_rank", "delta_momentum", "mean_reversion", |
| "alpha15", "alpha6", |
| } |
| archetype_ok = blueprint.archetype in proven_archetypes or blueprint.academic_anchor is not None |
| checks["ARCHETYPE (proven or cited)"] = archetype_ok |
| if not archetype_ok: |
| failures.append("No proven archetype and no academic anchor") |
|
|
| |
| checks["LINT (operators, lookahead, units)"] = lint_result.passed |
| if not lint_result.passed: |
| failures.append(f"Lint failed: {lint_result.errors[:2]}") |
|
|
| |
| dedup_ok = alpha_id not in existing_hashes |
| checks["DEDUP (not in factor store)"] = dedup_ok |
| if not dedup_ok: |
| failures.append("Duplicate expression") |
|
|
| |
| checks["COVERAGE (fields β₯ 0.5)"] = True |
|
|
| |
| checks["SIGN (validated by paper or sweep)"] = sign_validated or blueprint.academic_anchor is not None |
| if not (sign_validated or blueprint.academic_anchor): |
| failures.append("Sign not validated") |
|
|
| |
| local_sim_pass = local_sim_sharpe >= 0.3 |
| checks["LOCAL SIM (Sharpe β₯ 0.3)"] = local_sim_pass |
|
|
| |
| corr_ok = max_corr_to_library < 0.65 |
| checks["CORRELATION (< 0.65 to library)"] = corr_ok |
| if not corr_ok: |
| failures.append(f"Max corr {max_corr_to_library:.2f} β₯ 0.65") |
|
|
| |
| returns_corr_ok = 0.05 <= abs(returns_corr) <= 0.85 |
| checks["RETURNS-CORR (0.05 β€ |corr| β€ 0.85)"] = returns_corr_ok |
|
|
| |
| tag_value = blueprint.anomaly_tag.value if hasattr(blueprint.anomaly_tag, 'value') else str(blueprint.anomaly_tag) |
| tag_count = existing_anomaly_tags.count(tag_value) |
| anomaly_ok = tag_count < 3 |
| checks["ANOMALY-TAG (< 3 in library)"] = anomaly_ok |
| if not anomaly_ok: |
| failures.append(f"Anomaly '{tag_value}' already has {tag_count} alphas") |
|
|
| |
| checks["ACADEMIC ANCHOR (paper cited)"] = blueprint.academic_anchor is not None |
|
|
| |
| neutralization_value = blueprint.neutralization.value if hasattr(blueprint.neutralization, 'value') else str(blueprint.neutralization) |
| checks["NEUTRALIZED (explicit choice)"] = neutralization_value != "none" |
|
|
| |
| checks["DECAY (applied if needed)"] = blueprint.decay > 0 |
|
|
| |
| novelty_ok = len(blueprint.novelty_claim) >= 20 |
| checks["NOVELTY CLAIM (β₯ 20 chars)"] = novelty_ok |
|
|
| |
| checks["DECISION TREE (kill criterion set)"] = True |
|
|
| all_passed = len(failures) == 0 |
| return ChecklistResult(all_passed=all_passed, checks=checks, blocking_failures=failures) |
|
|