diff --git a/backend/app/services/collectors/etf_collector.py b/backend/app/services/collectors/etf_collector.py index 0ed2b1f..b281c1b 100644 --- a/backend/app/services/collectors/etf_collector.py +++ b/backend/app/services/collectors/etf_collector.py @@ -48,6 +48,16 @@ class ETFCollector(BaseCollector): else: return AssetClass.MIXED.value + def _get_openapi_ticker(self, row) -> str: + """Extract 6-digit ticker from KRX Open API rows.""" + ticker = row.get("ISU_SRT_CD", row.get("ISU_CD", "")) + if pd.isna(ticker): + return "" + if isinstance(ticker, float): + return str(int(ticker)).zfill(6) + ticker = str(ticker).strip() + return ticker.zfill(6) if ticker.isdigit() else ticker + def _fetch_etf_data_openapi(self) -> pd.DataFrame: """Fetch ETF data via KRX Open API.""" client = get_krx_client() @@ -96,8 +106,8 @@ class ETFCollector(BaseCollector): """Parse Open API response DataFrame into ETF records.""" records = [] for _, row in df.iterrows(): - ticker = row.get("ISU_SRT_CD") - name = row.get("ISU_ABBRV") + ticker = self._get_openapi_ticker(row) + name = row.get("ISU_ABBRV", row.get("ISU_NM")) if not ticker or pd.isna(ticker) or not name or pd.isna(name): continue @@ -114,8 +124,8 @@ class ETFCollector(BaseCollector): """Parse pykrx response DataFrame into ETF records.""" records = [] for _, row in df.iterrows(): - ticker = row.get("ISU_SRT_CD") - name = row.get("ISU_ABBRV") + ticker = self._get_openapi_ticker(row) + name = row.get("ISU_ABBRV", row.get("ISU_NM")) if not ticker or pd.isna(ticker) or not name or pd.isna(name): continue diff --git a/backend/app/services/collectors/etf_price_collector.py b/backend/app/services/collectors/etf_price_collector.py index 73c1b99..8fdaa7b 100644 --- a/backend/app/services/collectors/etf_price_collector.py +++ b/backend/app/services/collectors/etf_price_collector.py @@ -55,6 +55,16 @@ class ETFPriceCollector(BaseCollector): except (ValueError, TypeError): return None + def _get_openapi_ticker(self, row) -> str: + """Extract 6-digit ticker from KRX Open API rows.""" + ticker = row.get("ISU_SRT_CD", row.get("ISU_CD", "")) + if pd.isna(ticker): + return "" + if isinstance(ticker, float): + return str(int(ticker)).zfill(6) + ticker = str(ticker).strip() + return ticker.zfill(6) if ticker.isdigit() else ticker + def _collect_openapi(self) -> int: """Collect ETF prices via KRX Open API (date-based bulk fetch).""" client = get_krx_client() @@ -79,7 +89,7 @@ class ETFPriceCollector(BaseCollector): records = [] for _, row in df.iterrows(): - ticker = str(row.get("ISU_SRT_CD", "")) + ticker = self._get_openapi_ticker(row) if not ticker or ticker not in ticker_set: continue diff --git a/backend/app/services/collectors/price_collector.py b/backend/app/services/collectors/price_collector.py index 6ea3a7b..1eaa4fe 100644 --- a/backend/app/services/collectors/price_collector.py +++ b/backend/app/services/collectors/price_collector.py @@ -55,6 +55,16 @@ class PriceCollector(BaseCollector): except (ValueError, TypeError): return None + def _get_openapi_ticker(self, row) -> str: + """Extract 6-digit ticker from KRX Open API rows.""" + ticker = row.get("ISU_SRT_CD", row.get("ISU_CD", "")) + if pd.isna(ticker): + return "" + if isinstance(ticker, float): + return str(int(ticker)).zfill(6) + ticker = str(ticker).strip() + return ticker.zfill(6) if ticker.isdigit() else ticker + def _collect_openapi(self) -> int: """Collect stock prices via KRX Open API (date-based bulk fetch).""" client = get_krx_client() @@ -79,7 +89,7 @@ class PriceCollector(BaseCollector): records = [] for _, row in df.iterrows(): - ticker = str(row.get("ISU_SRT_CD", "")) + ticker = self._get_openapi_ticker(row) if not ticker or ticker not in ticker_market: continue diff --git a/backend/app/services/collectors/stock_collector.py b/backend/app/services/collectors/stock_collector.py index 0bc56fa..72dde9a 100644 --- a/backend/app/services/collectors/stock_collector.py +++ b/backend/app/services/collectors/stock_collector.py @@ -53,6 +53,16 @@ class StockCollector(BaseCollector): except (ValueError, TypeError): return None + def _get_openapi_ticker(self, row) -> str: + """Extract 6-digit ticker from KRX Open API rows.""" + ticker = row.get("ISU_SRT_CD", row.get("ISU_CD", "")) + if pd.isna(ticker): + return "" + if isinstance(ticker, float): + return str(int(ticker)).zfill(6) + ticker = str(ticker).strip() + return ticker.zfill(6) if ticker.isdigit() else ticker + def _collect_openapi(self) -> int: """Collect stock data via KRX Open API.""" client = get_krx_client() @@ -73,12 +83,12 @@ class StockCollector(BaseCollector): trade_map = {} if trade_df is not None and not trade_df.empty: for _, row in trade_df.iterrows(): - ticker = str(row.get("ISU_SRT_CD", "")) + ticker = self._get_openapi_ticker(row) if ticker: trade_map[ticker] = row for _, row in base_df.iterrows(): - ticker = str(row.get("ISU_SRT_CD", "")) + ticker = self._get_openapi_ticker(row) name = str(row.get("ISU_ABBRV", "")) if not ticker or not name: continue