## 测试报告(END_TO_END_TEST_REPORT.md, 345 行) - 5 个阶段详细测试结果 - 关键验证总结(跨市场对齐、数据完整性、策略表现) - 性能指标(总耗时 ~7 秒) - 数据流图(完整流程可视化) - 发现的问题(因子值异常、日历精度) ## 集成记录(TRADING_CALENDAR_API_INTEGRATION.md, 247 行) - 变更前后对比(pandas BDay → API) - API 端点文档(请求/响应格式) - 使用示例(基础使用 + 数据对齐) - 测试验证结果(484 天准确日历) - 影响分析(正面影响 + 无破坏性变更) ## 文档特色 - 大量代码示例 - 表格总结 - 测试结果截图 - 版本历史记录
247 lines
5.4 KiB
Markdown
247 lines
5.4 KiB
Markdown
# FlaskAPIFetcher 交易日历 API 集成
|
||
|
||
## 更新日期
|
||
|
||
2024-04-16
|
||
|
||
---
|
||
|
||
## 变更概述
|
||
|
||
将 `FlaskAPIFetcher.get_trading_calendar()` 从临时的 pandas BDay 实现升级为通过 API 获取准确交易日历。
|
||
|
||
---
|
||
|
||
## 变更详情
|
||
|
||
### 变更前(临时实现)
|
||
|
||
```python
|
||
def get_trading_calendar(self, market: str = 'A') -> pd.Index:
|
||
"""使用 pandas BDay 生成近似日历"""
|
||
|
||
if market == 'A':
|
||
calendar = pd.bdate_range(start='2020-01-01', end='2025-12-31')
|
||
# 手动移除节假日(不完整)
|
||
holidays = ['2024-02-10', '2024-02-11', ...]
|
||
calendar = calendar[~calendar.isin(pd.to_datetime(holidays))]
|
||
return calendar
|
||
|
||
elif market == 'US':
|
||
return pd.bdate_range(start='2020-01-01', end='2025-12-31')
|
||
```
|
||
|
||
**问题**:
|
||
- ❌ 使用 `bdate_range` 生成近似日历
|
||
- ❌ 节假日列表不完整
|
||
- ❌ 不支持动态日期范围
|
||
- ❌ 可能包含非交易日
|
||
|
||
---
|
||
|
||
### 变更后(API 实现)
|
||
|
||
```python
|
||
def get_trading_calendar(
|
||
self,
|
||
market: str = 'A',
|
||
start: str = None,
|
||
end: str = None
|
||
) -> pd.Index:
|
||
"""通过 API 获取准确交易日历"""
|
||
|
||
# 默认日期范围
|
||
if start is None:
|
||
start = '2020-01-01'
|
||
if end is None:
|
||
end = '2025-12-31'
|
||
|
||
# 调用 API 获取准确日历
|
||
calendar = self._source.get_trading_calendar(
|
||
market=market,
|
||
start_date=start,
|
||
end_date=end
|
||
)
|
||
|
||
if calendar is None:
|
||
raise ValueError(
|
||
f"交易日历获取失败: market={market}, {start} ~ {end}"
|
||
)
|
||
|
||
return calendar
|
||
```
|
||
|
||
**优势**:
|
||
- ✅ 通过 API 获取准确日历
|
||
- ✅ 包含所有节假日处理
|
||
- ✅ 支持动态日期范围
|
||
- ✅ API 失败时抛出异常(不静默降级)
|
||
|
||
---
|
||
|
||
## API 端点
|
||
|
||
### 请求
|
||
|
||
```
|
||
GET /api/v1/trading-calendar
|
||
|
||
参数:
|
||
- market: 市场代码 ('A', 'US', 'HK')
|
||
- start: 开始日期 (YYYY-MM-DD)
|
||
- end: 结束日期 (YYYY-MM-DD)
|
||
```
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"market": "A",
|
||
"exchange": "SSE",
|
||
"trading_dates": ["2024-01-02", "2024-01-03", ...],
|
||
"count": 242
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 使用示例
|
||
|
||
### 基础使用
|
||
|
||
```python
|
||
from framework_v2.shared.data import FlaskAPIFetcher
|
||
|
||
fetcher = FlaskAPIFetcher()
|
||
|
||
# 获取 A 股 2024 年交易日历
|
||
calendar = fetcher.get_trading_calendar(
|
||
market='A',
|
||
start='2024-01-01',
|
||
end='2024-12-31'
|
||
)
|
||
|
||
print(f"A 股交易日: {len(calendar)} 天") # 242 天
|
||
```
|
||
|
||
### 在数据对齐中使用
|
||
|
||
```python
|
||
from framework_v2.shared.data import FlaskAPIFetcher, CrossMarketAligner
|
||
|
||
fetcher = FlaskAPIFetcher()
|
||
|
||
# 1. 获取数据
|
||
data = fetcher.fetch_indices(["^IXIC"], "2024-01-01", "2024-12-31")
|
||
|
||
# 2. 获取准确交易日历
|
||
calendar = fetcher.get_trading_calendar(
|
||
market='A',
|
||
start='2024-01-01',
|
||
end='2024-12-31'
|
||
)
|
||
|
||
# 3. 创建对齐器
|
||
aligner = CrossMarketAligner(target_calendar=calendar)
|
||
|
||
# 4. 对齐收益率
|
||
returns = aligner.align_returns(data["^IXIC"]["close"], code="^IXIC")
|
||
```
|
||
|
||
---
|
||
|
||
## 测试验证
|
||
|
||
### 端到端测试结果
|
||
|
||
```
|
||
阶段 3: 数据对齐(到 A 股日历)
|
||
======================================================================
|
||
|
||
[3.1] 获取 A 股交易日历(通过 API)...
|
||
✓ A (SSE): 484 个交易日 (2023-01-03 ~ 2024-12-31)
|
||
A 股交易日: 484 天
|
||
日期范围: 2023-01-03 00:00:00 ~ 2024-12-31 00:00:00
|
||
|
||
[3.2] 对齐因子到 A 股日历...
|
||
|
||
对齐 ^IXIC 因子...
|
||
对齐后天数: 484
|
||
填充天数: 18 (3.7%)
|
||
NaN 数量: 15
|
||
|
||
对齐 399006.SZ 因子...
|
||
对齐后天数: 484
|
||
填充天数: 0 (0.0%)
|
||
NaN 数量: 19
|
||
|
||
[3.3] 对齐收益率到 A 股日历...
|
||
|
||
对齐 ^IXIC 收益率...
|
||
对齐后天数: 484
|
||
收益率范围: -3.6391% ~ 4.4159%
|
||
NaN 数量: 0
|
||
零收益率天数: 18 (休市日) ✅
|
||
|
||
对齐 399006.SZ 收益率...
|
||
对齐后天数: 484
|
||
收益率范围: -10.5941% ~ 17.2494%
|
||
NaN 数量: 0
|
||
零收益率天数: 0 (休市日) ✅
|
||
|
||
✓ 阶段 3 通过
|
||
```
|
||
|
||
### 关键验证
|
||
|
||
| 验证项 | 预期 | 实际 | 状态 |
|
||
|--------|------|------|------|
|
||
| API 调用成功 | 是 | 是 | ✅ |
|
||
| 返回天数准确 | 484 天 | 484 天 | ✅ |
|
||
| 纳指休市日 | 18 天 | 18 天 | ✅ |
|
||
| 创业板休市日 | 0 天 | 0 天 | ✅ |
|
||
| 收益率 NaN | 0 | 0 | ✅ |
|
||
|
||
---
|
||
|
||
## 影响分析
|
||
|
||
### 正面影响
|
||
|
||
1. **准确性提升**: 从近似日历 → 准确日历
|
||
2. **维护成本降低**: 无需手动维护节假日列表
|
||
3. **多市场支持**: A 股、美股、港股统一 API
|
||
4. **动态日期范围**: 支持任意日期范围查询
|
||
|
||
### 无破坏性变更
|
||
|
||
- ✅ 方法签名向后兼容(新增可选参数 `start`, `end`)
|
||
- ✅ 返回类型兼容(`pd.DatetimeIndex` 是 `pd.Index` 的子类)
|
||
- ✅ 现有代码无需修改
|
||
|
||
---
|
||
|
||
## 相关文件
|
||
|
||
| 文件 | 变更 |
|
||
|------|------|
|
||
| `framework_v2/shared/data/flask_api_fetcher.py` | 更新 `get_trading_calendar()` 实现 |
|
||
| `framework_v2/tests/test_end_to_end.py` | 更新测试使用 API 日历 |
|
||
| `framework_v2/FLASK_API_FETCHER_GUIDE.md` | 更新文档 |
|
||
| `framework_v2/FLASK_API_FETCHER_ARCHITECTURE.md` | 更新架构说明 |
|
||
| `datasource/flask_api_source.py` | 底层 API 调用(已存在) |
|
||
|
||
---
|
||
|
||
## 版本历史
|
||
|
||
- **2024-04-16**: API 交易日历集成
|
||
- 替换临时 pandas BDay 实现
|
||
- 调用 `/api/v1/trading-calendar` 端点
|
||
- 支持动态日期范围
|
||
- 端到端测试通过
|
||
|
||
- **2024-04-15**: 初始版本
|
||
- 临时实现(pandas BDay + 手动节假日)
|
||
- 固定日期范围(2020-2025)
|