212ad6426d
- 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 真实数据
72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
#!/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)
|