|
|
feb7c78e68
|
refactor: 统一ETF获取接口为单个DataFrame返回
重构说明:
- TushareSource.fetch_etf(): 新增 adj 参数,统一接口
- 返回单个 DataFrame
- df.attrs['nav']: 净值 DataFrame
- df.attrs['premium']: 溢价率 Series
- 移除冗余方法:
- fetch_etf_with_nav() → 合并到 fetch_etf()
- fetch_etf_adj() → 重命名为 _fetch_etf_hfq()(内部方法)
- UniversalDataFetcher: 适配新接口
- fetch_etf_with_nav(): 从 df.attrs 提取元数据(兼容旧接口)
- fetch_etf_adj(): 调用 fetch_etf(adj='hfq')
- Flask: 更新注释说明
架构优势:
- 单一接口:一个方法搞定所有 ETF 数据获取
- 数据一致:所有数据在一个 DataFrame 对象中
- 缓存友好:只需缓存一个 DataFrame
- 扩展性强:新增数据直接添加到 attrs
|
2026-05-23 22:36:23 +08:00 |
|
|
|
2867ae8d21
|
refactor: 将ETF净值和溢价率逻辑下移到TushareSource层
重构说明:
- TushareSource: 新增 fetch_etf_with_nav() 和 _calculate_premium_series()
- UniversalDataFetcher: 简化 fetch_etf_with_nav() 为透传调用
- Flask: 更新注释说明数据层已处理
架构优势:
- 职责分离:TushareSource 封装完整数据获取逻辑
- 可复用性:任何调用 TushareSource 的地方都有净值
- 维护性:业务逻辑集中在数据源层
- 符合单一职责原则
|
2026-05-23 22:28:21 +08:00 |
|
|
|
3697c9d38b
|
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 原始价格数据获取恢复正常
- 类型判断逻辑更准确
- 数据源接口签名统一
|
2026-05-23 21:46:01 +08:00 |
|
|
|
b7f7a756b6
|
refactor: SSH配置完全封装到UniversalDataFetcher
变更内容:
1. UniversalDataFetcher 新增方法:
- get_ssh_config_from_env(): 从环境变量读取 SSH 配置
- from_env(): 工厂方法,自动读取环境变量创建实例
- get_ssh_status(): 返回 SSH 状态信息字典
2. flask_server.py 简化:
- 移除 get_ssh_config() 函数(18行)
- 移除 ssh_config 全局变量
- get_fetcher() 使用 from_env()
- / 和 /health 路由使用 get_ssh_status()
架构改进:
- SSH 配置逻辑完全封装在 UniversalDataFetcher
- flask_server.py 只依赖 fetcher 接口
- 减少 24 行重复代码
|
2026-05-23 21:20:43 +08:00 |
|
|
|
67d67b1eea
|
refactor(universal_fetcher): SSH隧道按资产类型统一启动
定义 SSH_REQUIRED_TYPES 常量集合,在 fetch() 入口处统一启动隧道
改进:
- 新增 SSH_REQUIRED_TYPES 常量(港美股/加密货币需要 SSH)
- fetch() 入口统一启动隧道,移除各分支重复调用
- fetch_us_adj/fetch_hk_adj 简化为调用 fetch()
- fetch_batch 移除冗余的隧道启动
- 移除废弃的 _fetch_xxx 内部方法(减少 55 行)
SSH 调用次数:10次 → 3次(仅保留必要场景)
|
2026-05-23 18:53:26 +08:00 |
|
|
|
c319fd42be
|
refactor(universal_fetcher): fetch添加adj参数,fetch_with_adj简化
UniversalDataFetcher.fetch() 新增 adj 参数,直接传递给底层
- fetch(adj='raw/qfq/hfq'): 统一入口,参数校验和路由
- fetch_with_adj(): 简化为 return self.fetch(adj=adj)
- 删除重复的 VALID_ADJ_BY_TYPE 定义和路由逻辑(~70行)
- VALID_ADJ_BY_TYPE 移到类级别作为静态配置
|
2026-05-23 18:32:10 +08:00 |
|
|
|
1148d3166c
|
refactor(datasource): 分层接口设计,移除HybridDataSource
架构改动:
- 移除 HybridDataSource(功能被 UniversalDataFetcher 覆盖)
- 新增分层接口设计:基础层 + 扩展层
基础层(统一接口):
- fetch(): 统一 OHLCV 接口,自动识别资产类型
- fetch_batch(): 批量获取
扩展层(资产类型特有):
- fetch_etf_adj(): A股 ETF 后复权价格
- fetch_us_adj(): 美股复权价格
- fetch_etf_with_nav(): ETF 价格 + 净值 + 溢价率
其他修改:
- YFinanceSource: 新增 fetch_adj() 方法
- strategy.py: 改用 UniversalDataFetcher 替代 HybridDataSource
- __init__.py: 移除 HybridDataSource 导出
|
2026-05-23 12:46:48 +08:00 |
|
|
|
bed92027fc
|
fix(premium): 溢价率计算改用动态匹配原则
修复 _calculate_premium_series 方法,改为动态匹配净值日期:
原问题:
- 统一使用T-1净值规则导致A股/港股/商品ETF溢价率计算错误
- 如创业板ETF用T-1净值而非当天净值,溢价率从0.76%变成0.19%
修复方案:
- 优先使用当天净值(A股/港股/商品/债券/日本QDII)
- 当天净值不存在时使用T-1净值(美股QDII/欧洲QDII/原油QDII)
验证结果:
- 11只ETF全部验证通过,与集思录数据完全一致
|
2026-05-16 10:27:07 +08:00 |
|
|
|
13be83965b
|
fix(datasource): QDII溢价率计算修复净值日期滞后一天对齐
问题: 溢价率计算使用同一天收盘价+净值,但QDII净值T+1披露
修复: 将净值索引后移一天,T日收盘价配T-1日净值
参考: 集思录做法(价格日期配前一日净值)
验证数据(513100.SH):
- 2026-05-15: 收盘价2.100, 净值(5/14)2.0200, 溢价率3.96% ✓
|
2026-05-16 08:57:20 +08:00 |
|
|
|
a49002f622
|
fix(datasource): 溢价率计算改用同一天市价与净值
问题:之前用 ffill 将前一天净值填充到当天,导致溢价率偏差过大
例如:5月13日市价 4.048 vs 5月12日净值 3.946 → 溢价率 2.58%
修复:
- 不使用 ffill,只计算有净值日期的溢价率
- 使用 price_df 和 nav_df 的交集日期计算
- 溢价率 = (当天市价 - 当天净值) / 当天净值
- 5月12日市价 3.94 vs 净值 3.946 → 溢价率 ~0%
注意:净值 T+1 公布,最新一天溢价率可能无法计算
|
2026-05-14 01:31:39 +08:00 |
|
|
|
6a5d4dacd4
|
fix(datasource): 修复溢价率计算重复日期导致的 reindex 失败
问题:长时间范围 ETF 数据获取时,出现 'cannot reindex on an axis with duplicate labels' 错误
修复:
- 在 _calculate_premium_series 中先检测并去除重复日期
- price_df 和 nav_df 的索引都使用 duplicated(keep='last') 去重
- 确保 reindex 操作正常执行
|
2026-05-14 01:15:03 +08:00 |
|
|
|
416f708d53
|
feat(datasource): 实现加密货币数据获取功能
- 新增 ccxt_source.py: CCXT + OKX 加密货币数据源
- 新增 socks2http.py: SOCKS5 转 HTTP 代理转换器
- 修改 universal_fetcher.py: 添加 _fetch_crypto 方法,支持 timeframe 参数
- 修改 flask_server.py: API 支持 timeframe 参数,加密货币不缓存
支持的 timeframe: 1d, 1h, 4h, 15m, 1m
测试验证: BTC 数据获取成功
|
2026-05-13 23:30:32 +08:00 |
|
|
|
a712bc0f03
|
fix(datasource): 支持US_STOCK和HK_STOCK类型数据获取
- universal_fetcher.py: 添加 _fetch_us_stock 和 _fetch_hk_stock 方法
- flask_server.py: SSH_HOST 修正为正确的IP地址 8.218.167.69
- 测试 META 获取成功,info 字段在最外层返回179个属性
|
2026-05-13 00:38:01 +08:00 |
|
|
|
16affb2368
|
feat: fetch_etf_with_nav 返回历史溢价率序列
修改内容:
1. universal_fetcher.py
- fetch_etf_with_nav 返回三值:(price_df, nav_df, premium_series)
- 新增 _calculate_premium_series 方法:计算每一天的溢价率
- 溢价率 = (ETF收盘价 - ETF净值) / ETF净值
- 净值用ffill对齐价格日期(处理T+1延迟)
2. flask_server.py
- /api/v1/etf/nav 端点返回历史溢价率序列
- 添加 premium_series 字段:[{date, premium}]
- 添加 latest_premium: 最新溢价率
- 添加 premium_stats: 统计数据(mean/std/min/max/median)
测试结果(513100.SH 纳指100 ETF):
- 价格数据: 8条
- 净值数据: 8条
- 溢价率序列: 8条
- 最新溢价率: 0.1500%
- 溢价率均值: 1.1433%
- 溢价率范围: 0.15% ~ 1.69%
|
2026-05-12 21:39:07 +08:00 |
|
|
|
4e3aac5e0e
|
feat: Flask统一数据服务迁移(分层架构)
架构设计:
- 对外统一接口 fetch():自动识别资产类型并路由
- 对内分层实现:各资产类型独立方法,职责单一
新增文件:
- datasource/universal_fetcher.py: 统一数据获取器
- _fetch_china_index: A股指数(Tushare)
- _fetch_china_etf: A股ETF(含净值)
- _fetch_us_index: 美股指数(YFinance+SSH)
- _fetch_hk_index: 港股指数(YFinance+SSH)
- _fetch_futures: 期货(Tushare/YFinance)
- fetch_etf_with_nav: ETF价格+净值(计算溢价率)
- datasource/asset_type_detector.py: 资产类型检测器
- AssetType枚举:9种资产类型
- detect(): 自动识别资产类型
- group_by_type(): 批量分组
- datasource/flask_server.py: Flask API服务
- LRU + TTL 双缓存机制
- 8个API端点:ohlcv、etf/nav、batch、cache等
更新:
- datasource/__init__.py: 导出新模块
验证:
- 模块导入成功
- 资产类型检测正确
- A股数据获取正常(沪深300: 5条)
|
2026-05-12 21:33:19 +08:00 |
|