diff --git a/backend/app/api/endpoints/backtest.py b/backend/app/api/endpoints/backtest.py index 4db991d..6ea568f 100644 --- a/backend/app/api/endpoints/backtest.py +++ b/backend/app/api/endpoints/backtest.py @@ -35,7 +35,7 @@ logger = logging.getLogger(__name__) _cached_training_data: Optional[Dict[str, Any]] = None -# ── Pydantic 스키마 ──────────────────────────────────────────────────────────── +# ── Pydantic 스키마 ────────────────────────────────────────────────────── class GenerateTrainingDataRequest(BaseModel): stock_codes: List[str] = Field(..., description="대상 종목 코드 목록") @@ -76,7 +76,7 @@ class RunUniverseBacktestRequest(BaseModel): top_n_results: int = Field(20, description="성과 상위 N개만 반환") -# ── API 엔드포인트 ───────────────────────────────────────────────────────────── +# ── API 엔드포인트 ───────────────────────────────────────────────────── @router.get("/universe-presets") async def api_get_universe_presets() -> Dict[str, Any]: @@ -84,33 +84,20 @@ async def api_get_universe_presets() -> Dict[str, Any]: 사전 정의된 종목 유니버스 프리셋 목록 Returns: - {'large_cap': {...}, 'kospi_all': {...}, ...} + {'large_cap': {'description': '...', 'filter': {...}}, ...} """ presets = StockUniverse.get_preset_universes() # StockFilter를 dict로 변환 from dataclasses import asdict - return { - key: { - **asdict(filter_obj), - "description": _get_preset_description(key) + result = {} + for key, preset_data in presets.items(): + result[key] = { + "description": preset_data["description"], + "filter": asdict(preset_data["filter"]) } - for key, filter_obj in presets.items() - } - - -def _get_preset_description(preset_key: str) -> str: - """프리셋 설명""" - descriptions = { - "all": "전체 종목 (관리종목 제외)", - "kospi_all": "KOSPI 전체", - "kosdaq_all": "KOSDAQ 전체", - "large_cap": "대형주 (KOSPI 시총 1조 이상, 상위 100)", - "mid_cap": "중형주 (KOSPI 시총 3천억 이상, 상위 200)", - "liquid_kosdaq": "유동성 높은 KOSDAQ (거래량 20만주+, 상위 100)", - "penny_stocks": "저가주 (1~5천원, 고거래량, 상위 50)", - } - return descriptions.get(preset_key, "") + + return result @router.post("/run-universe") @@ -133,7 +120,8 @@ async def api_run_universe_backtest(req: RunUniverseBacktestRequest) -> Dict[str if req.universe_preset not in presets: raise HTTPException(status_code=400, detail=f"잘못된 유니버스 프리셋: {req.universe_preset}") - stock_filter = presets[req.universe_preset] + # 새로운 구조: {'description': '...', 'filter': StockFilter(...)} + stock_filter = presets[req.universe_preset]["filter"] stock_codes = await StockUniverse.get_filtered_stocks(stock_filter) if not stock_codes: @@ -248,7 +236,7 @@ async def api_generate_training_data(req: GenerateTrainingDataRequest) -> Dict[s if "error" in result: raise HTTPException(status_code=500, detail=result["error"]) - # 데이터 캠싱 (CSV 다운로드용) + # 데이터 캐싱 (CSV 다운로드용) _cached_training_data = result # DataFrame을 직렬화할 수 없으므로 통계만 반환