# 统一数据获取接口 (UniversalDataFetcher) ## 概述 `UniversalDataFetcher` 是一个封装了 Tushare、YFinance、CCXT 等多个数据源的统一接口,能够自动识别资产类型并路由到对应的数据源获取K线数据。 ## 支持的资产类型 | 资产类型 | 代码格式示例 | 数据源 | 说明 | |---------|------------|--------|------| | A股指数 | `000300.SH`, `399006.SZ`, `H30269.CSI` | Tushare (index_daily) | 沪深交易所指数、中证指数 | | A股ETF | `510300.SH`, `159915.SZ` | Tushare (fund_daily) | 场内交易型开放式指数基金 | | A股股票 | `600000.SH`, `000001.SZ` | Tushare (daily) | 沪深A股 | | 港股指数 | `HSI`, `HSTECH.HK` | YFinance | 恒生指数、恒生科技等 | | 美股指数 | `NDX`, `SPX`, `DJI` | YFinance | 纳斯达克、标普500、道琼斯 | | 美股股票 | `AAPL`, `MSFT`, `GOOGL` | YFinance | 美股个股 | | 期货合约 | `AU.SHF`, `CU.SHF` | Tushare (fut_daily) | 上期所、大商所等期货 | | 加密货币 | `BTC`, `ETH` | CCXT/OKX | 比特币、以太坊等 | ## 快速开始 ### 1. 基础用法 ```python from core.datasource.universal_fetcher import fetch_kline # 获取A股指数 df = fetch_kline("000300.SH", "2024-01-01", "2024-03-31") print(df.tail()) ``` 输出: ``` open high low close volume code date 2024-03-25 3564.488 3574.77 3547.43 3559.70 2.8576e+08 000300.SH 2024-03-26 3561.748 3592.50 3561.75 3591.53 2.9412e+08 000300.SH 2024-03-27 3587.960 3595.71 3561.65 3564.16 3.0183e+08 000300.SH 2024-03-28 3562.771 3575.31 3546.99 3570.56 2.7411e+08 000300.SH 2024-03-29 3573.374 3586.97 3568.63 3586.97 2.5862e+08 000300.SH ``` ### 2. 检测资产类型 ```python from core.datasource.universal_fetcher import detect_asset_type codes = ["000300.SH", "510300.SH", "NDX", "AAPL", "BTC", "AU.SHF"] for code in codes: asset_type = detect_asset_type(code) print(f"{code:15s} -> {asset_type}") ``` 输出: ``` 000300.SH -> china_index 510300.SH -> china_etf NDX -> us_index AAPL -> us_stock BTC -> crypto AU.SHF -> futures ``` ### 3. 批量获取 ```python from core.datasource.universal_fetcher import UniversalDataFetcher codes = ["000300.SH", "NDX", "HSI", "AU.SHF"] fetcher = UniversalDataFetcher() with fetcher: results = fetcher.fetch_multiple(codes, "2024-01-01", "2024-03-31") for code, df in results.items(): if df is not None: print(f"✓ {code}: {len(df)} 条, 最新收盘价 {df['close'].iloc[-1]:.3f}") ``` ### 4. 配置SSH隧道(访问受限数据源) ```python ssh_config = { "enabled": True, "host": "your-server.com", "port": 22, "username": "your-username", "key_path": "/path/to/private/key.pem", "local_port": 1080, } fetcher = UniversalDataFetcher(ssh_config=ssh_config) with fetcher: df = fetcher.fetch("NDX", "2024-01-01", "2024-03-31") ``` ## API 参考 ### UniversalDataFetcher 类 #### 初始化 ```python UniversalDataFetcher(ssh_config: Optional[dict] = None, use_cache: bool = True) ``` 参数: - `ssh_config`: SSH隧道配置字典(可选) - `use_cache`: 是否使用缓存(可选,默认 True) #### fetch() - 获取单只标的 ```python fetcher.fetch( code: str, start_date: str, end_date: str, retry: int = 3 ) -> Optional[pd.DataFrame] ``` 参数: - `code`: 标的代码 - `start_date`: 开始日期,格式 'YYYY-MM-DD' - `end_date`: 结束日期,格式 'YYYY-MM-DD' - `retry`: 重试次数(默认 3) 返回: - DataFrame,包含列: `[open, high, low, close, volume, code]` - 索引为日期(DatetimeIndex) - 失败时返回 None #### fetch_multiple() - 批量获取 ```python fetcher.fetch_multiple( codes: List[str], start_date: str, end_date: str, retry: int = 3 ) -> Dict[str, Optional[pd.DataFrame]] ``` 返回: - 字典 `{code: DataFrame}` ### 便捷函数 #### fetch_kline() ```python from core.datasource.universal_fetcher import fetch_kline df = fetch_kline("000300.SH", "2024-01-01", "2024-03-31") ``` #### detect_asset_type() ```python from core.datasource.universal_fetcher import detect_asset_type asset_type = detect_asset_type("000300.SH") # 返回 'china_index' ``` ## 使用示例 ### 示例1: 跨市场组合分析 ```python from core.datasource.universal_fetcher import UniversalDataFetcher import pandas as pd portfolio = { "000300.SH": "沪深300", "NDX": "纳斯达克100", "HSI": "恒生指数", "N225": "日经225", } fetcher = UniversalDataFetcher() with fetcher: results = fetcher.fetch_multiple( list(portfolio.keys()), "2024-01-01", "2024-12-31" ) # 合并收盘价 close_prices = pd.DataFrame() for code, name in portfolio.items(): if results[code] is not None: close_prices[name] = results[code]['close'] # 计算年化收益率 returns = close_prices.pct_change().dropna() annual_returns = (returns.mean() * 252 * 100).round(2) print(annual_returns) ``` ### 示例2: 结合技术指标 ```python from core.datasource.universal_fetcher import fetch_kline df = fetch_kline("000300.SH", "2024-01-01", "2024-06-30") # 计算移动平均线 df['MA5'] = df['close'].rolling(5).mean() df['MA20'] = df['close'].rolling(20).mean() # 计算RSI delta = df['close'].diff() gain = delta.where(delta > 0, 0).rolling(14).mean() loss = (-delta.where(delta < 0, 0)).rolling(14).mean() df['RSI'] = 100 - (100 / (1 + gain/loss)) print(df[['close', 'MA5', 'MA20', 'RSI']].tail()) ``` ### 示例3: 与轮动策略集成 ```python from core.datasource.universal_fetcher import UniversalDataFetcher code_config = { "399006.SZ": {"name": "创业板指", "etf": "159915.SZ", "market": "A"}, "NDX": {"name": "纳指100", "etf": "513100.SH", "market": "US"}, } all_codes = list(code_config.keys()) etf_codes = [cfg['etf'] for cfg in code_config.values()] fetcher = UniversalDataFetcher() with fetcher: # 获取指数数据(用于因子计算) index_data = fetcher.fetch_multiple(all_codes, "2024-01-01", "2024-03-31") # 获取ETF数据(用于收益计算) etf_data = fetcher.fetch_multiple(etf_codes, "2024-01-01", "2024-03-31") ``` ## 数据源路由逻辑 ``` 输入代码 ↓ 资产类型检测器 (AssetTypeDetector) ↓ ┌─────────────────────────────────┐ │ 检测规则(按优先级): │ │ 1. 加密货币代码集合匹配 │ │ 2. 期货后缀匹配 (.SHF等) │ │ 3. 港股后缀匹配 (.HK) │ │ 4. A股后缀匹配 (.SH/.SZ等) │ │ 5. 美股指数映射表匹配 │ │ 6. 默认: 美股股票 │ └─────────────────────────────────┘ ↓ 数据源路由: ├─ china_index/etf/stock → Tushare ├─ hk/us_index/stock → YFinance ├─ futures → Tushare (fut_daily) └─ crypto → CCXT/OKX ``` ## A股代码分类规则 ``` 6位数字代码: ├─ 指数前缀: 000, 001, 002, 399, 930, 931, 932 │ └─ → china_index ├─ ETF前缀: 51, 52, 56, 58, 15, 16 │ └─ → china_etf └─ 其他 └─ → china_stock ``` ## 环境要求 ### 必需 - Python 3.8+ - pandas - yfinance ### 按数据源 - **Tushare**: 需要设置环境变量 `TUSHARE_TOKEN` - **YFinance**: 网络可达(中国地区可能需要SSH隧道) - **CCXT**: 需要安装 `ccxt` 库 ### 安装依赖 ```bash pip install pandas yfinance tushare ccxt ``` ### 配置 Tushare Token 在 `.env` 文件中添加: ```env TUSHARE_TOKEN=your_tushare_api_token ``` ## 测试 运行测试脚本: ```bash python tests/test_universal_fetcher.py ``` ## 示例代码 查看更多示例: ```bash python examples/universal_fetcher_examples.py ``` ## 与现有代码的关系 `UniversalDataFetcher` 是对现有 `HybridDataSource` 的封装和扩展: - **复用**: 内部使用 `HybridDataSource` 的底层数据获取逻辑 - **扩展**: 增加了对A股股票、自动资产类型检测、便捷函数等功能 - **简化**: 提供了更简单的API,无需手动判断数据源 ## 常见问题 ### Q: 为什么获取美股数据失败? A: YFinance 在中国大陆可能被限制,需要配置SSH隧道或使用代理。 ### Q: 如何获取ETF净值数据? A: 当前接口返回的是交易价格(收盘价)。如需净值数据,请直接使用 `HybridDataSource._fetch_etf_nav()` 方法。 ### Q: 支持分钟级数据吗? A: 当前仅支持日线数据。如需分钟级数据,需要扩展接口。 ### Q: 如何添加新的资产类型? A: 在 `AssetTypeDetector` 中添加检测规则,在 `UniversalDataFetcher` 中添加对应的获取方法即可。 ## 更新日志 ### v1.0.0 (2024-XX-XX) - 初始版本 - 支持8种资产类型 - 自动资产类型检测 - 批量获取功能 - SSH隧道支持 - 完善的测试和示例 ## 许可证 MIT License