galaxis-po/backend/tests/unit/test_screening_sector_strongest.py
2026-05-24 21:08:03 +09:00

181 lines
5.3 KiB
Python

from datetime import date
from decimal import Decimal
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from app.models.screening import ScreeningSignal
from app.models.stock import MarketIndex, Price, Sector, Stock
def _add_signal(
db: Session,
*,
ticker: str,
sector: str,
trading_value: int,
daily_return: Decimal,
is_limit_up: bool = False,
) -> None:
db.add(
ScreeningSignal(
screen_date=date(2026, 5, 22),
ticker=ticker,
name=f"{ticker} Corp",
sector=sector,
trading_value=trading_value,
daily_return=daily_return,
is_limit_up=is_limit_up,
status="pending",
)
)
def _add_stock_with_sector(db: Session, ticker: str, name: str, sector: str) -> None:
db.add(Stock(ticker=ticker, name=name, market="KOSPI", base_date=date(2026, 5, 22)))
db.add(
Sector(
ticker=ticker,
sector_code=f"S{ticker[-2:]}",
company_name=name,
sector_name=sector,
base_date=date(2026, 5, 22),
)
)
def _add_price_series(
db: Session,
ticker: str,
*,
start_close: int,
step: int,
latest_volume: int,
) -> None:
for offset in range(31):
current_date = date(2026, 4, 22 + offset) if offset <= 8 else date(2026, 5, offset - 8)
close = Decimal(start_close + (step * offset))
volume = latest_volume if offset == 30 else 1_000_000
db.add(
Price(
ticker=ticker,
date=current_date,
open=close - Decimal("10"),
high=close + Decimal("20"),
low=close - Decimal("20"),
close=close,
volume=volume,
trading_value=int(close) * volume,
)
)
def _add_kospi_series(db: Session) -> None:
for offset in range(31):
current_date = date(2026, 4, 22 + offset) if offset <= 8 else date(2026, 5, offset - 8)
close = Decimal(2500 + offset)
db.add(
MarketIndex(
code="1001",
date=current_date,
name="KOSPI",
open=close,
high=close + Decimal("5"),
low=close - Decimal("5"),
close=close,
volume=1_000_000,
trading_value=100_000_000_000,
)
)
def test_sector_strongest_returns_top_signal_per_sector(
client: TestClient,
auth_headers: dict,
db: Session,
):
_add_signal(
db,
ticker="000001",
sector="반도체",
trading_value=250_000_000_000,
daily_return=Decimal("0.0500"),
)
_add_signal(
db,
ticker="000002",
sector="반도체",
trading_value=400_000_000_000,
daily_return=Decimal("0.0300"),
)
_add_signal(
db,
ticker="000003",
sector="2차전지",
trading_value=220_000_000_000,
daily_return=Decimal("0.0100"),
)
_add_signal(
db,
ticker="000004",
sector="2차전지",
trading_value=210_000_000_000,
daily_return=Decimal("0.3000"),
is_limit_up=True,
)
db.commit()
response = client.get(
"/api/screening/sector-strongest?target_date=2026-05-22",
headers=auth_headers,
)
assert response.status_code == 200
data = response.json()
assert len(data) == 2
by_sector = {item["sector"]: item for item in data}
assert by_sector["반도체"]["ticker"] == "000002"
assert by_sector["반도체"]["signal_count"] == 2
assert by_sector["2차전지"]["ticker"] == "000004"
assert by_sector["2차전지"]["is_limit_up"] is True
assert by_sector["2차전지"]["signal_strength"] > by_sector["반도체"]["signal_strength"]
def test_recent_sector_candidates_returns_stronger_same_sector_stocks(
client: TestClient,
auth_headers: dict,
db: Session,
):
_add_signal(
db,
ticker="000001",
sector="반도체",
trading_value=120_000_000_000,
daily_return=Decimal("0.0200"),
)
_add_stock_with_sector(db, "000001", "기준전자", "반도체")
_add_stock_with_sector(db, "000002", "강한전자", "반도체")
_add_stock_with_sector(db, "000003", "약한전자", "반도체")
_add_stock_with_sector(db, "000004", "다른섹터", "자동차")
_add_kospi_series(db)
_add_price_series(db, "000001", start_close=10000, step=5, latest_volume=1_000_000)
_add_price_series(db, "000002", start_close=10000, step=250, latest_volume=8_000_000)
_add_price_series(db, "000003", start_close=10000, step=-5, latest_volume=1_000_000)
_add_price_series(db, "000004", start_close=10000, step=400, latest_volume=10_000_000)
db.commit()
response = client.get(
"/api/screening/recent-sector-candidates?as_of=2026-05-22&window_days=30",
headers=auth_headers,
)
assert response.status_code == 200
data = response.json()
assert len(data) == 1
assert data[0]["ticker"] == "000001"
assert data[0]["sector"] == "반도체"
assert data[0]["stronger_count"] == 1
assert data[0]["candidates"][0]["ticker"] == "000002"
assert data[0]["candidates"][0]["is_stronger_than_source"] is True