- screener/router.py: APIRouter prefix=/api/stock/screener - GET /nodes: NODE_REGISTRY + GATE_REGISTRY 메타 노출 (7 score + 1 gate) - GET /settings: screener_settings 싱글톤 row 조회 - PUT /settings: 가중치/노드/게이트 파라미터 round-trip - main.py: screener_router include (FastAPI 생성 직후) - db.py: STOCK_DB_PATH 환경변수 지원 (테스트 격리, 기본값 /app/data/stock.db 유지) - test_screener_router.py: 3 tests (nodes list, settings GET, PUT round-trip)
65 lines
2.0 KiB
Python
65 lines
2.0 KiB
Python
import os
|
|
import sqlite3
|
|
import pytest
|
|
from fastapi.testclient import TestClient
|
|
|
|
from app.screener.schema import ensure_screener_schema
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def isolated_db(tmp_path, monkeypatch):
|
|
db_path = tmp_path / "screener_router.db"
|
|
c = sqlite3.connect(db_path)
|
|
ensure_screener_schema(c)
|
|
c.close()
|
|
monkeypatch.setenv("STOCK_DB_PATH", str(db_path))
|
|
|
|
|
|
@pytest.fixture
|
|
def client():
|
|
from app.main import app
|
|
return TestClient(app)
|
|
|
|
|
|
def test_get_nodes_lists_7_score_and_1_gate(client):
|
|
r = client.get("/api/stock/screener/nodes")
|
|
assert r.status_code == 200
|
|
body = r.json()
|
|
assert len(body["score_nodes"]) == 7
|
|
assert len(body["gate_nodes"]) == 1
|
|
assert {n["name"] for n in body["score_nodes"]} == {
|
|
"foreign_buy", "volume_surge", "momentum",
|
|
"high52w", "rs_rating", "ma_alignment", "vcp_lite",
|
|
}
|
|
|
|
|
|
def test_settings_get_returns_defaults(client):
|
|
r = client.get("/api/stock/screener/settings")
|
|
assert r.status_code == 200
|
|
body = r.json()
|
|
assert body["weights"]["foreign_buy"] == 1.0
|
|
assert body["top_n"] == 20
|
|
|
|
|
|
def test_settings_put_then_get_round_trip(client):
|
|
new_settings = {
|
|
"weights": {"foreign_buy": 2.5, "momentum": 1.0, "volume_surge": 1.0,
|
|
"high52w": 1.2, "rs_rating": 1.2, "ma_alignment": 1.0, "vcp_lite": 0.8},
|
|
"node_params": {"foreign_buy": {"window_days": 7}},
|
|
"gate_params": {"min_market_cap_won": 100_000_000_000,
|
|
"min_avg_value_won": 500_000_000,
|
|
"min_listed_days": 60,
|
|
"skip_managed": True, "skip_preferred": True, "skip_spac": True,
|
|
"skip_halted_days": 3},
|
|
"top_n": 30,
|
|
"rr_ratio": 2.5,
|
|
"atr_window": 14,
|
|
"atr_stop_mult": 2.0,
|
|
}
|
|
r = client.put("/api/stock/screener/settings", json=new_settings)
|
|
assert r.status_code == 200
|
|
r2 = client.get("/api/stock/screener/settings")
|
|
body = r2.json()
|
|
assert body["weights"]["foreign_buy"] == 2.5
|
|
assert body["top_n"] == 30
|