Files
etf/framework_v2/FLASK_API_FETCHER_GUIDE.md
aszerW 99d3584d05 docs(framework_v2): 更新 FlaskAPIFetcher 文档(API 日历集成)
## 使用指南更新(FLASK_API_FETCHER_GUIDE.md)
- get_trading_calendar() 方法签名更新
  - 新增 start, end 参数(支持动态日期范围)
  - 返回类型: pd.DatetimeIndex(准确日历)
- 使用示例更新(API 调用方式)
- 注意事项更新:交易日历准确性  已解决

## 架构设计更新(FLASK_API_FETCHER_ARCHITECTURE.md)
- get_trading_calendar() 实现更新
  - 从临时 pandas BDay → API 准确日历
  - API 端点: GET /api/v1/trading-calendar
- 未来优化: 移除交易日历 TODO(已完成)

## 文档一致性
- 所有示例代码使用 API 日历
- 架构描述与实际实现一致
- 版本历史更新(2024-04-16)
2026-05-24 12:38:55 +08:00

366 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# FlaskAPIFetcher 使用指南
## 概述
`FlaskAPIFetcher` 是 framework_v2 的数据获取器实现,通过 HTTP API 获取线上数据指数、ETF
**核心优势**
- ✅ 无需本地 SSH 隧道配置
- ✅ 支持远程调用(生产环境)
- ✅ 自动重试 + 超时处理
- ✅ Pydantic Schema 验证响应
- ✅ ETF 数据自动附加净值和溢价率
---
## 快速开始
### 1. 基础使用
```python
from framework_v2.shared.data import FlaskAPIFetcher
# 创建数据获取器
fetcher = FlaskAPIFetcher(
base_url="https://k3s.tokenpluse.xyz", # 或从环境变量读取
timeout=120,
retries=3
)
# 获取指数数据
data = fetcher.fetch_indices(
codes=["000300.SH", "000905.SH"],
start="2024-01-01",
end="2024-12-31"
)
# 访问数据
df_300 = data["000300.SH"]
print(df_300.head())
```
### 2. 获取 ETF 数据
```python
# 获取 ETF 数据(自动附加净值和溢价率)
data = fetcher.fetch_etf(
codes=["510300.SH", "159919.SZ"],
start="2024-01-01",
end="2024-12-31"
)
# 访问价格数据
df = data["510300.SH"]
print(df.head())
# 访问净值数据
nav = df.attrs.get('nav')
if nav is not None:
print(f"净值数据: {len(nav)} 条")
# 访问溢价率
premium = df.attrs.get('latest_premium')
if premium is not None:
print(f"最新溢价率: {premium:.2f}%")
```
---
## 完整示例:结合 CrossMarketAligner
### 场景:获取跨市场数据并对齐到 A 股日历
```python
from framework_v2.shared.data import FlaskAPIFetcher, CrossMarketAligner
# 1. 创建数据获取器
fetcher = FlaskAPIFetcher()
# 2. 获取 A 股交易日历(通过 API
a_share_calendar = fetcher.get_trading_calendar(
market='A',
start='2024-01-01',
end='2024-12-31'
)
# 3. 创建对齐器
aligner = CrossMarketAligner(target_calendar=a_share_calendar)
# 4. 获取跨市场指数数据
us_indices = fetcher.fetch_indices(
codes=["^GSPC", "^IXIC"], # 美股
start="2024-01-01",
end="2024-12-31"
)
cn_indices = fetcher.fetch_indices(
codes=["000300.SH", "000905.SH"], # A股
start="2024-01-01",
end="2024-12-31"
)
# 5. 对齐收益率到 A 股日历
returns_aligned = aligner.align_multi_asset(
close_dict={
"SP500": us_indices["^GSPC"]["close"],
"NASDAQ": us_indices["^IXIC"]["close"],
"CSI300": cn_indices["000300.SH"]["close"],
"CSI500": cn_indices["000905.SH"]["close"],
}
)
# 6. 验证对齐结果
print(returns_aligned.head())
print(f"\nNaN 数量: {returns_aligned.isna().sum().sum()}") # 应该为 0
```
---
## API 参考
### FlaskAPIFetcher
#### 初始化
```python
FlaskAPIFetcher(
base_url: str = None, # API 地址(默认从环境变量读取)
timeout: int = 120, # 请求超时时间(秒)
retries: int = 3 # 重试次数
)
```
#### 核心方法
| 方法 | 说明 | 返回类型 |
|------|------|----------|
| `fetch_indices(codes, start, end)` | 获取指数 OHLCV 数据 | `Dict[str, DataFrame]` |
| `fetch_etf(codes, start, end)` | 获取 ETF 数据(价格+净值) | `Dict[str, DataFrame]` |
| `get_trading_calendar(market, start, end)` | 获取交易日历API | `pd.DatetimeIndex` |
| `get_benchmark(code, start, end)` | 获取基准数据 | `pd.Series` |
| `get_health()` | 检查 API 健康状态 | `Dict` |
#### fetch_indices 参数
```python
fetcher.fetch_indices(
codes=["000300.SH", "000905.SH"], # 指数代码列表
start="2024-01-01", # 开始日期
end="2024-12-31" # 结束日期
)
```
**返回 DataFrame 结构**
```
code open high low close volume
date
2024-01-02 000300.SH 3388.30 3395.40 3372.50 3390.20 12345678
2024-01-03 000300.SH 3390.20 3405.60 3385.10 3398.50 13456789
```
#### fetch_etf 参数
```python
fetcher.fetch_etf(
codes=["510300.SH", "159919.SZ"], # ETF 代码列表
start="2024-01-01", # 开始日期
end="2024-12-31" # 结束日期
)
```
**返回 DataFrame 结构**
```
code open high low close volume
date
2024-01-02 510300.SH 3.520 3.545 3.510 3.540 45678901
```
**附加信息df.attrs**
- `nav`: 净值数据 DataFrame
- `premium_series`: 溢价率序列dict
- `latest_premium`: 最新溢价率float
- `premium_stats`: 溢价率统计dict
---
## 与 DataFetcher 抽象基类的关系
```
framework_v2/core/data.py # 抽象基类
└── DataFetcher (ABC)
├── fetch_indices() [抽象]
├── fetch_etf() [抽象]
├── get_trading_calendar() [抽象]
└── get_benchmark() [可选]
framework_v2/shared/data/flask_api_fetcher.py # 具体实现
└── FlaskAPIFetcher(DataFetcher)
├── fetch_indices() ✅ 实现(调用 FlaskAPIDataSource
├── fetch_etf() ✅ 实现(调用 FlaskAPIDataSource
├── get_trading_calendar() ✅ 实现API 准确日历)
└── get_benchmark() ✅ 实现
```
### 继承关系验证
```python
from framework_v2.core.data import DataFetcher
from framework_v2.shared.data import FlaskAPIFetcher
# 验证继承
assert issubclass(FlaskAPIFetcher, DataFetcher)
# 验证抽象方法已实现
fetcher = FlaskAPIFetcher()
assert hasattr(fetcher, 'fetch_indices')
assert hasattr(fetcher, 'fetch_etf')
assert hasattr(fetcher, 'get_trading_calendar')
```
---
## 环境变量配置
### FLASK_API_URL
```bash
# .env 文件
FLASK_API_URL=https://k3s.tokenpluse.xyz
```
**优先级**
1. 构造函数参数 `base_url`
2. 环境变量 `FLASK_API_URL`
3. 默认值 `https://k3s.tokenpluse.xyz`
---
## 错误处理
### 自动重试
```python
fetcher = FlaskAPIFetcher(retries=3)
# 失败时自动重试:
# - 网络超时
# - HTTP 5xx 错误
# - JSON 解析失败
```
### 手动错误处理
```python
data = fetcher.fetch_indices(["000300.SH"], "2024-01-01", "2024-12-31")
if "000300.SH" not in data:
print("✗ 数据获取失败")
# 处理错误...
else:
print(f"✓ 获取 {len(data['000300.SH'])} 条数据")
```
---
## 性能优化
### 批量获取 vs 单个获取
```python
# ✅ 推荐:批量获取(内部自动重试 + 进度显示)
data = fetcher.fetch_indices(
codes=["000300.SH", "000905.SH", "000852.SH"],
start="2024-01-01",
end="2024-12-31"
)
# ❌ 不推荐:循环单个获取(无进度显示)
for code in codes:
df = fetcher._source.fetch(code, start, end)
```
### 超时设置
```python
# 网络较慢时增加超时
fetcher = FlaskAPIFetcher(timeout=180) # 3 分钟
```
---
## 测试
运行测试验证功能:
```bash
cd /Users/aszer/Documents/vscode/etf
python framework_v2/tests/test_flask_api_fetcher.py
```
**预期输出**
```
✓ 测试通过 - 健康检查
✓ 测试通过 - 指数数据
✓ 测试通过 - ETF 数据
✓ 测试通过 - 交易日历
✓ 测试通过 - 基准数据
总计: 5/5 通过
```
---
## 相关文档
- **[框架总览](../README.md)** - framework_v2 架构说明
- **[数据架构方案](../DATA_ARCHITECTURE.md)** - 数据流设计
- **[跨市场对齐方案](../ALIGNMENT_GUIDE.md)** - CrossMarketAligner 使用
- **[Aligner + Schema 整合](../ALIGNMENT_SCHEMA_INTEGRATION.md)** - 验证架构
---
## 注意事项
### 1. 交易日历准确性
**已解决**:通过 API 获取准确交易日历,包含所有节假日。
**使用方式**
```python
# 获取 A 股 2024 年交易日历(准确)
calendar = fetcher.get_trading_calendar('A', '2024-01-01', '2024-12-31')
print(f"A 股交易日: {len(calendar)} 天") # 242 天
```
### 2. ETF 净值数据量
ETF 净值数据可能远多于价格数据(历史净值 vs 交易价格):
```python
df = data["510300.SH"]
print(f"价格: {len(df)} 条") # ~60 条2024 Q1
print(f"净值: {len(df.attrs['nav'])} 条") # ~3695 条(全历史)
```
### 3. 资产类型检测
FlaskAPIDataSource 支持自动检测资产类型,也可手动指定:
```python
# 自动检测
df = fetcher._source.fetch("510300.SH", start, end)
# 手动覆盖
df = fetcher._source.fetch("510300.SH", start, end, asset_type='china_etf')
```
---
## 版本历史
- **2024-04-16**: 初始版本
- 继承 DataFetcher 抽象基类
- 实现指数、ETF 数据获取
- 集成 FlaskAPIDataSource
- 5/5 测试通过