feat(pipeline): todos 补「因子晋级评审候选」源——触点②另一半上板(assessable 且近窗 t≥REVIEW_T_GATE=2,与评审页下拉同门);待办板「N 件等你决策」与评审页待办同口径,修三矛盾②(评审页等五问/待办却 0 件) [vps] [no-doc]
This commit is contained in:
@@ -612,3 +612,56 @@ def test_attribution_factor_contribution_missing_file(client, token, env):
|
||||
# env 注入目录存在但空 → [];目录整个不存在同路径 fail-soft 返 [] 不 500
|
||||
doc = client.get("/api/v1/pipeline/attribution", headers=_h(token)).json()
|
||||
assert doc["factorContribution"] == []
|
||||
|
||||
|
||||
def test_todos_factor_review_candidates(client, token, env, tmp_path, monkeypatch):
|
||||
# 三矛盾②:触点②补源——assessable 且近窗 t≥2 → 待办「待晋级评审」;
|
||||
# 无 IC 数据/t 不显著/非 assessable 一律不上板(与评审页下拉同门)
|
||||
monkeypatch.setenv("SANGUO_FACTOR_REGISTRY",
|
||||
str(tmp_path / "factor_registry.yaml"))
|
||||
with open(tmp_path / "factor_registry.yaml", "w", encoding="utf-8") as f:
|
||||
yaml.safe_dump({"factors": {
|
||||
"fa_hot": {"name": "fa_hot", "hypothesis": "H-1",
|
||||
"status": "assessable", "versions": []},
|
||||
"fa_nodata": {"name": "fa_nodata", "hypothesis": "H-2",
|
||||
"status": "assessable", "versions": []},
|
||||
"fa_weak": {"name": "fa_weak", "hypothesis": "H-3",
|
||||
"status": "assessable", "versions": []},
|
||||
"fa_prom": {"name": "fa_prom", "hypothesis": "H-4",
|
||||
"status": "promoted", "promotion_t": 3.0,
|
||||
"versions": []},
|
||||
}}, f, allow_unicode=True)
|
||||
monkeypatch.setenv("SANGUO_FACTOR_EVAL_DB",
|
||||
str(tmp_path / "no_such_eval.db"))
|
||||
from datetime import date
|
||||
from sanguo_api.routes_pipeline import set_pipeline_eval_db_path
|
||||
from sanguo_factor import eval_store
|
||||
inj_db = str(tmp_path / "factor_eval.db")
|
||||
eval_store.init_db(inj_db)
|
||||
end = date.today().isoformat()
|
||||
run_id = eval_store.create_run(inj_db, "monthly_2026-09", "sz", 10, 1,
|
||||
"2025-10-01", end, {})
|
||||
eval_store.save_results(inj_db, run_id, [
|
||||
{"factor": "fa_hot", "category": "fundamental", "expression": "x",
|
||||
"metrics": {"1": {"t_stat": 3.4, "ic_mean": 0.03, "count": 240}}},
|
||||
{"factor": "fa_weak", "category": "fundamental", "expression": "y",
|
||||
"metrics": {"1": {"t_stat": -0.2, "ic_mean": 0.001, "count": 240}}},
|
||||
])
|
||||
eval_store.finish_run(inj_db, run_id, "done", 1)
|
||||
set_pipeline_eval_db_path(inj_db)
|
||||
try:
|
||||
r = client.get("/api/v1/pipeline/todos", headers=_h(token))
|
||||
assert r.status_code == 200
|
||||
items = r.json()["items"]
|
||||
rev = [i for i in items if i["id"] == "review-fa_hot"]
|
||||
assert len(rev) == 1
|
||||
assert rev[0]["touchpoint"] == "promotion"
|
||||
assert rev[0]["path"] == "/pipeline/review"
|
||||
assert rev[0]["severity"] == "warn"
|
||||
assert "3.40" in rev[0]["detail"] or "3.4" in rev[0]["detail"]
|
||||
ids = [i["id"] for i in items]
|
||||
assert "review-fa_nodata" not in ids # 无 IC 数据不上板
|
||||
assert "review-fa_weak" not in ids # t<2 不上板
|
||||
assert "review-fa_prom" not in ids # 非 assessable 不上板
|
||||
finally:
|
||||
set_pipeline_eval_db_path("")
|
||||
|
||||
Reference in New Issue
Block a user