feat: add local correlation filters and full recheck action
Deploy production / deploy (push) Successful in 54s
Deploy production / deploy (push) Successful in 54s
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
"""Full rechecks freeze all passing targets and overwrite existing correlation results."""
|
||||
|
||||
import pytest
|
||||
|
||||
from app.alphas import upsert_alpha
|
||||
from app.models import Alpha, SelfCorrelation
|
||||
from tests.conftest import alpha
|
||||
from tests.test_jobs import result
|
||||
|
||||
|
||||
async def test_recheck_all_passed_targets_deduplicates_and_repeats(app, logged_in):
|
||||
runner = app.state.runner
|
||||
async with runner.sessions.begin() as db:
|
||||
for i in range(105):
|
||||
row = await upsert_alpha(db, alpha(f"pass{i:03}"))
|
||||
row.check_type = "PRE_CHECK" if i % 2 else "PASS"
|
||||
for name, status in [("failed", "FAIL_1"), ("failed2", "FAIL_2"), ("pending", "PENDING")]:
|
||||
row = await upsert_alpha(db, alpha(name))
|
||||
row.check_type = status
|
||||
db.add(SelfCorrelation(alpha_id="pass000", region="USA", stale=False,
|
||||
result={"status": "high", "max_correlation": 0.9}))
|
||||
response = await logged_in.post("/api/v1/sync-jobs", json={"kind": "self_correlation_recheck"})
|
||||
assert response.status_code == 202
|
||||
job = response.json()
|
||||
assert job["total"] == 105
|
||||
assert job["payload"]["alpha_ids"] == [f"pass{i:03}" for i in range(105)]
|
||||
duplicate = (await logged_in.post("/api/v1/sync-jobs", json={"kind": "self_correlation_recheck"})).json()
|
||||
assert duplicate["id"] == job["id"]
|
||||
await runner.execute(job["id"])
|
||||
completed = await result(runner, job["id"])
|
||||
assert completed.status == "completed" and completed.processed == 105
|
||||
async with runner.sessions() as db:
|
||||
for i in range(105):
|
||||
cached = await db.get(SelfCorrelation, f"pass{i:03}")
|
||||
assert cached.stale is False and cached.result["max_correlation"] == 0
|
||||
assert await db.get(SelfCorrelation, "failed") is None
|
||||
assert (await db.get(Alpha, "pass000")).check_type == "PASS"
|
||||
again = (await logged_in.post("/api/v1/sync-jobs", json={"kind": "self_correlation_recheck"})).json()
|
||||
assert again["id"] != job["id"] and again["total"] == 105
|
||||
|
||||
|
||||
async def test_empty_recheck_completes_without_platform_connection(logged_in):
|
||||
response = await logged_in.post("/api/v1/sync-jobs", json={"kind": "self_correlation_recheck"})
|
||||
assert response.status_code == 202
|
||||
assert response.json()["total"] == 0 and response.json()["status"] == "completed"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("extra", [{"alpha_ids": ["target"]}, {"submission": "UNSUBMITTED"}, {"date_from": "2026-01-01"}])
|
||||
async def test_recheck_rejects_partial_scope(logged_in, extra):
|
||||
assert (await logged_in.post("/api/v1/sync-jobs", json={"kind": "self_correlation_recheck", **extra})).status_code == 422
|
||||
@@ -0,0 +1,45 @@
|
||||
"""Cached correlation filters compose before pagination and match visible states."""
|
||||
|
||||
import csv
|
||||
import io
|
||||
|
||||
import pytest
|
||||
|
||||
from app.alphas import upsert_alpha
|
||||
from app.models import SelfCorrelation
|
||||
from tests.conftest import alpha
|
||||
|
||||
|
||||
async def test_correlation_filters(app, logged_in):
|
||||
patterns = [("negative", "low", -0.4, False), ("zero", "low", 0, False),
|
||||
("yellow", "high", 0.7, False), ("boundary", "high", 0.75, False),
|
||||
("red", "high", 0.8, False), ("old", "low", 0.2, True),
|
||||
("partial", "partial", 0.5, False), ("empty", "insufficient_data", None, False)]
|
||||
async with app.state.sessions.begin() as db:
|
||||
for name, status, value, stale in patterns:
|
||||
await upsert_alpha(db, alpha(name))
|
||||
db.add(SelfCorrelation(alpha_id=name, region="USA", stale=stale,
|
||||
result={"status": status, "max_correlation": value}))
|
||||
await upsert_alpha(db, alpha("missing"))
|
||||
for status, ids in [("not_cached", ["missing"]), ("stale", ["old"]), ("low", ["negative", "zero"]),
|
||||
("high", ["boundary", "red", "yellow"]), ("partial", ["partial"]), ("insufficient_data", ["empty"])]:
|
||||
response = await logged_in.get("/api/v1/alphas", params={"local_correlation_status": status, "sort": "id", "direction": "asc"})
|
||||
assert response.status_code == 200
|
||||
assert [row["id"] for row in response.json()["items"]] == ids
|
||||
query = "local_correlation_min=0.7&local_correlation_max=0.75®ion=USA&submission=UNSUBMITTED&sort=id&direction=asc&limit=1&offset=1"
|
||||
page = (await logged_in.get(f"/api/v1/alphas?{query}")).json()
|
||||
assert page["total"] == 2 and [row["id"] for row in page["items"]] == ["yellow"]
|
||||
export = await logged_in.get(f"/api/v1/alphas/export?{query}")
|
||||
assert [row["id"] for row in csv.DictReader(io.StringIO(export.text.lstrip("\ufeff")))] == ["boundary", "yellow"]
|
||||
for query, expected in [("local_correlation_max=0", ["negative", "zero"]),
|
||||
("local_correlation_min=0.1&local_correlation_max=0.3", ["old"]),
|
||||
("local_correlation_status=low&local_correlation_min=0.1&local_correlation_max=0.3", []),
|
||||
("local_correlation_status=not_cached&local_correlation_min=-1", [])]:
|
||||
page = (await logged_in.get(f"/api/v1/alphas?{query}&sort=id&direction=asc")).json()
|
||||
assert [row["id"] for row in page["items"]] == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("query", ["local_correlation_min=0.8&local_correlation_max=0.7", "local_correlation_min=-1.1",
|
||||
"local_correlation_max=1.1", "local_correlation_min=nan", "local_correlation_status=invalid"])
|
||||
async def test_correlation_filter_validation(logged_in, query):
|
||||
assert (await logged_in.get(f"/api/v1/alphas?{query}")).status_code == 422
|
||||
Reference in New Issue
Block a user