fix: 修复数据获取架构逻辑Bug
修复内容: 1. Bug #1: TushareSource.fetch(adj='raw') ETF 无法获取 - 在 adj='raw' 分支优先判断 ETF - ETF 代码现在正确路由到 fetch_etf() 2. Bug #2: is_china_index 判断范围过宽 - 添加 ETF 排除逻辑 - ETF 不再被误判为指数 3. 接口一致性:CCXTSource 添加 adj 参数 - fetch(code, start, end, adj='raw', timeframe) - 加密货币仅支持 adj='raw' - UniversalDataFetcher._fetch_crypto() 同步更新 影响: - ETF 原始价格数据获取恢复正常 - 类型判断逻辑更准确 - 数据源接口签名统一
This commit is contained in:
@@ -146,6 +146,7 @@ class CCXTSource:
|
||||
code: str,
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
adj: str = 'raw',
|
||||
timeframe: str = '1d'
|
||||
) -> Optional[pd.DataFrame]:
|
||||
"""
|
||||
@@ -155,11 +156,16 @@ class CCXTSource:
|
||||
code: 加密货币代码(BTC, ETH 等)
|
||||
start_date: 开始日期 YYYY-MM-DD
|
||||
end_date: 结束日期 YYYY-MM-DD
|
||||
adj: 复权类型(加密货币仅支持 'raw')
|
||||
timeframe: K 线周期(1d, 1h, 4h, 15m, 1m)
|
||||
|
||||
Returns:
|
||||
DataFrame with columns: date, open, high, low, close, volume
|
||||
"""
|
||||
# 校验 adj 参数(加密货币仅支持 raw)
|
||||
if adj != 'raw':
|
||||
raise ValueError(f"加密货币不支持复权,adj='{adj}' 无效,仅支持 'raw'")
|
||||
|
||||
if not CCXT_AVAILABLE:
|
||||
print(f"⚠️ ccxt 未安装,无法获取 {code}")
|
||||
return None
|
||||
|
||||
@@ -188,7 +188,10 @@ class TushareSource:
|
||||
return None
|
||||
|
||||
def is_china_index(self, code: str) -> bool:
|
||||
"""判断是否为A股指数"""
|
||||
"""判断是否为A股指数(排除 ETF)"""
|
||||
# 先排除 ETF
|
||||
if self._is_etf_code(code):
|
||||
return False
|
||||
return code.endswith(".SH") or code.endswith(".SZ") or code.endswith(".SS") or code.endswith(".CSI")
|
||||
|
||||
def is_futures(self, code: str) -> bool:
|
||||
@@ -237,7 +240,10 @@ class TushareSource:
|
||||
|
||||
# 原始数据
|
||||
if adj == 'raw':
|
||||
if self.is_china_index(code):
|
||||
# 优先判断 ETF(修复:ETF 原始数据获取)
|
||||
if self._is_etf_code(code):
|
||||
return self.fetch_etf(code, start_date, end_date)
|
||||
elif self.is_china_index(code):
|
||||
return self.fetch_index(code, start_date, end_date)
|
||||
elif self.is_futures(code):
|
||||
return self.fetch_futures(code, start_date, end_date)
|
||||
|
||||
@@ -255,7 +255,7 @@ class UniversalDataFetcher:
|
||||
elif asset_type == AssetType.FUTURES:
|
||||
return self._fetch_futures(code, start_date, end_date, adj)
|
||||
elif asset_type == AssetType.CRYPTO:
|
||||
return self._fetch_crypto(code, start_date, end_date, timeframe)
|
||||
return self._fetch_crypto(code, start_date, end_date, adj, timeframe)
|
||||
else:
|
||||
print(f"⚠️ 未知资产类型: {code} -> {asset_type}")
|
||||
return None
|
||||
@@ -440,6 +440,7 @@ class UniversalDataFetcher:
|
||||
code: str,
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
adj: str = 'raw',
|
||||
timeframe: str = '1d'
|
||||
) -> Optional[pd.DataFrame]:
|
||||
"""
|
||||
@@ -450,11 +451,13 @@ class UniversalDataFetcher:
|
||||
- 需要通过 socks2http 将 SOCKS5 转 HTTP 代理
|
||||
- 必须指定 timeframe
|
||||
- 不缓存(每次实时下载)
|
||||
- 加密货币仅支持 adj='raw'(无复权)
|
||||
|
||||
Args:
|
||||
code: 加密货币代码(BTC, ETH)
|
||||
start_date: 开始日期
|
||||
end_date: 结束日期
|
||||
adj: 复权类型(仅支持 'raw')
|
||||
timeframe: K线周期(1d, 1h, 4h, 15m, 1m)
|
||||
"""
|
||||
# 延迟初始化加密货币数据源
|
||||
@@ -463,7 +466,7 @@ class UniversalDataFetcher:
|
||||
socks_port = self.ssh_config.get('local_port', 1080)
|
||||
self._crypto = get_crypto_source(socks_port=socks_port)
|
||||
|
||||
return self._crypto.fetch(code, start_date, end_date, timeframe)
|
||||
return self._crypto.fetch(code, start_date, end_date, adj, timeframe)
|
||||
|
||||
# ============================================================
|
||||
# 批量获取
|
||||
|
||||
Reference in New Issue
Block a user