""" KRX Open API client wrapper. Uses pykrx-openapi library to access KRX official REST API. Activated when KRX_OPENAPI_KEY environment variable is set. """ import os import logging from datetime import datetime import pandas as pd from pykrx_openapi import KRXOpenAPI logger = logging.getLogger(__name__) class KRXClient: """Thin wrapper around pykrx-openapi with project defaults.""" def __init__(self, api_key: str | None = None): key = api_key or os.getenv("KRX_OPENAPI_KEY") if not key: raise ValueError("KRX_OPENAPI_KEY is required for KRXClient") self.client = KRXOpenAPI(api_key=key) def _to_date_str(self, date_input: str) -> str: """Ensure date string is in YYYYMMDD format.""" return date_input.replace("-", "") def _records_to_df(self, result: dict) -> pd.DataFrame: """Convert API response dict to DataFrame.""" records = result.get("OutBlock_1", []) if not records: return pd.DataFrame() return pd.DataFrame(records) def get_etf_daily(self, bas_dd: str) -> pd.DataFrame: """Fetch all ETF daily trade data for a given date.""" bas_dd = self._to_date_str(bas_dd) result = self.client.get_etf_daily_trade(bas_dd=bas_dd) return self._records_to_df(result) def get_stock_daily(self, bas_dd: str, market: str = "KOSPI") -> pd.DataFrame: """Fetch stock daily trade data for a given date and market.""" bas_dd = self._to_date_str(bas_dd) if market == "KOSDAQ": result = self.client.get_kosdaq_stock_daily_trade(bas_dd=bas_dd) else: result = self.client.get_stock_daily_trade(bas_dd=bas_dd) return self._records_to_df(result) def get_stock_base_info(self, bas_dd: str, market: str = "KOSPI") -> pd.DataFrame: """Fetch stock base info for a given date and market.""" bas_dd = self._to_date_str(bas_dd) if market == "KOSDAQ": result = self.client.get_kosdaq_stock_base_info(bas_dd=bas_dd) else: result = self.client.get_stock_base_info(bas_dd=bas_dd) return self._records_to_df(result) def get_krx_client() -> KRXClient | None: """Return KRXClient if KRX_OPENAPI_KEY is set, else None.""" key = os.getenv("KRX_OPENAPI_KEY") if key: return KRXClient(api_key=key) return None