Compare commits

...

4 Commits

Author SHA1 Message Date
48ff15d92a docs: 新增轮动策略核心逻辑V2文档
V2相对于V1的核心升级:
- 候选池: 22只(以A股行业为主) → 11只(全球7大类精选)
- 因子类型: slope_r2(等权回归) → weighted_momentum(加权回归,近期权重2.0)
- 选股模式: 纯Top5 → 跨大类分散化(每大类Top1→全局Top3,等权33%)
- 崩盘过滤: 无 → 有(连续3天跌>5%得分清零)
- 商品信号源: 指数价格 → 期货价格(AU.SHF/CL.NYM/CU.SHF)
- 加密货币: 保留 → 移除(全部使用A股场内ETF交易)

V2实证数据(2019-02~2026-04):
  累计收益1473%, CAGR 46.42%, Sharpe 2.22, MaxDD -17.33%, Calmar 2.68
  diversified=true全面优于false(2022年差异+17.63%)

文档包含完整配置清单、因子计算公式、分散化选股机制、
调仓控制逻辑、溢价率控制、跨市场数据对齐方案、V1 vs V2对比表
2026-04-30 13:49:42 +08:00
5cf5bfc7d6 chore: 清理根目录已迁移到docs/的旧md文件 2026-04-30 13:41:13 +08:00
d0a9d66a11 feat(config): 添加CU.SHF有色金属期货信号源,移除冗余上证红利
讨论背景:
- 159980.SZ(有色ETF)是商品型基金,跟踪上期所有色金属期货价格指数
- 应使用期货价格(CU.SHF沪铜)作为信号源,与黄金(AU.SHF)/原油(CL.NYM)保持一致
- 上证红利(000015.SH)与中证红利低波(H30269.CSI)高度相关,同属A股大类
  在diversified模式下只能选1个,保留两个无实际意义

配置变更:
- rotation.yaml: 新增CU.SHF→159980.SZ映射(market=COMMODITY)
- rotation.yaml: 移除000015.SH上证红利(与红利低波冗余)
- hybrid_source.py: FUTURES_CODE_MAP新增CU.SHF铜期货
- ab_test_iterations.py: 同步更新有色market为COMMODITY

实证结果 - CU.SHF加入前后对比(11只池,2019-2026):
  无CU(11只): CAGR=47.37%, Sharpe=2.25, MaxDD=-17.86%, Calmar=2.65
  含CU(12只): CAGR=46.16%, Sharpe=2.21, MaxDD=-17.86%, Calmar=2.58
  影响: CAGR-1.2%, 商品大类内部竞争加剧(黄金/原油/有色三选一)
  2020/2022铜价暴涨时有色贡献额外收益,整体影响很小

实证结果 - 移除上证红利后(11只,2019-2026):
  含上证红利: CAGR=46.16%, Sharpe=2.21, MaxDD=-17.86%, Calmar=2.58
  移除后:     CAGR=46.42%, Sharpe=2.22, MaxDD=-17.33%, Calmar=2.68
  所有指标均改善,消除冗余标的提升选择效率

实证结果 - diversified=true vs false(11只,select_num=3):
  true(跨类分散):  CAGR=46.45%, Sharpe=2.22, MaxDD=-17.33%, Calmar=2.68
  false(纯Top3):   CAGR=44.19%, Sharpe=2.13, MaxDD=-18.12%, Calmar=2.44
  关键差异在2022年(+17.63%): false模式选3只商品同时回调
  结论: diversified=true全面优于false,保持当前配置

最终候选池(11只,7大类):
  A股: 创业板(399006.SZ), 红利低波(H30269.CSI)
  美股: 纳指100(NDX) | 日本: 日经225(N225) | 欧洲: 德国DAX(GDAXI)
  港股: 恒生指数(HSI), 恒生科技(HSTECH.HK)
  商品: 黄金(AU.SHF), 原油(CL.NYM), 有色金属(CU.SHF)
  固收: 30年国债(931862.CSI)
2026-04-30 13:37:46 +08:00
4df3ac4e31 chore(docs): reorganize documentation files into docs/ folder
Moved markdown documentation from root to docs/ directory to improve project structure.
2026-04-30 01:06:25 +08:00
8 changed files with 263 additions and 5 deletions

View File

