Files
auto-stock/backend/app/services/watchlist.py
2026-02-22 17:23:20 +09:00

64 lines
2.1 KiB
Python

"""
분석종목(Watchlist) 관리 공용 서비스
아침 배치(batch_daily_analysis)와 장중 배치(batch_intraday_analysis)가 공유하는
초기화 함수. 각 배치 스크립트가 자신의 AsyncSession을 전달해 사용한다.
"""
from datetime import datetime, date
import logging
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.models import WatchlistStock, StockAnalysis
logger = logging.getLogger(__name__)
# 분석종목 관련 상수
WATCHLIST_INIT_SIZE: int = 50 # 아침 배치 초기화 종목 수
WATCHLIST_MAX_SIZE: int = 100 # 최대 관리 종목 수
WATCHLIST_ENTRY_SCORE: int = 60 # 장중 신규 진입 기준 점수
WATCHLIST_EXIT_SCORE: int = 20 # 장중 제거 기준 점수
async def initialize_watchlist(session: AsyncSession, analysis_date: date) -> int:
"""아침 배치 완료 후 분석종목 초기화.
기존 활성 종목을 전부 비활성화하고,
오늘 stock_analysis score 상위 WATCHLIST_INIT_SIZE 개로 새로 채운다.
Returns: 추가된 종목 수
"""
now = datetime.now()
# 1. 기존 활성 종목 전부 비활성화
await session.execute(
update(WatchlistStock)
.where(WatchlistStock.is_active == True)
.values(is_active=False, removed_at=now, removed_reason="daily_reset")
)
# 2. 오늘 score 상위 N개 조회
result = await session.execute(
select(StockAnalysis.stock_code, StockAnalysis.stock_name, StockAnalysis.score)
.where(StockAnalysis.analysis_date == analysis_date)
.order_by(StockAnalysis.score.desc())
.limit(WATCHLIST_INIT_SIZE)
)
top_stocks = result.all()
# 3. 신규 활성 종목 등록
for row in top_stocks:
session.add(WatchlistStock(
stock_code=row.stock_code,
stock_name=row.stock_name,
added_at=now,
added_reason="morning_batch",
score_at_add=row.score,
is_active=True,
))
await session.commit()
logger.info(f"📋 분석종목 초기화 완료: {len(top_stocks)}개 (기준일: {analysis_date})")
return len(top_stocks)