Files
etf/archive/framework_v2/config/CONFIG_DESIGN.md
aszerW c905230a40 refactor(archive): move unused modules to archive/
Archive legacy framework and utility modules that are no longer
referenced by the active core (datasource/ and rotation/):

- framework/ -> archive/framework/
- framework_v2/ -> archive/framework_v2/
- strategies/ -> archive/strategies/
- config/ -> archive/config/
- visualization/ -> archive/visualization/
- scripts/ -> archive/scripts/
- tests/ -> archive/tests/
- run_rotation.py, run_us_rotation.py -> archive/single_files/
- compare_*.py, test_api_dates.py -> archive/single_files/
2026-06-03 23:41:46 +08:00

574 lines
12 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.

# V2 配置设计文档
## 概述
framework_v2 的配置系统基于 **Pydantic Schema 验证**,解决 V1 配置文件的 10 个问题。
---
## 核心设计原则
### 1. **类型安全**(解决 V1 问题 #2
```python
# ❌ V1: 无验证
n_days: 25 # 如果是 "25"(字符串)会静默失败
# ✅ V2: Pydantic 验证
class FactorConfig(BaseModel):
n_days: int = Field(default=25, ge=5, le=250)
```
**验证效果**
```python
# 错误:超出范围
factor: {n_days: 1000}
# → ValidationError: n_days 必须在 5-250 之间
# 错误:类型错误
factor: {n_days: "25"}
# → ValidationError: n_days 必须是整数
```
---
### 2. **敏感信息环境变量化**(解决 V1 问题 #1
```yaml
# ❌ V1: 硬编码
flask_api:
url: "https://k3s.tokenpluse.xyz"
ssh_tunnel:
host: "8.218.167.69"
key_path: "hk_ecs.pem"
# ✅ V2: 环境变量
data:
sources:
- type: "flask_api"
url: "${FLASK_API_URL}" # 从环境变量读取
- type: "tushare"
token: "${TUSHARE_TOKEN}" # 从环境变量读取
```
**环境变量替换**
```python
# 支持格式
${VAR_NAME} # 必需环境变量
${VAR_NAME:default_value} # 带默认值
# 示例
url: "${FLASK_API_URL}" # 必须设置
timeout: "${TIMEOUT:120}" # 默认 120
```
---
### 3. **资产池按类别分组**(解决 V1 问题 #3
```yaml
# ❌ V1: 混合在一起
code_list:
"399006.SZ":
name: "创业板指"
market: "A"
"GC=F":
name: "黄金"
market: "COMMODITY"
# ✅ V2: 按类别分组
asset_pools:
equity: # 股票资产
"399006.SZ":
name: "创业板指"
market: "CN_EQUITY"
"NDX":
name: "纳指100"
market: "US_EQUITY"
commodity: # 商品资产
"GC=F":
name: "黄金"
market: "COMMODITY"
fixed_income: # 固定收益
"931862.CSI":
name: "短债指数"
market: "FIXED_INCOME"
```
**优势**
- ✅ 清晰的资产分类
- ✅ 支持分散化策略(每类选 Top-N
- ✅ 易于扩展新资产类别
---
### 4. **精简注释 + 独立文档**(解决 V1 问题 #4
```yaml
# ❌ V1: 30 行注释
# 931862.CSI = 中证0-9个月国债指数短债指数
# 数据范围2007-12-31开始约19年数据
# 久期:极短(<1年波动极小熊市防御效果最佳
# ...(共 30 行)
"931862.CSI":
name: "短债指数"
etf: null
market: "BOND"
# ✅ V2: 精简注释 + description 字段
fixed_income:
"931862.CSI":
name: "短债指数"
etf: null
market: "FIXED_INCOME"
description: "中证0-9个月国债指数久期<1年防御配置"
```
**详细文档独立**
```
docs/
├── bond_analysis.md # 债券收益归因分析
├── asset_pool_design.md # 资产池设计说明
└── threshold_strategy.md # 阈值策略文档
```
---
### 5. **统一阈值配置**(解决 V1 问题 #6
```yaml
# ❌ V1: V2 + V3 共存,逻辑混乱
min_score: 0.0 # V2 固定阈值
bond_threshold: # V3 动态阈值
enabled: true
bond_code: "931862.CSI"
ratio: 1.0
fill_bond: true
# ✅ V2: 统一配置
rotation:
threshold:
mode: "dynamic" # 阈值模式: fixed / dynamic
fixed_value: 0.0 # mode=fixed 时使用
dynamic: # mode=dynamic 时使用
reference: "931862.CSI" # 参考标的
ratio: 1.0 # 倍数
fallback_enabled: true # 回退开关
fallback_value: 0.0 # 回退值
```
**模式切换**
```yaml
# 固定阈值模式
threshold:
mode: "fixed"
fixed_value: 0.0
# 动态阈值模式
threshold:
mode: "dynamic"
dynamic:
reference: "931862.CSI"
ratio: 1.0
```
---
### 6. **标准化市场类型**(解决 V1 问题 #8
```yaml
# ❌ V1: 随意定义
market: "A" # A股
market: "US" # 美股
market: "JP" # 日本
# ✅ V2: 标准枚举
market: "CN_EQUITY" # 中国股票
market: "US_EQUITY" # 美国股票
market: "JP_EQUITY" # 日本股票
market: "EU_EQUITY" # 欧洲股票
market: "HK_EQUITY" # 香港股票
market: "COMMODITY" # 商品
market: "FIXED_INCOME" # 固定收益
```
**Python 枚举**
```python
class MarketType(str, Enum):
CN_EQUITY = "CN_EQUITY"
US_EQUITY = "US_EQUITY"
JP_EQUITY = "JP_EQUITY"
EU_EQUITY = "EU_EQUITY"
HK_EQUITY = "HK_EQUITY"
COMMODITY = "COMMODITY"
FIXED_INCOME = "FIXED_INCOME"
```
---
### 7. **多数据源降级策略**(解决 V1 问题 #9
```yaml
# ❌ V1: 扁平化配置
flask_api:
enabled: true
url: "https://k3s.tokenpluse.xyz"
ssh_tunnel:
enabled: true
# ...
# ✅ V2: 优先级列表
data:
sources:
# 主数据源
- type: "flask_api"
enabled: true
url: "${FLASK_API_URL}"
timeout: 120
# 备用数据源
- type: "tushare"
enabled: true
token: "${TUSHARE_TOKEN}"
timeout: 60
# 降级数据源
- type: "yfinance"
enabled: false
timeout: 120
```
**降级逻辑**
```python
for source in config.data.sources:
if not source.enabled:
continue
try:
data = fetch_from_source(source)
return data
except Exception as e:
print(f"数据源 {source.type} 失败: {e}")
continue
raise ValueError("所有数据源均失败")
```
---
### 8. **配置版本控制**(解决 V1 问题 #10
```yaml
# ❌ V1: 无版本信息
# ETF轮动策略配置
# (无版本)
# ✅ V2: 元数据
metadata:
version: "1.0.0"
strategy: "rotation"
description: "ETF轮动策略 V2 - 基于 framework_v2 架构"
last_updated: "2024-04-16"
```
---
## Schema 层次结构
```
RotationStrategyConfig
├── metadata: MetadataConfig
│ ├── version: str
│ ├── strategy: str
│ ├── description: str
│ └── last_updated: str
├── asset_pools: AssetPool
│ ├── equity: Dict[str, AssetConfig]
│ ├── commodity: Dict[str, AssetConfig]
│ └── fixed_income: Dict[str, AssetConfig]
├── benchmark: BenchmarkConfig
│ ├── code: str
│ └── name: str
├── backtest: BacktestConfig
│ ├── start_date: str
│ └── end_date: Optional[str]
├── factor: FactorConfig
│ ├── type: FactorType
│ ├── n_days: int (5-250)
│ ├── auto_day: bool
│ ├── min_days: int
│ └── max_days: int
├── rotation: RotationConfig
│ ├── select_num: int (1-10)
│ ├── diversified: bool
│ └── threshold: ThresholdConfig
│ ├── mode: ThresholdMode
│ ├── fixed_value: float
│ └── dynamic: DynamicThresholdConfig
│ ├── reference: str
│ ├── ratio: float
│ ├── fallback_enabled: bool
│ └── fallback_value: float
├── rebalance: RebalanceConfig
│ ├── min_hold_days: int (1-30)
│ ├── score_threshold: float (0-0.5)
│ └── trade_cost: float (0-0.01)
├── premium_control: PremiumControlConfig
│ ├── enabled: bool
│ ├── default_threshold: float
│ ├── mode: PremiumMode
│ ├── penalty_factor: float
│ └── market_overrides: Dict[str, MarketPremiumOverride]
└── data: DataConfig
├── sources: List[DataSourceConfig]
├── use_cache: bool
└── cache_dir: str
```
---
## 使用示例
### 基础使用
```python
from framework_v2.config import load_config
# 加载配置文件
config = load_config('rotation_example.yaml')
# 访问配置
print(f"动量窗口: {config.factor.n_days}")
print(f"选股数量: {config.rotation.select_num}")
print(f"数据源: {len(config.data.sources)} 个")
```
### 验证错误处理
```python
from pydantic import ValidationError
try:
config = load_config('invalid_config.yaml')
except ValidationError as e:
print(f"配置验证失败: {e}")
# 输出详细错误信息
for error in e.errors():
print(f" - {error['loc']}: {error['msg']}")
```
### 环境变量
```bash
# 设置环境变量
export FLASK_API_URL="https://k3s.tokenpluse.xyz"
export TUSHARE_TOKEN="your_token_here"
# 加载配置(自动替换环境变量)
config = load_config('rotation_example.yaml')
```
---
## 文件结构
```
framework_v2/config/
├── __init__.py # 导出模块
├── schemas.py # Pydantic Schema 定义275 行)
├── loader.py # 配置加载器237 行)
├── rotation_example.yaml # 示例配置文件195 行)
└── CONFIG_DESIGN.md # 配置设计文档(本文件)
framework_v2/tests/
└── test_config.py # 配置测试286 行)
```
---
## 测试验证
### 测试结果
```
✓ 测试 1: 加载配置文件 - 通过
✓ 测试 2: 资产池配置 - 通过
✓ 测试 3: 阈值配置 - 通过
✓ 测试 4: 数据源配置 - 通过
✓ 测试 5: 验证错误处理 - 通过
✓ 测试 6: 环境变量替换 - 通过
总计: 6/6 通过
```
### 验证覆盖
| 验证项 | 测试内容 | 状态 |
|--------|----------|------|
| 配置加载 | YAML 解析 + 环境变量替换 | ✅ |
| 类型验证 | n_days 范围、必需字段 | ✅ |
| 资产池 | 股票/商品/债券分类 | ✅ |
| 阈值配置 | 固定/动态模式切换 | ✅ |
| 数据源 | 多源降级配置 | ✅ |
| 错误处理 | ValidationError 捕获 | ✅ |
---
## V1 vs V2 对比
| 特性 | V1 | V2 | 改进 |
|------|----|----|----|
| **类型安全** | ❌ 无验证 | ✅ Pydantic Schema | 早期失败 |
| **敏感信息** | ❌ 硬编码 | ✅ 环境变量 | 安全性 |
| **资产分类** | ❌ 混合 | ✅ 按类别分组 | 可维护性 |
| **注释** | ❌ 冗长30行 | ✅ 精简 + 独立文档 | 可读性 |
| **阈值逻辑** | ❌ V2/V3 共存 | ✅ 统一配置 | 逻辑清晰 |
| **市场类型** | ❌ 随意字符串 | ✅ 标准枚举 | 一致性 |
| **数据源** | ❌ 扁平化 | ✅ 优先级列表 | 可靠性 |
| **版本控制** | ❌ 无 | ✅ 元数据 | 可追溯 |
---
## 迁移指南
### 从 V1 迁移到 V2
#### 1. 更新配置文件结构
```yaml
# V1
code_list:
"399006.SZ":
name: "创业板指"
etf: "159915.SZ"
market: "A"
# V2
asset_pools:
equity:
"399006.SZ":
name: "创业板指"
etf: "159915.SZ"
market: "CN_EQUITY"
```
#### 2. 更新市场类型
```yaml
# V1 → V2 映射
"A" → "CN_EQUITY"
"US" → "US_EQUITY"
"HK" → "HK_EQUITY"
"COMMODITY" → "COMMODITY"
"BOND" → "FIXED_INCOME"
```
#### 3. 更新阈值配置
```yaml
# V1
min_score: 0.0
bond_threshold:
enabled: true
bond_code: "931862.CSI"
ratio: 1.0
# V2
rotation:
threshold:
mode: "dynamic"
dynamic:
reference: "931862.CSI"
ratio: 1.0
```
#### 4. 更新数据源配置
```yaml
# V1
flask_api:
enabled: true
url: "https://k3s.tokenpluse.xyz"
# V2
data:
sources:
- type: "flask_api"
enabled: true
url: "${FLASK_API_URL}"
```
---
## 最佳实践
### 1. 使用环境变量管理敏感信息
```bash
# .env 文件(不要提交到 Git
FLASK_API_URL=https://k3s.tokenpluse.xyz
TUSHARE_TOKEN=your_token_here
SSH_HOST=8.218.167.69
SSH_KEY_PATH=/path/to/hk_ecs.pem
```
### 2. 为不同环境创建不同配置
```
config/
├── rotation_dev.yaml # 开发环境
├── rotation_prod.yaml # 生产环境
└── rotation_test.yaml # 测试环境
```
### 3. 使用版本控制追踪配置变更
```yaml
metadata:
version: "1.0.0"
last_updated: "2024-04-16"
changelog:
- "2024-04-16: 初始版本"
```
### 4. 定期验证配置
```bash
# 运行配置测试
python framework_v2/tests/test_config.py
```
---
## 未来优化
1. [ ] 配置热重载(无需重启策略)
2. [ ] 配置 diff 工具(对比版本差异)
3. [ ] 配置 UI 编辑器(可视化配置)
4. [ ] 配置模板系统(快速创建新策略)
---
## 版本历史
- **2024-04-16**: 初始版本
- Pydantic Schema 验证
- 环境变量替换
- 资产池分类
- 统一阈值配置
- 多数据源降级
- 6/6 测试通过