feat: add Super Alpha research, management and MCP workflows
Deploy production / deploy (push) Successful in 56s

This commit is contained in:
yuxuanhui
2026-09-13 12:32:16 +08:00
parent 7c8188df9c
commit e256d6fef1
59 changed files with 3766 additions and 125 deletions
+97
View File
@@ -0,0 +1,97 @@
"""Parse only explicit component evidence; never infer actual members from a preview."""
import re
from datetime import datetime
from uuid import uuid4
from fastapi import HTTPException
from sqlalchemy import select
from ..alphas import sanitize
from ..backtests.contracts import fingerprint
from ..models import SuperSelectionSnapshot
from ..research.serialization import encode_snapshot
def parse_components(raw):
"""Return normalized rows and completeness; count/duplicate/next ambiguity stays unknown."""
warnings = []
if isinstance(raw, dict):
supplied = raw.get("warnings", [])
warnings.extend(supplied if isinstance(supplied, list) else [supplied])
rows = raw.get("results", raw.get("alphas", raw.get("components")))
total = raw.get("count", raw.get("total"))
complete_hint = raw.get("complete") is True
next_page = raw.get("next")
else:
rows, total, complete_hint, next_page = raw, None, False, None
invalid_total = total is not None and (type(total) is not int or total < 0)
total = total if type(total) is int and total >= 0 else None
valid_shape = isinstance(rows, list)
items, seen, malformed = [], set(), False
for row in rows if valid_shape else []:
entry = {"id": row} if isinstance(row, str) else row
if not isinstance(entry, dict):
malformed = True
continue
alpha_id = entry.get("id", entry.get("alpha", entry.get("alphaId")))
if not isinstance(alpha_id, str) or not re.fullmatch(r"[A-Za-z0-9_-]{1,100}", alpha_id) or alpha_id in seen:
malformed = True
continue
seen.add(alpha_id)
items.append({**sanitize(entry), "id": alpha_id})
complete = valid_shape and not malformed and not invalid_total and not next_page and (
(total is not None and total == len(items)) or (total is None and complete_hint))
if not complete:
warnings.append("组件列表未核实完整性;不生成完整组件指纹,不用于同池结论")
return {"components": items, "total": total, "complete": complete,
"component_hash": fingerprint({"alpha_ids": sorted(seen)}) if complete else None,
"warnings": sanitize(warnings)}
def snapshot_output(row, limit=25, offset=0, q=""):
items = [item for item in row.components if not q or q.lower() in str(item).lower()]
return encode_snapshot({"snapshot_id": row.id, "job_id": row.job_id, "item_id": row.item_id,
"source": row.source, "request": row.request, "request_hash": row.request_hash,
"component_hash": row.component_hash, "complete": row.complete, "reported_total": row.total,
"observed_at": row.observed_at, "warnings": row.warnings,
"status": "available" if row.complete else "unknown", "total": len(items),
"limit": limit, "offset": offset, "has_more": offset + limit < len(items),
"items": items[offset:offset + limit]})
async def read_selection(db, args):
query = select(SuperSelectionSnapshot)
query = query.where(SuperSelectionSnapshot.id == args.snapshot_id) if args.snapshot_id else query.where(
SuperSelectionSnapshot.job_id == args.job_id)
row = await db.scalar(query)
if not row:
if args.job_id:
from ..models import Job
job = await db.get(Job, args.job_id)
if not job or job.kind != "super_selection_preview":
raise HTTPException(404, "组件预览任务不存在")
return {"status": job.status, "snapshot_id": None, "job_id": job.id, "items": [],
"total": 0, "complete": False, "error": job.error, "observed_at": None}
raise HTTPException(404, "组件快照不存在")
return snapshot_output(row, args.limit, args.offset, args.q)
async def save_actual_components(db, item, detail, observed_at):
raw = detail.get("components", detail.get("selectedAlphas"))
if raw is None and isinstance(detail.get("selection"), dict):
selection = detail["selection"]
if isinstance(selection.get("alphas"), list):
raw = {"alphas": selection["alphas"], "count": selection.get("count")}
request = {"type": "SUPER", "selection": item.selection, "combo": item.combo, "settings": item.settings}
parsed = parse_components(raw)
db.add(SuperSelectionSnapshot(id=str(uuid4()), item_id=item.id, source="actual", request=request,
request_hash=fingerprint(request), raw=sanitize(raw) if isinstance(raw, (dict, list)) else {},
observed_at=datetime.fromisoformat(observed_at), **parsed))
async def actual_components(db, item_id, limit=25, offset=0):
row = await db.scalar(select(SuperSelectionSnapshot).where(SuperSelectionSnapshot.item_id == item_id))
return snapshot_output(row, limit, offset) if row else {
"status": "unknown", "complete": False, "source": "actual", "items": [], "total": 0,
"component_hash": None, "observed_at": None, "warnings": ["平台实际组件尚未核实"]}