@@ -14,10 +14,6 @@ code_list:
name: "中证红利低波"
etf: "512890.SH"
market: "A"
"000015.SH":
name: "上证红利"
etf: "510880.SH"
market: "A"
# 全球市场
"NDX":
@@ -50,6 +46,10 @@ code_list:
name: "原油"
etf: "160723.SZ"
market: "COMMODITY"
"CU.SHF":
name: "有色金属"
etf: "159980.SZ"
market: "COMMODITY"
"931862.CSI":
name: "30年国债"
etf: "511090.SH"

View File

@@ -135,6 +135,7 @@ class HybridDataSource:
# 期货代码映射 (代码 -> Tushare格式)
FUTURES_CODE_MAP = {
"AU.SHF": "AU.SHF", # 上海期货交易所黄金主力合约
"CU.SHF": "CU.SHF", # 上海期货交易所铜主力合约
}
def __init__(self, ssh_config: Optional[dict] = None, use_cache: bool = True):

View File

@@ -0,0 +1,257 @@
# ETF轮动策略核心逻辑 V2
## 📊 策略概览
基于**加权动量因子**的跨市场ETF轮动策略通过量化评分自动选择表现最优的ETF组合进行投资。V2版本核心升级**跨大类强制分散化选股**,确保持仓在不同资产类别间均衡配置,避免集中在单一市场。
---
## 🎯 候选池配置
### 覆盖市场7大类11只标的
| 大类 (market) | 标的 | 信号源代码 | 交易ETF | 数据来源 |
|---|---|---|---|---|
| **A股 (A)** | 创业板指 | 399006.SZ | 159915.SZ | Tushare |
| **A股 (A)** | 中证红利低波 | H30269.CSI | 512890.SH | Tushare |
| **美股 (US)** | 纳指100 | NDX | 513100.SH | YFinance |
| **日本 (JP)** | 日经225 | N225 | 513520.SH | YFinance |
| **欧洲 (EU)** | 德国DAX | GDAXI | 513030.SH | YFinance |
| **港股 (HK)** | 恒生指数 | HSI | 159920.SZ | YFinance |
| **港股 (HK)** | 恒生科技 | HSTECH.HK | 513130.SH | YFinance |
| **商品 (COMMODITY)** | 黄金 | AU.SHF | 518880.SH | Tushare/期货 |
| **商品 (COMMODITY)** | 原油 | CL.NYM | 160723.SZ | YFinance |
| **商品 (COMMODITY)** | 有色金属(铜) | CU.SHF | 159980.SZ | Tushare/期货 |
| **固收 (BOND)** | 30年国债 | 931862.CSI | 511090.SH | Tushare |
### 双轨数据架构
- **信号源(指数/期货)**:用于计算动量因子得分,决定选哪些标的
- **交易标的ETF**用于计算实际收益所有ETF均在A股场内交易
- 商品类标的使用期货价格作为信号源AU.SHF→黄金ETFCL.NYM→原油ETFCU.SHF→有色ETF保证信号来源的纯粹性
---
## 🧮 得分计算逻辑
### 因子类型:加权线性回归动量 (weighted_momentum)
#### 核心公式
```
得分 = 年化收益率 ×
```
#### 计算步骤
1. **取对数收益**`y = ln(价格序列)`过去25个交易日
2. **构造权重**`weights = linspace(1, 2, 25)`近期权重2.0远期权重1.0,线性递增)
3. **加权线性回归**`slope, intercept = polyfit(x, y, 1, w=weights)`
4. **年化收益率**`annualized_returns = exp(slope × 250) - 1`
5. **加权R²**
```
y_pred = slope × x + intercept
ss_res = Σ(weights × (y - y_pred)²)
ss_tot = Σ(weights × (y - weighted_mean(y))²)
R² = 1 - ss_res / ss_tot
```
6. **最终得分**`score = annualized_returns ×`
#### 得分含义
- **正值**:上升趋势,值越大代表趋势越强且越稳定
- **负值**:下降趋势(会被过滤,不参与选股)
- **接近0**:无明显趋势或趋势不稳定
### 崩盘过滤机制
在得分计算后对最近3个交易日进行崩盘检测
- **条件1**最近3天中任一天跌幅 > 5%
- **条件2**连续3天下跌且累计跌幅 > 5%
满足任一条件 → **得分强制清零**,该标的当日不参与选股。
### V1 vs V2 因子对比
| 维度 | V1 (slope_r2) | V2 (weighted_momentum) |
|---|---|---|
| 输入数据 | 归一化价格 | 对数价格 |
| 回归方式 | 等权线性回归 | 加权线性回归(近期权重更高) |
| 得分公式 | `slope ×× 10000` | `年化收益率 ×` |
| 权重分配 | 所有交易日等权 | 近期权重2.0远期权重1.0 |
| 崩盘过滤 | 无 | 有连续3天跌>5%清零) |
---
## 📦 选股逻辑:跨大类强制分散化 (diversified=true)
### 核心机制:两步筛选
**第一步:类内竞争** —— 每个 `market` 大类只保留得分最高的1只标的大类冠军
```
A股: 创业板指 vs 红利低波 → 选1只冠军
港股: 恒生指数 vs 恒生科技 → 选1只冠军
商品: 黄金 vs 原油 vs 有色金属 → 选1只冠军
美股/日本/欧洲/固收: 各1只自动成为冠军
```
**第二步:跨类排序** —— 从最多7个大类冠军中按得分从高到低选 Top 3
```
最终持仓 = Top 3 大类冠军等权33%
```
### 具体示例
某日各标的得分:
| 大类 | 标的 | 得分 | 类内排名 |
|---|---|---|---|
| A | 创业板指 | 2.5 | ✓ 冠军 |
| A | 红利低波 | 1.8 | ✗ 淘汰 |
| US | 纳指100 | 4.7 | ✓ 冠军 |
| JP | 日经225 | 3.5 | ✓ 冠军 |
| HK | 恒生科技 | 1.2 | ✓ 冠军 |
| HK | 恒生指数 | 0.8 | ✗ 淘汰 |
| COMMODITY | 黄金 | 3.1 | ✓ 冠军 |
| COMMODITY | 原油 | -0.5 | ✗ 负分过滤 |
→ 大类冠军纳指100(4.7) > 日经225(3.5) > 黄金(3.1) > 创业板指(2.5) > 恒生科技(1.2)
→ 选 Top 3**纳指100 + 日经225 + 黄金**各33%
### 为什么使用分散化?
实证对比11只标的2019-2026
| 指标 | diversified=true | diversified=false | 差异 |
|---|---|---|---|
| CAGR | 46.45% | 44.19% | +2.26% |
| Sharpe | 2.22 | 2.13 | +0.09 |
| 最大回撤 | -17.33% | -18.12% | 改善0.79% |
| Calmar | 2.68 | 2.44 | +0.24 |
关键差异在2022年+17.63%`false` 模式集中持有3只商品商品回调时同步下跌`true` 模式强制分散到不同大类,有效对冲单一资产类别风险。
---
## ⏱️ 调仓控制
### 调仓触发条件
每日检查,同时满足以下条件才触发调仓:
1. **最低持仓期**:距上次调仓 ≥ 1个交易日`rebalance_days = 1`
2. **得分改善检查**
- 多品种模式:`新组合总得分 / 旧组合总得分 - 1 ≥ 0%``rebalance_threshold = 0.0`
- 即:只要新组合得分更高就调仓
3. **目标信号有效**:目标组合不为空(所有标的得分为负时不调仓,继续持有)
### T+1执行机制
- T日收盘后计算因子得分生成信号`信号_raw`
- 信号向后移位1天`shift(1)`作为T+1日的执行信号
- **运行时间**T+1日上午9:00北京时间因美股/期货数据凌晨才可用
### 交易成本
- **成本率**0.1%(双边,含佣金+滑点)
- **扣除方式**:按换手率比例扣除
- `换手率 = 新增品种数 / 旧持仓品种数`
- `成本 = 换手率 × 0.1%`
- 例如3只持仓换1只 → 换手率1/3 → 成本0.033%
---
## 🛡️ 溢价率控制
### 机制说明
跨境ETF港股/美股在A股交易时可能出现溢价ETF价格 > 净值),溢价过高时买入风险大。
### 控制配置
| 市场类型 | 启用 | 阈值 | 模式 |
|---|---|---|---|
| A股 | 否 | — | — |
| 港股 | 是 | 10% | filter完全排除 |
| 美股 | 是 | 10% | filter完全排除 |
| 商品 | 否 | — | — |
| 固收 | 否 | — | — |
### 溢价率计算
```
溢价率 = ETF收盘价 / ETF单位净值 - 1
```
- 净值数据通过 Tushare `fund_nav` 接口获取
- `filter` 模式:溢价超阈值的标的直接从当日候选池排除
- `penalize` 模式可选对高溢价标的得分乘以惩罚系数0.5
---
## 📡 跨市场数据对齐
### 基准日历
以**A股交易日历**为基准,所有标的数据对齐到该日历。
### 数据对齐策略
1. **A股指数/期货**Tushare直连获取天然对齐A股交易日
2. **非A股标的**(港美股等):
- 各标的按自身交易日历计算因子得分
- 计算完成后,通过 `ffill`前向填充对齐到A股交易日
-周一A股开盘但美股假期 → 使用上周五美股数据
3. **数据质量检查**:对齐后缺失率 > 50% 的标的自动剔除
### 数据源路由
| 数据类型 | 数据源 | 代理方式 |
|---|---|---|
| A股指数 (.SH/.SZ/.CSI) | Tushare | 直连(清除代理) |
| 期货 (AU.SHF/CU.SHF) | Tushare fut_daily | 直连 |
| 港股/美股/欧日 | YFinance | SSH隧道(SOCKS5) |
| 原油 (CL.NYM) | YFinance (CL=F) | SSH隧道 |
| ETF价格 | Tushare fund_daily | 直连 |
| ETF净值 | Tushare fund_nav | 直连 |
| 基准指数 | Tushare | 直连 |
---
## 📈 回测绩效2019-02 ~ 2026-04
| 维度 | V2配置 |
|---|---|
| 累计收益 | 1473% |
| CAGR | 46.42% |
| Sharpe | 2.22 |
| 最大回撤 | -17.33% |
| Calmar | 2.68 |
| 日胜率 | 56.48% |
| 基准(沪深300) | CAGR 5.23% |
| 最大回撤区间 | 2020-02-13 ~ 2020-03-23 |
---
## 📋 策略特点总结
| 维度 | V1配置 | V2配置 |
|---|---|---|
| **候选池** | 22只以A股行业为主 | 11只全球7大类精选 |
| **市场覆盖** | A股17 + 港1 + 美1 + 商品1 + 加密2 | A股2 + 美1 + 日1 + 欧1 + 港2 + 商品3 + 固收1 |
| **因子类型** | slope_r2 | weighted_momentum加权近期权重更高 |
| **崩盘过滤** | 无 | 有3天跌>5%得分清零) |
| **持仓数量** | 5只等权20% | 3只等权33% |
| **选股模式** | 纯Top N | 跨大类分散化每类Top1→全局Top3 |
| **调仓频率** | 每日评估 | 每日评估 |
| **交易成本** | 0.1% | 0.1%(按换手率比例扣除) |
| **溢价控制** | 港3%/美2% | 港美统一10%filter模式 |
| **数据源** | Tushare + YFinance + CCXT | Tushare + YFinance去掉加密货币 |
| **基准指数** | 沪深300 | 沪深300 |
---
## 💡 V2核心优势
1. **全球分散**7大类资产覆盖全球主要市场降低单一市场/经济体风险
2. **强制分散化**diversified模式确保持仓跨大类配置避免同类资产集中
3. **期货信号+ETF交易**商品类使用期货价格作为信号源ETF作为交易载体两者分离
4. **加权动量**:近期数据权重更高,对趋势变化更敏感
5. **崩盘保护**:短期暴跌自动清零得分,避免追接下跌中的飞刀
6. **全A股可交易**所有标的均有对应的A股场内ETF无需境外账户
---
*文档版本V2.0*
*更新时间2026-04-30*
*对应配置config/strategies/rotation.yaml*

View File

@@ -28,7 +28,7 @@ ORIGINAL_POOL = {
"399986.SZ": {"name": "中证银行", "market": "A", "etf": "516310.SH"},
"399997.SZ": {"name": "中证白酒", "market": "A", "etf": "512690.SH"},
"399989.SZ": {"name": "中证医疗", "market": "A", "etf": "512170.SH"},
"399395.SZ": {"name": "国证有色", "market": "A", "etf": "159880.SZ"},
"399395.SZ": {"name": "国证有色", "market": "COMMODITY", "etf": "159880.SZ"},
"399998.SZ": {"name": "中证煤炭", "market": "A", "etf": "515220.SH"},
"399967.SZ": {"name": "中证军工", "market": "A", "etf": "512660.SH"},
"HSTECH.HK": {"name": "恒生科技", "market": "HK", "etf": "513180.SH"},