""" Fetcher Factory - Backend Version Currently supports CN market with Tushare """ import os class FetcherFactory: """ 数据获取工厂类 (Backend版本) 当前支持的数据源: - Tushare: CN (中国A股) - iFinD: HK, JP, US, VN - Bloomberg: CN, HK, JP, US, VN """ @staticmethod def get_fetcher(market: str, data_source: str = None, **kwargs): """ 获取对应市场和数据源的 Fetcher Args: market: 市场代码 (CN, HK, JP, US, VN) data_source: 数据源名称 (iFinD, Tushare, Bloomberg) **kwargs: 额外参数(如 API tokens) Returns: Fetcher 实例 """ market = market.upper() # 如果未指定数据源,使用默认值 if not data_source: data_source = FetcherFactory._get_default_source(market) elif data_source == 'iFinD': return FetcherFactory._get_ifind_fetcher(market, **kwargs) elif data_source == 'Bloomberg': return FetcherFactory._get_bloomberg_fetcher(market, **kwargs) else: # 其他数据源暂未迁移 raise NotImplementedError( f"Data source '{data_source}' not supported in backend." ) @staticmethod def _get_default_source(market: str) -> str: """获取市场的默认数据源""" defaults = { 'CN': 'Tushare', 'HK': 'iFinD', 'JP': 'iFinD', 'US': 'iFinD', 'VN': 'iFinD' } return defaults.get(market, 'iFinD') @staticmethod def _get_tushare_fetcher(market: str, **kwargs): """获取 Tushare Fetcher""" if market != 'CN': raise ValueError("Tushare only supports CN market") # 获取 Tushare token tushare_token = kwargs.get('tushare_token') or os.getenv('TUSHARE_TOKEN') if not tushare_token: raise ValueError("Tushare token is required for CN market") from app.fetchers.cn_fetcher import CnFetcher return CnFetcher(tushare_token) @staticmethod def _get_ifind_fetcher(market: str, **kwargs): """Get iFinD Fetcher""" ifind_token = kwargs.get('ifind_token') or os.getenv('IFIND_REFRESH_TOKEN') if not ifind_token: # Try legacy env var name if needed, but IFIND_REFRESH_TOKEN is standard ifind_token = os.getenv('IFIND_REFRESH_TOKEN') if not ifind_token: raise ValueError("iFinD refresh token is required (IFIND_REFRESH_TOKEN)") if market == 'HK': from app.fetchers.hk_fetcher import HkFetcher return HkFetcher(ifind_token) elif market == 'JP': from app.fetchers.jp_fetcher import JpFetcher return JpFetcher(ifind_token) elif market == 'VN': from app.fetchers.vn_fetcher import VnFetcher return VnFetcher(ifind_token) elif market == 'US': from app.fetchers.us_fetcher import UsFetcher return UsFetcher(ifind_token) else: raise NotImplementedError(f"iFinD fetcher for market {market} not yet migrated to backend.") @staticmethod def _get_bloomberg_fetcher(market: str, **kwargs): """Get Bloomberg Fetcher""" # Bloomberg client typically uses internal auth (password based) or default keys. # We can pass kwargs but default init handles env vars. from app.fetchers.bloomberg_fetcher import BloombergFetcher return BloombergFetcher(market=market)