""" 분석종목(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)