feat(s2): 投研核心端到端跑通(IC 表 + tears 报告)
- Task 加 raw_result 字段;orchestrator get_raw_result(内存存 FactorReport)
- 路由 /factor/list、/task/{id}/ic-summary、/task/{id}/report/{factor}(query token 给 iframe)
- analyzer cfg=None 时加载 data_platform.yaml(修 API 路径 read_db_daily 崩)
- get_status 返回 error_msg(调试+前端 failed 展示)
- 前端 投研-新建(多因子/多标的/日期)+ 结果页(IC 表 + tears iframe)
- factor 冒烟通过:ma5 → IC 1D/5D/10D 真实数据
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Phase 3b S2 end-to-end smoke: login -> submit factor analysis (ma5,
|
||||
multi-symbol) -> poll -> verify ic-summary non-empty.
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
|
||||
BASE = "http://192.168.2.154:8000"
|
||||
|
||||
|
||||
def _req(method, path, token=None, body=None):
|
||||
headers = {"Content-Type": "application/json"}
|
||||
if token:
|
||||
headers["Authorization"] = f"Bearer {token}"
|
||||
data = json.dumps(body).encode() if body is not None else None
|
||||
req = urllib.request.Request(BASE + path, data=data, headers=headers, method=method)
|
||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||
return json.loads(resp.read())
|
||||
|
||||
|
||||
def main() -> int:
|
||||
tok = _req("POST", "/api/v1/auth/login", body={"username": "admin", "password": "admin"})["token"]
|
||||
print("[1] login OK")
|
||||
|
||||
fl = _req("GET", "/api/v1/factor/list", token=tok)
|
||||
print(f"[2] factors: {[f['name'] for f in fl['factors']]}")
|
||||
|
||||
sub = _req("POST", "/api/v1/factor/analyze", token=tok, body={
|
||||
"symbols": ["600000", "000001", "300750"],
|
||||
"factor_names": ["ma5"],
|
||||
"start": "2024-01-01",
|
||||
"end": "2024-06-30",
|
||||
})
|
||||
tid = sub["task_id"]
|
||||
print(f"[3] submitted: {tid}")
|
||||
|
||||
status = "pending"
|
||||
for i in range(60):
|
||||
s = _req("GET", f"/api/v1/task/{tid}", token=tok)
|
||||
status = s["status"]
|
||||
print(f" [{i:02d}] status={status} stage={s.get('stage', '')}")
|
||||
if status in ("done", "failed"):
|
||||
break
|
||||
time.sleep(3)
|
||||
|
||||
if status != "done":
|
||||
print(f"[!] factor analysis did not complete: {status}")
|
||||
return 1
|
||||
|
||||
ic = _req("GET", f"/api/v1/task/{tid}/ic-summary", token=tok)["ic_summary"]
|
||||
print(f"[4] ic_summary keys: {list(ic.keys())}")
|
||||
assert "ma5" in ic, "ma5 missing from ic_summary"
|
||||
ma5 = ic["ma5"]
|
||||
print(f" ma5 status: {ma5.get('status')}")
|
||||
print(f" ma5 ic: {json.dumps(ma5.get('ic', {}), ensure_ascii=False)[:300]}")
|
||||
assert ma5.get("ic"), "ma5 ic empty"
|
||||
print("[5] SMOKE PASSED")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main())
|
||||
except AssertionError as e:
|
||||
print(f"[SMOKE FAILED] {e}")
|
||||
sys.exit(2)
|
||||
except Exception as e:
|
||||
print(f"[SMOKE ERROR] {type(e).__name__}: {e}")
|
||||
sys.exit(3)
|
||||
Reference in New Issue
Block a user