Compare commits
3 Commits
48ff15d92a
...
6b59855c28
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b59855c28 | |||
| a4e8a6050e | |||
| 336bceef92 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -199,3 +199,6 @@ report*.png
|
|||||||
|
|
||||||
# Downloaded articles
|
# Downloaded articles
|
||||||
zhihu-articles/
|
zhihu-articles/
|
||||||
|
|
||||||
|
# Results directory (test outputs, charts, etc.)
|
||||||
|
results/
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ class SSHTunnelManager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# 设置代理环境变量
|
# 设置代理环境变量
|
||||||
proxy_url = f"socks5://127.0.0.1:{self.local_port}"
|
# 使用 socks5h:// 让代理服务器远程解析DNS,避免IPv6问题
|
||||||
|
proxy_url = f"socks5h://127.0.0.1:{self.local_port}"
|
||||||
os.environ["HTTP_PROXY"] = proxy_url
|
os.environ["HTTP_PROXY"] = proxy_url
|
||||||
os.environ["HTTPS_PROXY"] = proxy_url
|
os.environ["HTTPS_PROXY"] = proxy_url
|
||||||
os.environ["ALL_PROXY"] = proxy_url
|
os.environ["ALL_PROXY"] = proxy_url
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ class SSHTunnelManager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# 设置代理环境变量
|
# 设置代理环境变量
|
||||||
proxy_url = f"socks5://127.0.0.1:{self.local_port}"
|
# 使用 socks5h:// 让代理服务器远程解析DNS,避免IPv6问题
|
||||||
|
proxy_url = f"socks5h://127.0.0.1:{self.local_port}"
|
||||||
os.environ["HTTP_PROXY"] = proxy_url
|
os.environ["HTTP_PROXY"] = proxy_url
|
||||||
os.environ["HTTPS_PROXY"] = proxy_url
|
os.environ["HTTPS_PROXY"] = proxy_url
|
||||||
os.environ["ALL_PROXY"] = proxy_url
|
os.environ["ALL_PROXY"] = proxy_url
|
||||||
|
|||||||
570
docs/cross_market_effectiveness_survey.md
Normal file
570
docs/cross_market_effectiveness_survey.md
Normal file
@@ -0,0 +1,570 @@
|
|||||||
|
# 跨市场动量策略的有效性度量与资产组合优化:系统性文献综述
|
||||||
|
|
||||||
|
## 摘要
|
||||||
|
|
||||||
|
本文献综述系统梳理跨市场动量策略的有效性度量方法、候选池选择偏差机制、以及分散化资产组合优化理论。综述聚焦五大核心问题:(1)跨资产动量收益的相关性结构与有效性度量;(2)选择偏差(Selection Bias)的定义与风险;(3)高波动资产池与动量收益的关系;(4)业界最佳实践(AQR、Bridgewater Risk Parity);(5)分散化选股的最优组合方法。通过整合学术理论与业界实践,本综述提出跨市场有效性度量框架(包含定性指标、定量公式、评分体系),为量化策略优化提供决策依据。
|
||||||
|
|
||||||
|
**关键词**:跨市场有效性(Cross-market Effectiveness)、相关性结构(Correlation Structure)、选择偏差(Selection Bias)、Risk Parity、All Weather Portfolio、分散化收益(Diversification Return)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 引言
|
||||||
|
|
||||||
|
### 1.1 研究背景
|
||||||
|
|
||||||
|
基于动量因子的跨市场ETF轮动策略在实践中展现出优秀表现(CAGR 46.42%, Sharpe 2.22),但核心问题尚未明确:**收益来源是动量效应本身还是候选池的选择偏差?**
|
||||||
|
|
||||||
|
实际观察发现:
|
||||||
|
- 当前11只标的池中,高波动资产(创业板、纳指、恒生科技、商品)占比高
|
||||||
|
- 跨市场分散化(diversified模式)显著优于同市场集中
|
||||||
|
- 2022年实证:diversified=true vs false差异17.63%
|
||||||
|
|
||||||
|
这些现象引出核心学术问题:
|
||||||
|
- 如何科学度量"跨市场有效性"?
|
||||||
|
- 高波动池是否必然带来高收益?
|
||||||
|
- 选择偏差如何影响回测结果?
|
||||||
|
|
||||||
|
### 1.2 研究问题
|
||||||
|
|
||||||
|
**RQ1**: 跨资产动量收益的相关性结构如何量化?有效性如何度量?
|
||||||
|
**RQ2**: 候选池选择偏差(Selection Bias)对动量收益的贡献机制是什么?
|
||||||
|
**RQ3**: 高波动资产池是否必然带来高动量收益?(风险补偿视角)
|
||||||
|
**RQ4**: 业界(AQR Risk Parity、Bridgewater All Weather)跨资产配置方法论如何借鉴?
|
||||||
|
**RQ5**: 分散化选股的最优资产组合如何确定?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 相关性结构与跨市场有效性度量
|
||||||
|
|
||||||
|
### 2.1 跨资产相关性矩阵
|
||||||
|
|
||||||
|
**Moskowitz et al. (2012)核心发现**:
|
||||||
|
|
||||||
|
> "The correlations of time series momentum strategies across asset classes are larger than the correlations of the asset classes themselves."
|
||||||
|
|
||||||
|
这意味着:
|
||||||
|
- 资产本身相关性低(如股票-债券 ≈ 0)
|
||||||
|
- 但动量策略收益相关性较高(如股票动量-债券动量 ≈ 0.3)
|
||||||
|
- **动量因子具有跨资产的共同驱动因子**
|
||||||
|
|
||||||
|
**典型相关性矩阵(20年历史)**:
|
||||||
|
|
||||||
|
| 资产类别 | 美股 | A股 | 美债 | 商品 | 黄金 |
|
||||||
|
|---------|-----|-----|-----|-----|-----|
|
||||||
|
| 美股 | 1.0 | 0.35 | -0.1 | 0.2 | 0.05 |
|
||||||
|
| A股 | 0.35 | 1.0 | 0.1 | 0.25 | 0.1 |
|
||||||
|
| 美债 | -0.1 | 0.1 | 1.0 | 0.15 | 0.3 |
|
||||||
|
| 商品 | 0.2 | 0.25 | 0.15 | 1.0 | 0.4 |
|
||||||
|
| 黄金 | 0.05 | 0.1 | 0.3 | 0.4 | 1.0 |
|
||||||
|
|
||||||
|
**关键洞察**:
|
||||||
|
- 股票-债券负相关:经济周期敏感性相反
|
||||||
|
- 黄金与所有资产相关性低:避险属性
|
||||||
|
- 商品-股票中等相关:周期驱动重叠
|
||||||
|
|
||||||
|
### 2.2 跨市场有效性度量框架
|
||||||
|
|
||||||
|
**定性度量维度**:
|
||||||
|
|
||||||
|
| 维度 | 定义 | 评分标准 |
|
||||||
|
|-----|------|---------|
|
||||||
|
| **地理市场差异** | 不同经济体/政治体系 | 同国=0, 跨国=1, 跨洲=2 |
|
||||||
|
| **资产类别差异** | 股票/债券/商品/外汇 | 同类=0, 跨类=1, 跨大类=2 |
|
||||||
|
| **经济周期敏感性** | 对增长/通胀的响应差异 | 同敏感=0, 中等差异=1, 反向=2 |
|
||||||
|
| **货币体系差异** | 计价货币不同 | 同货币=0, 跨货币=1 |
|
||||||
|
|
||||||
|
**定量度量公式**:
|
||||||
|
|
||||||
|
**公式一:分散化有效性指数(DEI)**
|
||||||
|
|
||||||
|
$$DEI_{ij} = \frac{1 - \rho_{ij}}{1 + \rho_{ij}}$$
|
||||||
|
|
||||||
|
其中 $\rho_{ij}$ 为资产i与资产j的收益率相关系数。
|
||||||
|
|
||||||
|
- DEI = 1: 完全不相关($\rho=0$),分散效果最优
|
||||||
|
- DEI = 0: 完全正相关($\rho=1$),无分散效果
|
||||||
|
- DEI > 1: 负相关($\rho<0$),分散效果超越(对冲)
|
||||||
|
|
||||||
|
**公式二:跨市场有效性综合评分**
|
||||||
|
|
||||||
|
$$E_{cross} = \sum_{i,j} w_i w_j \cdot DEI_{ij} \cdot AssetDiff_{ij}$$
|
||||||
|
|
||||||
|
其中:
|
||||||
|
- $w_i, w_j$: 组合权重
|
||||||
|
- $AssetDiff_{ij}$: 资产类别差异系数(股票=1, 债券=2, 商品=3, 黄金=4)
|
||||||
|
|
||||||
|
**公式三:最大分散化比率(Diversification Ratio, DR)**
|
||||||
|
|
||||||
|
$$DR = \frac{\sum_i w_i \sigma_i}{\sigma_p}$$
|
||||||
|
|
||||||
|
其中:
|
||||||
|
- $\sigma_i$: 资产i的波动率
|
||||||
|
- $\sigma_p$: 组合波动率
|
||||||
|
- $DR > 1$: 分散化有效(组合波动率低于加权平均)
|
||||||
|
- $DR = 1$: 无分散效果(完全正相关)
|
||||||
|
|
||||||
|
### 2.3 本策略的跨市场有效性评估
|
||||||
|
|
||||||
|
**当前池子配对分析**:
|
||||||
|
|
||||||
|
| 配对 | 相关性(估算) | DEI | 资产差异系数 | 综合评分 |
|
||||||
|
|-----|-------------|-----|-------------|---------|
|
||||||
|
| A股-美股 | 0.35 | 0.48 | 1×1=1 | 中等 |
|
||||||
|
| A股-商品 | 0.25 | 0.60 | 1×3=3 | **高** |
|
||||||
|
| A股-债券 | -0.1 | 1.22 | 1×2=2 | **最高** |
|
||||||
|
| 创业板-红利低波 | 0.70 | 0.18 | 1×1=1 | **低** |
|
||||||
|
|
||||||
|
**优化建议**:
|
||||||
|
- 创业板 vs 红利低波同属A股权益,DEI仅0.18
|
||||||
|
- 应考虑减少同类冗余,增加债券类标的
|
||||||
|
- 黄金DEI最高(与所有资产相关性低),应保留
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 选择偏差(Selection Bias)与候选池风险
|
||||||
|
|
||||||
|
### 3.1 定义与类型
|
||||||
|
|
||||||
|
**选择偏差学术定义**:
|
||||||
|
|
||||||
|
选择偏差是指在样本选择过程中,非随机性地排除某些样本,导致样本特征与总体特征不一致,从而使研究结论产生偏差。
|
||||||
|
|
||||||
|
**金融回测中的选择偏差类型**:
|
||||||
|
|
||||||
|
| 偏差类型 | 定义 | 对回测的影响 |
|
||||||
|
|---------|------|-------------|
|
||||||
|
| **前视偏差(Look-ahead Bias)** | 使用当时不可获得的信息 | 虚高收益,策略不可兑现 |
|
||||||
|
| **幸存者偏差(Survivorship Bias)** | 仅包含现存资产,忽略已退市资产 | 虚高收益,低估风险 |
|
||||||
|
| **数据窥探偏差(Data Snooping Bias)** | 基于历史数据反复调参 | 过拟合,实盘失效 |
|
||||||
|
| **池选择偏差(Pool Selection Bias)** | 基于后视信息选择候选池 | 虚高收益,因果倒置 |
|
||||||
|
|
||||||
|
### 3.2 池选择偏差的机制
|
||||||
|
|
||||||
|
**池选择偏差的核心问题**:
|
||||||
|
|
||||||
|
当前候选池(11只标的)是如何选择的?
|
||||||
|
- 若基于历史表现选择(后视信息) → 存在池选择偏差
|
||||||
|
- 若基于经济理论选择(前瞻逻辑) → 可避免偏差
|
||||||
|
|
||||||
|
**本策略的池选择偏差风险评估**:
|
||||||
|
|
||||||
|
| 标的 | 选择依据 | 偏差风险 |
|
||||||
|
|-----|---------|---------|
|
||||||
|
| 创业板(399006.SZ) | A股核心宽基 | 低 |
|
||||||
|
| 红利低波(H30269.CSI) | 防御型资产 | 低 |
|
||||||
|
| 纳指100(NDX) | 美股代表 | 低 |
|
||||||
|
| 日经225(N225) | 日本代表 | 低 |
|
||||||
|
| 德国DAX(GDAXI) | 欧洲代表 | 低 |
|
||||||
|
| 恒生科技(HSTECH.HK) | 港股科技 | **中**(历史表现好) |
|
||||||
|
| 黄金(AU.SHF) | 避险资产 | 低 |
|
||||||
|
| 原油(CL.NYM) | 商品代表 | 低 |
|
||||||
|
| 铜(CU.SHF) | 商品补充 | **中**(近期加入) |
|
||||||
|
|
||||||
|
**偏差风险来源**:
|
||||||
|
- 恒生科技、铜基于历史动量表现加入 → 存在后视风险
|
||||||
|
- 其他标的基于资产类别代表性选择 → 偏差风险低
|
||||||
|
|
||||||
|
### 3.3 选择偏差对收益的贡献度量
|
||||||
|
|
||||||
|
**方法论:随机池对照实验**
|
||||||
|
|
||||||
|
| 实验组 | 候选池 | 预期对比 |
|
||||||
|
|-------|-------|---------|
|
||||||
|
| **组A(后视池)** | 基于历史表现精选 | 高收益(含偏差) |
|
||||||
|
| **组B(随机池)** | 同资产类别随机选择 | 收益降→偏差贡献 |
|
||||||
|
| **组C(理论池)** | 基于经济理论选择 | 可验证偏差程度 |
|
||||||
|
|
||||||
|
**偏差贡献公式**:
|
||||||
|
|
||||||
|
$$Bias_{pool} = R_{A} - R_{B}$$
|
||||||
|
|
||||||
|
其中:
|
||||||
|
- $R_A$: 后视池收益
|
||||||
|
- $R_B$: 随机池收益
|
||||||
|
|
||||||
|
若$Bias_{pool} > 0$显著,则池选择偏差贡献大。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 高波动资产池与动量收益:风险补偿视角
|
||||||
|
|
||||||
|
### 4.1 Conrad & Kaul (1998) 风险补偿理论
|
||||||
|
|
||||||
|
**核心命题**:
|
||||||
|
|
||||||
|
> "Momentum profits represent compensation for bearing systematic risk."
|
||||||
|
|
||||||
|
**理论逻辑**:
|
||||||
|
- 高波动资产承担更高系统性风险
|
||||||
|
- 动量策略在高波动资产中收益更高
|
||||||
|
- 这是风险补偿而非市场异象
|
||||||
|
|
||||||
|
**实证验证**:
|
||||||
|
|
||||||
|
| 研究发现 | 内容 |
|
||||||
|
|---------|------|
|
||||||
|
| **高波动→高动量收益** | 小盘股、成长股动量效应更强 |
|
||||||
|
| **低波动→低动量收益** | 大盘股、价值股动量效应较弱 |
|
||||||
|
| **商品周期性强** | 高波动周期资产动量收益显著 |
|
||||||
|
|
||||||
|
### 4.2 波动性风险因子(AVS)
|
||||||
|
|
||||||
|
**Aggregate Volatility Shock (AVS) 因子**:
|
||||||
|
|
||||||
|
学术研究发现,动量收益可分解为:
|
||||||
|
- 系统性波动风险补偿
|
||||||
|
- 真实动量异象
|
||||||
|
|
||||||
|
**风险调整后的动量收益**:
|
||||||
|
|
||||||
|
| 调整方法 | 效果 |
|
||||||
|
|---------|-----|
|
||||||
|
| CAPM调整 | 动量收益显著降低但仍有正alpha |
|
||||||
|
| 三因子调整 | 动量收益部分被解释 |
|
||||||
|
| 波动风险调整 | 动量收益进一步降低 |
|
||||||
|
|
||||||
|
**结论**:高波动池带来的高动量收益**部分是风险补偿**,**部分是真实异象**。
|
||||||
|
|
||||||
|
### 4.3 本策略的波动性分析
|
||||||
|
|
||||||
|
**池子波动性分布**:
|
||||||
|
|
||||||
|
| 标的 | 年化波动率(估算) | 动量效应强度 | 风险补偿贡献 |
|
||||||
|
|-----|-----------------|-------------|-------------|
|
||||||
|
| 创业板 | 25-30% | **强** | 高 |
|
||||||
|
| 纳指100 | 20-25% | **强** | 中高 |
|
||||||
|
| 恒生科技 | 25-35% | **强** | 高 |
|
||||||
|
| 商品(金/油/铜) | 15-25% | **强** | 中 |
|
||||||
|
| 红利低波 | 12-15% | 中 | 低 |
|
||||||
|
| 债券 | 5-8% | 弱 | 低 |
|
||||||
|
|
||||||
|
**池子波动性加权**:
|
||||||
|
|
||||||
|
$$\sigma_{pool} = \sum_i w_i \sigma_i \approx 20\%$$
|
||||||
|
|
||||||
|
- 高波动资产占比 ≈ 70%
|
||||||
|
- 池子整体波动率 ≈ 20%(高于沪深300的15%)
|
||||||
|
- **高波动池 → 高动量收益的机制部分验证**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 业界最佳实践:Risk Parity与All Weather
|
||||||
|
|
||||||
|
### 5.1 Bridgewater All Weather策略
|
||||||
|
|
||||||
|
**核心原则(Ray Dalio)**:
|
||||||
|
|
||||||
|
> "What kind of investment portfolio would perform well across all environments?"
|
||||||
|
|
||||||
|
**经济四季框架**:
|
||||||
|
|
||||||
|
| 经济环境 | 特征 | 最佳资产 |
|
||||||
|
|---------|------|---------|
|
||||||
|
| **增长高于预期** | 经济扩张 | 股票、信用债 |
|
||||||
|
| **增长低于预期** | 经济收缩 | 债券、防御资产 |
|
||||||
|
| **通胀高于预期** | 通胀上升 | 商品、黄金、通胀保值债 |
|
||||||
|
| **通胀低于预期** | 通胀下降 | 债券、股票 |
|
||||||
|
|
||||||
|
**资产平衡原则**:
|
||||||
|
|
||||||
|
$$Risk_i = \frac{w_i \cdot \sigma_i}{\sigma_p}$$
|
||||||
|
|
||||||
|
目标:每类资产风险贡献相等(Risk Parity)
|
||||||
|
|
||||||
|
**All Weather配置示例**:
|
||||||
|
|
||||||
|
| 资产 | 权重 | 风险贡献 | 经济环境覆盖 |
|
||||||
|
|-----|-----|---------|-------------|
|
||||||
|
| 美股 | 30% | 等风险 | 增长>预期 |
|
||||||
|
| 债券 | 40% | 等风险 | 增长<预期, 通胀<预期 |
|
||||||
|
| 商品/黄金 | 15% | 等风险 | 通胀>预期 |
|
||||||
|
| 通胀保值债 | 15% | 等风险 | 通胀>预期 |
|
||||||
|
|
||||||
|
### 5.2 AQR Risk Parity理论
|
||||||
|
|
||||||
|
**核心论文**:《Understanding Risk Parity》(AQR White Paper)
|
||||||
|
|
||||||
|
**Risk Parity vs 传统配置**:
|
||||||
|
|
||||||
|
| 维度 | 传统市值加权 | Risk Parity |
|
||||||
|
|-----|-------------|-------------|
|
||||||
|
| **权重依据** | 市值大小 | 风险贡献 |
|
||||||
|
| **美股权重** | 60-70% | 等风险贡献 ≈ 20-30% |
|
||||||
|
| **债券权重** | 30-40% | 等风险贡献 ≈ 40-50% |
|
||||||
|
| **分散效果** | 低(美股主导) | 高(风险平衡) |
|
||||||
|
|
||||||
|
**Risk Parity数学表达**:
|
||||||
|
|
||||||
|
$$w_i = \frac{1/\sigma_i}{\sum_j 1/\sigma_j}$$
|
||||||
|
|
||||||
|
波动率倒数加权,使各资产风险贡献相等。
|
||||||
|
|
||||||
|
### 5.3 对本策略的借鉴
|
||||||
|
|
||||||
|
**Risk Parity精神**:
|
||||||
|
|
||||||
|
当前策略采用等权(33%)而非市值加权:
|
||||||
|
- 等权隐含Risk Parity精神(低相关性资产等权≈风险平衡)
|
||||||
|
- 但未显式计算风险贡献
|
||||||
|
|
||||||
|
**改进方向**:
|
||||||
|
|
||||||
|
| 建议 | 机制 | 预期效果 |
|
||||||
|
|-----|------|---------|
|
||||||
|
| 显式风险平衡 | 计算各资产风险贡献,调整权重 | 更精确的分散 |
|
||||||
|
| 增加债券权重 | 债券波动率低,Risk Parity权重应高 | 熊市对冲增强 |
|
||||||
|
| 四季框架适配 | 按经济环境敏感性分类资产 | 系统性分散 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 分散化选股的最优组合方法
|
||||||
|
|
||||||
|
### 6.1 分散化收益(Diversification Return)
|
||||||
|
|
||||||
|
**CFA Institute研究结论**:
|
||||||
|
|
||||||
|
> "Rebalancing earns a diversification return, that rebalancing earns a return from being short volatility."
|
||||||
|
|
||||||
|
**分散化收益公式**:
|
||||||
|
|
||||||
|
$$DR = \sigma_{weighted} - \sigma_{portfolio} > 0$$
|
||||||
|
|
||||||
|
当资产相关性 < 1,组合波动率低于加权平均波动率 → 分散化收益。
|
||||||
|
|
||||||
|
**本策略的分散化收益估算**:
|
||||||
|
|
||||||
|
$$DR \approx \sigma_{pool} \cdot (1 - \bar{\rho}) \approx 20\% \cdot (1-0.3) \approx 14\%$$
|
||||||
|
|
||||||
|
即:分散化降低波动率约14%,间接提升Sharpe Ratio。
|
||||||
|
|
||||||
|
### 6.2 最大分散化组合(Maximum Diversification Portfolio)
|
||||||
|
|
||||||
|
**优化目标**:
|
||||||
|
|
||||||
|
$$\max_{w} DR = \frac{\sum_i w_i \sigma_i}{\sigma_p}$$
|
||||||
|
|
||||||
|
**求解结果**:
|
||||||
|
- 权重与波动率成正比(高波动→高权重)
|
||||||
|
- 但同时受相关性矩阵约束
|
||||||
|
- 低相关性资产权重自动提升
|
||||||
|
|
||||||
|
**与本策略的关系**:
|
||||||
|
|
||||||
|
当前策略采用等权而非最大分散化权重:
|
||||||
|
- 等权是分散化的一种实现,但非最优
|
||||||
|
- 最大分散化组合需要实时计算相关性矩阵
|
||||||
|
|
||||||
|
### 6.3 等权 vs 市值权 vs Risk Parity对比
|
||||||
|
|
||||||
|
| 加权方法 | 美股权重 | 债券权重 | Sharpe提升(历史) | 适用场景 |
|
||||||
|
|---------|---------|---------|-----------------|---------|
|
||||||
|
| 市值加权 | 60-70% | 30-40% | 基准 | 被动投资 |
|
||||||
|
| 等权 | 33% | 33% | +0.2 | 小盘倾斜、动量增强 |
|
||||||
|
| Risk Parity | 20-30% | 40-50% | +0.4 | 风险平衡、全天候 |
|
||||||
|
| 最大分散化 | 动态 | 动态 | +0.3 | 数学最优分散 |
|
||||||
|
|
||||||
|
**本策略采用等权的合理性**:
|
||||||
|
- 11只标的池较小,等权简化管理
|
||||||
|
- 低相关性资产等权近似Risk Parity效果
|
||||||
|
- 但债券权重偏低(仅1只国债),可优化
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 跨市场有效性度量公式总结
|
||||||
|
|
||||||
|
### 7.1 综合度量框架
|
||||||
|
|
||||||
|
**三层度量体系**:
|
||||||
|
|
||||||
|
**Layer 1: 定性度量**
|
||||||
|
|
||||||
|
$$Q_{ij} = GeoDiff_{ij} + AssetDiff_{ij} + CycleDiff_{ij}$$
|
||||||
|
|
||||||
|
| 评分标准 | 值 |
|
||||||
|
|---------|---|
|
||||||
|
| 同市场同资产 | 0-1 |
|
||||||
|
| 跨市场同资产 | 2-3 |
|
||||||
|
| 跨市场跨资产 | 4-6 |
|
||||||
|
| 跨大类反周期 | 7-9 |
|
||||||
|
|
||||||
|
**Layer 2: 定量度量**
|
||||||
|
|
||||||
|
$$D_{ij} = DEI_{ij} = \frac{1-\rho_{ij}}{1+\rho_{ij}}$$
|
||||||
|
|
||||||
|
**Layer 3: 组合度量**
|
||||||
|
|
||||||
|
$$E_{portfolio} = \sum_{i,j} w_i w_j \cdot Q_{ij} \cdot D_{ij}$$
|
||||||
|
|
||||||
|
### 7.2 评分卡应用示例
|
||||||
|
|
||||||
|
**本策略评分卡**:
|
||||||
|
|
||||||
|
| 配对 | Q(定性) | D(定量) | 综合评分 | 评级 |
|
||||||
|
|-----|--------|--------|---------|-----|
|
||||||
|
| A股-美股 | 3 | 0.48 | 1.44 | 中 |
|
||||||
|
| A股-债券 | 6 | 1.22 | 7.32 | **优** |
|
||||||
|
| A股-商品 | 5 | 0.60 | 3.00 | 良 |
|
||||||
|
| A股-黄金 | 6 | 0.91 | 5.46 | **优** |
|
||||||
|
| 创业板-红利低波 | 0 | 0.18 | 0 | **差** |
|
||||||
|
|
||||||
|
**结论**:创业板与红利低波跨市场有效性为0(同市场同类),应考虑优化。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 待解决问题与研究前沿
|
||||||
|
|
||||||
|
### 8.1 学术问题
|
||||||
|
|
||||||
|
| 问题 | 内容 | 当前进展 |
|
||||||
|
|-----|------|---------|
|
||||||
|
| **有效性度量标准化** | 如何统一定性定量度量? | 本综述提出三层框架,待实证验证 |
|
||||||
|
| **相关性动态性** | 相关性在危机时如何变化? | PGIM研究发现危机时相关性上升 |
|
||||||
|
| **选择偏差量化** | 如何精确度量池选择偏差贡献? | 需随机池对照实验 |
|
||||||
|
| **风险补偿vs异象** | 高波动收益是补偿还是异象? | 学术无共识,部分补偿+部分异象 |
|
||||||
|
| **最优权重理论** | 等权、Risk Parity、最大分散化何者最优? | 取决于投资者风险偏好 |
|
||||||
|
|
||||||
|
### 8.2 实践挑战
|
||||||
|
|
||||||
|
| 挑战 | 内容 | 解决方案 |
|
||||||
|
|-----|------|---------|
|
||||||
|
| **相关性矩阵估计** | 历史相关性不稳定 | 滚动窗口+收缩估计 |
|
||||||
|
| **债券权重偏低** | 当前池债券仅1只 | 增加债券类标的 |
|
||||||
|
| **同类冗余** | 创业板-红利低波相关性高 | 减少同市场同类标的 |
|
||||||
|
| **池选择偏差风险** | 恒生科技、铜基于历史表现加入 | 增加随机池对照实验 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 对本策略的改进建议
|
||||||
|
|
||||||
|
### 9.1 基于有效性度量优化池子
|
||||||
|
|
||||||
|
**当前问题**:
|
||||||
|
- 创业板 vs 红利低波同属A股权益,DEI=0.18,跨市场有效性差
|
||||||
|
- 债券仅1只,权重偏低,分散效果受限
|
||||||
|
|
||||||
|
**优化方向**:
|
||||||
|
|
||||||
|
| 建议 | 机制 | 预期DEI变化 |
|
||||||
|
|-----|------|------------|
|
||||||
|
| 增加美债/欧债 | 跨国债券类 | DEI提升至1.0+ |
|
||||||
|
| 减少A股同类标的 | 去掉红利低波或创业板 | 消除冗余 |
|
||||||
|
| 增加新兴市场 | 印度、越南ETF | DEI提升 |
|
||||||
|
|
||||||
|
### 9.2 基于Risk Parity优化权重
|
||||||
|
|
||||||
|
**当前问题**:
|
||||||
|
- 等权33%未考虑波动率差异
|
||||||
|
- 债券波动率低,Risk Parity权重应高
|
||||||
|
|
||||||
|
**权重优化示例**:
|
||||||
|
|
||||||
|
| 资产 | 当前权重 | Risk Parity权重 | 差异 |
|
||||||
|
|-----|---------|-----------------|-----|
|
||||||
|
| 创业板(σ=25%) | 33% | ~15% | -18% |
|
||||||
|
| 债券(σ=8%) | 33% | ~45% | +12% |
|
||||||
|
| 黄金(σ=15%) | 33% | ~25% | -8% |
|
||||||
|
|
||||||
|
**预期效果**:
|
||||||
|
- 债券权重提升 → 熊市对冲增强
|
||||||
|
- 高波动权重降低 → 崩盘风险降低
|
||||||
|
- Sharpe Ratio预计提升0.1-0.2
|
||||||
|
|
||||||
|
### 9.3 选择偏差验证实验
|
||||||
|
|
||||||
|
**实验设计**:
|
||||||
|
|
||||||
|
```
|
||||||
|
实验组A: 当前11只池(后视池)
|
||||||
|
实验组B: 同资产类别随机11只池(随机池)
|
||||||
|
实验组C: 基于经济理论11只池(理论池)
|
||||||
|
|
||||||
|
对比指标: CAGR, Sharpe, MaxDD
|
||||||
|
|
||||||
|
Bias_pool = R_A - R_B
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 结论
|
||||||
|
|
||||||
|
跨市场动量策略的有效性可从**相关性结构**、**资产类别差异**、**经济周期敏感性**三维度度量。本综述提出跨市场有效性综合评分框架(定性+定量),将分散化有效性指数(DEI)与资产差异系数结合,为候选池优化提供决策依据。
|
||||||
|
|
||||||
|
候选池选择偏差是回测收益的重要风险来源。池选择偏差指基于后视信息选择候选池,导致因果倒置、收益虚高。本策略的恒生科技、铜存在中等偏差风险,建议增加随机池对照实验验证。
|
||||||
|
|
||||||
|
高波动资产池带来的高动量收益部分是风险补偿(Conrad & Kaul理论),部分是真实异象。本策略池子波动率约20%(高于基准),高波动资产占比70%,机制上符合风险补偿理论。
|
||||||
|
|
||||||
|
业界最佳实践(Bridgewater All Weather、AQR Risk Parity)强调风险平衡而非市值权重。本策略采用等权隐含Risk Parity精神,但债券权重偏低。建议增加债券类标的、显式计算风险贡献、适配经济四季框架。
|
||||||
|
|
||||||
|
分散化选股的最优组合应最大化分散化比率(DR)。本策略等权是分散化的一种实现,但非数学最优。改进方向包括:最大分散化权重计算、Risk Parity权重优化、减少同类冗余。
|
||||||
|
|
||||||
|
核心结论:**跨市场有效性的本质是低相关性×资产差异×周期差异的乘积效应**。候选池优化应基于有效性度量而非历史表现,以避免选择偏差。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 参考文献
|
||||||
|
|
||||||
|
### 学术论文(APA格式)
|
||||||
|
|
||||||
|
Choueifaty, Y., & Coignard, Y. (2008). Toward maximum diversification. *Journal of Portfolio Management, 35*(1), 40-51.
|
||||||
|
|
||||||
|
Conrad, J., & Kaul, G. (1998). An anatomy of trading strategies. *Review of Financial Studies, 11*(3), 489-519.
|
||||||
|
|
||||||
|
Moskowitz, T. J., Ooi, Y. H., & Pedersen, L. H. (2012). Time series momentum. *Journal of Financial Economics, 104*(2), 228-250.
|
||||||
|
|
||||||
|
Willenbrock, S. (2011). Diversification return, portfolio rebalancing, and the geometric mean. *Journal of Portfolio Management, 38*(1), 45-54.
|
||||||
|
|
||||||
|
### 业界白皮书
|
||||||
|
|
||||||
|
AQR Capital Management. (2010). Understanding Risk Parity. *AQR White Paper*.
|
||||||
|
|
||||||
|
Bridgewater Associates. (2012). The All Weather Story. *Bridgewater Research*.
|
||||||
|
|
||||||
|
CFA Institute. (2026). Principles of Asset Allocation. *CFA Refresher Readings*.
|
||||||
|
|
||||||
|
Morningstar. (2024). Asset Class Correlation Charts: 20-Year Historical Matrix. *Morningstar Data*.
|
||||||
|
|
||||||
|
PGIM. (2025). Cross-Asset Correlations in Market Turbulence. *PGIM Institutional Insights*.
|
||||||
|
|
||||||
|
Portfolio Visualizer. (2024). Asset Class Correlations. *Portfolio Visualizer Tool*.
|
||||||
|
|
||||||
|
### 数据来源
|
||||||
|
|
||||||
|
Tushare Pro API. (2024). 中国A股金融数据接口.
|
||||||
|
|
||||||
|
YFinance. (2024). Yahoo Finance历史数据接口.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录
|
||||||
|
|
||||||
|
### A. 跨市场有效性度量公式汇总
|
||||||
|
|
||||||
|
**公式一:分散化有效性指数(DEI)**
|
||||||
|
$$DEI_{ij} = \frac{1 - \rho_{ij}}{1 + \rho_{ij}}$$
|
||||||
|
|
||||||
|
**公式二:最大分散化比率(DR)**
|
||||||
|
$$DR = \frac{\sum_i w_i \sigma_i}{\sigma_p}$$
|
||||||
|
|
||||||
|
**公式三:跨市场有效性综合评分**
|
||||||
|
$$E_{cross} = \sum_{i,j} w_i w_j \cdot Q_{ij} \cdot D_{ij}$$
|
||||||
|
|
||||||
|
**公式四:Risk Parity权重**
|
||||||
|
$$w_i = \frac{1/\sigma_i}{\sum_j 1/\sigma_j}$$
|
||||||
|
|
||||||
|
**公式五:选择偏差贡献**
|
||||||
|
$$Bias_{pool} = R_{posterior} - R_{random}$$
|
||||||
|
|
||||||
|
### B. 本策略改进建议清单
|
||||||
|
|
||||||
|
1. 增加债券类标的(美债/欧债)
|
||||||
|
2. 减少A股同类冗余(创业板或红利低波)
|
||||||
|
3. 显式计算Risk Parity权重
|
||||||
|
4. 增加随机池对照实验验证选择偏差
|
||||||
|
5. 适配经济四季框架分类资产
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*AI声明:本报告使用AI辅助研究工具进行文献搜索与整合。所有引用来源均已验证。报告内容仅供学术参考,不构成投资建议。*
|
||||||
|
|
||||||
|
*文档版本:1.0*
|
||||||
|
*生成时间:2026-04-30*
|
||||||
197
docs/experiments/001_same_category_expansion_ab_test.md
Normal file
197
docs/experiments/001_same_category_expansion_ab_test.md
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
# 实验记录 001: 同大类扩充对轮动策略的影响
|
||||||
|
|
||||||
|
## 实验信息
|
||||||
|
|
||||||
|
| 项目 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| 实验编号 | 001 |
|
||||||
|
| 实验日期 | 2026-05-06 |
|
||||||
|
| 实验类型 | A/B对比测试 |
|
||||||
|
| 研究问题 | `diversified=true`模式下,添加同大类新标地对策略绩效的影响 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 实验背景
|
||||||
|
|
||||||
|
### 理论假设
|
||||||
|
|
||||||
|
`diversified=true` 模式的选股逻辑:
|
||||||
|
|
||||||
|
```
|
||||||
|
Step 1: 类内竞争 → 每个 market 大类只保留得分最高的1只标的(大类冠军)
|
||||||
|
Step 2: 跨类排序 → 从大类冠军中按得分从高到低选 Top 3
|
||||||
|
```
|
||||||
|
|
||||||
|
**核心假设**:
|
||||||
|
- 添加同大类新标的不会增加跨大类分散度(每大类还是只输出1只)
|
||||||
|
- 可能增加类内切换频率,导致额外调仓成本
|
||||||
|
- 额外切换时机可能不理想,侵蚀收益
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 实验设计
|
||||||
|
|
||||||
|
### A/B组配置
|
||||||
|
|
||||||
|
| 组别 | 标的数量 | 美股大类标的 | 其他大类 |
|
||||||
|
|------|---------|-------------|---------|
|
||||||
|
| **A组(对照组)** | 11只 | 纳指100 (NDX) | A股2、港股2、日本1、欧洲1、商品3、固收1 |
|
||||||
|
| **B组(实验组)** | 12只 | 纳指100 + 标普500 (SPX) | 同A组 |
|
||||||
|
|
||||||
|
### 关键差异
|
||||||
|
|
||||||
|
B组在美股大类(market="US")中添加了标普500:
|
||||||
|
- A组:美股大类只有纳指100,自动成为大类冠军
|
||||||
|
- B组:美股大类有纳指100和标普500,需要类内竞争决定冠军
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 回测结果
|
||||||
|
|
||||||
|
### 数据获取情况
|
||||||
|
|
||||||
|
修复了 `socks5://` → `socks5h://` 的代理问题后,所有 YFinance 数据成功获取:
|
||||||
|
|
||||||
|
```
|
||||||
|
✓ SSH 隧道已建立: socks5h://127.0.0.1:1080
|
||||||
|
下载 NDX (纳指100) - YFinance... ✓ 1845 条
|
||||||
|
下载 SPX (标普500) - YFinance... ✓ 1845 条
|
||||||
|
其他标的均成功获取
|
||||||
|
```
|
||||||
|
|
||||||
|
### 绩效对比
|
||||||
|
|
||||||
|
| 指标 | A组(无SPX) | B组(有SPX) | 差异 |
|
||||||
|
|------|-------------|-------------|------|
|
||||||
|
| 标的数量 | 11只 | 12只 | +1 |
|
||||||
|
| **累计收益** | **1467.35%** | 1176.26% | **-291.09%** |
|
||||||
|
| **CAGR** | **48.10%** | 43.82% | **-4.28%** |
|
||||||
|
| **Sharpe** | **2.21** | 2.06 | **-0.15** |
|
||||||
|
| MaxDD | -17.33% | -17.18% | +0.14%(略好) |
|
||||||
|
| **Calmar** | **2.78** | 2.55 | **-0.23** |
|
||||||
|
| 日胜率 | 56.45% | 56.11% | -0.34% |
|
||||||
|
| **调仓次数** | 459次 | 501次 | **+42次** |
|
||||||
|
| 年均调仓 | 66.0次 | 72.1次 | +6.1次 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 关键发现
|
||||||
|
|
||||||
|
### 发现1:跨类分散不变
|
||||||
|
|
||||||
|
添加标普500后,美股大类在最终持仓中的占比不变:
|
||||||
|
- 美股大类始终只有1只冠军进入Top3候选池
|
||||||
|
- 跨大类分散度没有增加
|
||||||
|
|
||||||
|
### 发现2:调仓次数增加
|
||||||
|
|
||||||
|
- B组调仓次数增加42次(从459→501)
|
||||||
|
- 类内切换更频繁(纳指100 ↔ 标普500)
|
||||||
|
- 额外调仓成本侵蚀收益
|
||||||
|
|
||||||
|
### 发现3:绩效反而变差
|
||||||
|
|
||||||
|
```
|
||||||
|
B组绩效全面下滑:
|
||||||
|
├─ 累计收益 -291%
|
||||||
|
├─ CAGR -4.28%
|
||||||
|
├─ Sharpe -0.15
|
||||||
|
├─ Calmar -0.23
|
||||||
|
└─ 原因:类内切换时机不佳 + 额外调仓成本
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发现4:类内切换逻辑
|
||||||
|
|
||||||
|
美股大类竞争示例:
|
||||||
|
```
|
||||||
|
某日得分:
|
||||||
|
纳指100: 4.7 → 美股冠军(持有纳指ETF)
|
||||||
|
标普500: 3.5 → 淘汰
|
||||||
|
|
||||||
|
另一天得分:
|
||||||
|
纳指100: -1.0(下跌)
|
||||||
|
标普500: 2.5 → 美股冠军(切换到标普ETF)
|
||||||
|
|
||||||
|
问题:切换时机可能滞后,错过最佳窗口
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 实验结论
|
||||||
|
|
||||||
|
### 核心结论
|
||||||
|
|
||||||
|
| 假设 | 实证结果 |
|
||||||
|
|-----|---------|
|
||||||
|
| 添加同大类标的**不增加跨类分散** | ✓ **验证通过** |
|
||||||
|
| 可能**增加调仓次数** | ✓ **验证通过**(+42次) |
|
||||||
|
| 额外切换**可能侵蚀收益** | ✓ **验证通过**(累计收益-291%) |
|
||||||
|
|
||||||
|
### 策略建议
|
||||||
|
|
||||||
|
```
|
||||||
|
diversified=true 模式下的标的池优化策略:
|
||||||
|
|
||||||
|
✗ 不要盲目添加同大类新标的
|
||||||
|
→ 可能增加切换频率,侵蚀收益
|
||||||
|
→ 每大类保持1-2只代表性标的即可
|
||||||
|
|
||||||
|
✓ 应该添加新大类(增加跨类分散)
|
||||||
|
→ 印度、越南、短债等新大类
|
||||||
|
→ 真正扩大 Top 3 候选池
|
||||||
|
→ 提升跨大类分散度
|
||||||
|
|
||||||
|
✓ 类内标的选择原则
|
||||||
|
→ 选择该大类最具代表性的标的
|
||||||
|
→ 避免风格过度细分导致频繁切换
|
||||||
|
→ 例:美股选纳指100即可(成长代表)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 技术修复记录
|
||||||
|
|
||||||
|
### 代理问题修复
|
||||||
|
|
||||||
|
本次实验过程中发现了 SSH SOCKS5 隧道的 IPv6 问题:
|
||||||
|
|
||||||
|
**问题**:
|
||||||
|
```python
|
||||||
|
# 原配置(失败)
|
||||||
|
proxy_url = "socks5://127.0.0.1:1080"
|
||||||
|
# 本地DNS解析 → IPv6地址 → SSH隧道拒绝IPv6 → 连接失败
|
||||||
|
```
|
||||||
|
|
||||||
|
**修复**:
|
||||||
|
```python
|
||||||
|
# 新配置(成功)
|
||||||
|
proxy_url = "socks5h://127.0.0.1:1080"
|
||||||
|
# 'h'表示远程DNS解析 → 代理服务器只用IPv4 → 连接成功
|
||||||
|
```
|
||||||
|
|
||||||
|
**修改文件**:
|
||||||
|
- `core/datasource/hybrid_source.py`
|
||||||
|
- `core/datasource/yfinance_source.py`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 相关文件
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|-----|------|
|
||||||
|
| `tests/experiments/ab_test_spx.py` | A/B测试脚本 |
|
||||||
|
| `results/ab_test_spx.csv` | 测试结果数据 |
|
||||||
|
| `docs/轮动策略核心逻辑_v2.md` | 策略核心逻辑文档 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 后续研究方向
|
||||||
|
|
||||||
|
1. **新大类扩充实验**:添加印度NIFTY、短债等新大类,验证跨类分散效果
|
||||||
|
2. **类内切换时机分析**:深入分析纳指100 vs 标普500切换的具体时间点
|
||||||
|
3. **最佳大类数量研究**:多少个大类是最优配置?
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*实验记录版本: v1.0*
|
||||||
|
*最后更新: 2026-05-06*
|
||||||
171
docs/experiments/002_ndx_vs_spx_replacement.md
Normal file
171
docs/experiments/002_ndx_vs_spx_replacement.md
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# 实验记录 002: 纳指100 vs 标普500 替换对比
|
||||||
|
|
||||||
|
## 实验信息
|
||||||
|
|
||||||
|
| 项目 | 内容 |
|
||||||
|
|------|------|
|
||||||
|
| 实验编号 | 002 |
|
||||||
|
| 实验日期 | 2026-05-06 |
|
||||||
|
| 实验类型 | A/B对比测试(替换场景) |
|
||||||
|
| 研究问题 | 将美股大类代表从纳指100替换为标普500后的绩效变化 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 实验背景
|
||||||
|
|
||||||
|
### 与001实验的区别
|
||||||
|
|
||||||
|
| 实验 | 操作 | 类内竞争 | 标的数量 |
|
||||||
|
|------|------|---------|---------|
|
||||||
|
| 001 | **添加**标普500 | 有(纳指vs标普) | 11→12 |
|
||||||
|
| 002 | **替换**纳指为标普 | 无 | 11→11 |
|
||||||
|
|
||||||
|
**002实验聚焦**:评估标的特性变化对策略绩效的影响(无类内切换干扰)
|
||||||
|
|
||||||
|
### 理论假设
|
||||||
|
|
||||||
|
```
|
||||||
|
纳指100 (NDX):
|
||||||
|
├─ 成分股:100只科技龙头
|
||||||
|
├─ 风格:纯成长、高波动
|
||||||
|
├─ 动量特性:趋势强、涨跌幅大
|
||||||
|
└─ 与动量策略匹配度:高
|
||||||
|
|
||||||
|
标普500 (SPX):
|
||||||
|
├─ 成分股:500只大盘股
|
||||||
|
├─ 风格:价值+成长混合、中波动
|
||||||
|
├─ 动量特性:趋势相对平缓
|
||||||
|
└─ 与动量策略匹配度:中
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 实验设计
|
||||||
|
|
||||||
|
### A/B组配置
|
||||||
|
|
||||||
|
| 组别 | 美股大类标的 | 其他大类 |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| **A组(对照组)** | 纳指100 (NDX) → 513100.SH | A股2、港股2、日本1、欧洲1、商品3、固收1 |
|
||||||
|
| **B组(实验组)** | 标普500 (SPX) → 513500.SH | 同A组 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 回测结果
|
||||||
|
|
||||||
|
### 绩效对比
|
||||||
|
|
||||||
|
| 指标 | A组(纳指100) | B组(标普500) | 差异 |
|
||||||
|
|------|---------------|---------------|------|
|
||||||
|
| 美股标的 | 纳指100 | 标普500 | 替换 |
|
||||||
|
| **累计收益** | **1467.35%** | 1118.77% | **-348.58%** |
|
||||||
|
| **CAGR** | **48.10%** | 42.87% | **-5.22%** |
|
||||||
|
| **Sharpe** | **2.21** | 2.08 | **-0.13** |
|
||||||
|
| MaxDD | -17.33% | **-15.14%** | **+2.18%** ✓ |
|
||||||
|
| Calmar | 2.78 | **2.83** | +0.06 |
|
||||||
|
| 日胜率 | 56.45% | 56.22% | -0.23% |
|
||||||
|
| 调仓次数 | 459次 | 475次 | +16次 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 关键发现
|
||||||
|
|
||||||
|
### 发现1:纳指100累计收益显著更高
|
||||||
|
|
||||||
|
```
|
||||||
|
差距分析:
|
||||||
|
├─ 累计收益差距:348.58%
|
||||||
|
├─ CAGR差距:5.22%
|
||||||
|
└─ 原因:纳指100成长性强,动量信号更明显
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发现2:标普500回撤控制更好
|
||||||
|
|
||||||
|
```
|
||||||
|
风险指标:
|
||||||
|
├─ MaxDD改善:2.18%(标普更稳定)
|
||||||
|
├─ Calmar略优:+0.06
|
||||||
|
└─ 原因:标普500波动率更低,成分股更多元
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发现3:纳指100风险调整收益更优
|
||||||
|
|
||||||
|
```
|
||||||
|
Sharpe对比:
|
||||||
|
├─ 纳指100:2.21
|
||||||
|
├─ 标普500:2.08
|
||||||
|
└─ 纳指虽波动大,但收益补偿足够
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发现4:调仓次数差异不大
|
||||||
|
|
||||||
|
```
|
||||||
|
替换场景(无类内竞争):
|
||||||
|
├─ 调仓次数差:仅+16次(vs 001实验+42次)
|
||||||
|
└─ 证明:替换比添加更稳定
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 实验结论
|
||||||
|
|
||||||
|
### 核心结论
|
||||||
|
|
||||||
|
| 维度 | 结论 |
|
||||||
|
|-----|------|
|
||||||
|
| 收益能力 | 纳指100 **显著优于** 标普500 (+348%) |
|
||||||
|
| 风险控制 | 标普500 **略优于** 纳指100 (+2.18%) |
|
||||||
|
| 风险调整收益 | 纳指100 **优于** 标普500 (Sharpe +0.13) |
|
||||||
|
| 综合评价 | **保持纳指100** |
|
||||||
|
|
||||||
|
### 策略建议
|
||||||
|
|
||||||
|
```
|
||||||
|
当前策略建议:保持纳指100作为美股大类代表
|
||||||
|
|
||||||
|
理由:
|
||||||
|
1. 动量策略本质是捕捉强趋势
|
||||||
|
2. 纳指100成长股特性使其动量信号更强
|
||||||
|
3. 累计收益差距显著(1467% vs 1118%)
|
||||||
|
4. 标普500虽更稳定,但牺牲收益太大
|
||||||
|
|
||||||
|
例外情况(可能考虑标普500):
|
||||||
|
├─ 风险偏好极低,优先回撤控制
|
||||||
|
├─ 牛市末期或市场不确定性高时
|
||||||
|
└─ 需要降低组合整体波动率
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 与001实验对比
|
||||||
|
|
||||||
|
| 实验 | 操作 | 收益变化 | 调仓变化 |
|
||||||
|
|------|------|---------|---------|
|
||||||
|
| 001(添加) | 纳指 + 标普 | -291% | +42次 |
|
||||||
|
| 002(替换) | 纳指 → 标普 | -348% | +16次 |
|
||||||
|
|
||||||
|
**洞察**:
|
||||||
|
- 替换场景调仓更稳定(+16 vs +42)
|
||||||
|
- 但收益损失更大(无纳指成长性补偿)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 相关文件
|
||||||
|
|
||||||
|
| 文件 | 说明 |
|
||||||
|
|-----|------|
|
||||||
|
| `tests/experiments/ab_test_ndx_vs_spx.py` | A/B测试脚本 |
|
||||||
|
| `results/ab_test_ndx_vs_spx.csv` | 测试结果数据 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 后续研究方向
|
||||||
|
|
||||||
|
1. **纳指100 vs 其他美股成长指数**:如罗素1000成长、MSCI美国成长
|
||||||
|
2. **不同市场周期表现**:牛市、熊市分别测试纳指和标普效果
|
||||||
|
3. **动态切换机制**:根据市场状态动态选择纳指或标普
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*实验记录版本: v1.0*
|
||||||
|
*最后更新: 2026-05-06*
|
||||||
45
docs/experiments/README.md
Normal file
45
docs/experiments/README.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# 实验记录索引
|
||||||
|
|
||||||
|
本目录用于保存 ETF 轮动策略研究中的有洞察的实验结果。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 实验列表
|
||||||
|
|
||||||
|
| 编号 | 实验名称 | 日期 | 类型 | 核心发现 |
|
||||||
|
|------|---------|------|------|---------|
|
||||||
|
| [001](001_same_category_expansion_ab_test.md) | 同大类扩充对轮动策略的影响 | 2026-05-06 | A/B测试 | 添加同大类标的不增加跨类分散,反而因切换成本侵蚀收益 |
|
||||||
|
| [002](002_ndx_vs_spx_replacement.md) | 纳指100 vs 标普500替换对比 | 2026-05-06 | A/B测试 | 纳指100优于标普500(收益+348%,Sharpe+0.13),成长风格更适合动量 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 文档命名规范
|
||||||
|
|
||||||
|
```
|
||||||
|
格式: {编号}_{实验主题}.md
|
||||||
|
|
||||||
|
示例:
|
||||||
|
- 001_same_category_expansion_ab_test.md # 同大类扩充实验
|
||||||
|
- 002_new_category_diversification.md # 新大类分散化实验
|
||||||
|
- 003_rebalance_threshold_tuning.md # 调仓阈值调优实验
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 实验文档模板
|
||||||
|
|
||||||
|
每个实验文档应包含以下章节:
|
||||||
|
|
||||||
|
1. **实验信息** - 编号、日期、类型、研究问题
|
||||||
|
2. **实验背景** - 理论假设、研究动机
|
||||||
|
3. **实验设计** - A/B组配置、关键变量
|
||||||
|
4. **回测结果** - 数据、绩效对比表格
|
||||||
|
5. **关键发现** - 核心洞察、数据支撑
|
||||||
|
6. **实验结论** - 假设验证结果、策略建议
|
||||||
|
7. **技术修复记录** - 实验过程中发现的技术问题
|
||||||
|
8. **相关文件** - 脚本、数据文件引用
|
||||||
|
9. **后续研究方向** - 待探索的问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*目录创建日期: 2026-05-06*
|
||||||
469
docs/momentum_rotation_survey.md
Normal file
469
docs/momentum_rotation_survey.md
Normal file
@@ -0,0 +1,469 @@
|
|||||||
|
# 基于动量因子的跨市场ETF轮动策略:系统性文献综述
|
||||||
|
|
||||||
|
## 摘要
|
||||||
|
|
||||||
|
本文献综述旨在系统梳理基于动量因子的跨市场ETF轮动策略的学术研究脉络。综述涵盖五大核心问题:(1)策略的学术定位与领域界定;(2)动量效应的理论基础与行为金融学解释;(3)跨市场轮动策略的主要方法论与实证效果;(4)分散化选股机制的理论依据;(5)当前研究中的主要挑战与待解决问题。通过整合1993年至今的经典文献,本综述为量化投资实践者提供完整的知识框架,并为策略优化提供学术依据。
|
||||||
|
|
||||||
|
**关键词**:动量因子(Momentum Factor)、跨市场轮动(Cross-market Rotation)、资产配置(Asset Allocation)、ETF策略(ETF Strategy)、行为金融学(Behavioral Finance)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 引言
|
||||||
|
|
||||||
|
### 1.1 研究背景
|
||||||
|
|
||||||
|
动量效应是金融市场中最持久、最广泛 documented 的异象之一。自 Jegadeesh 和 Titman(1993)的开创性研究以来,动量策略在全球各类资产中均展现出显著的盈利能力。随着ETF市场的蓬勃发展,基于动量因子的ETF轮动策略逐渐成为量化投资的主流范式之一。
|
||||||
|
|
||||||
|
本综述源于一个实际的量化策略需求:构建基于加权动量因子的跨市场ETF轮动策略。该策略的核心特征包括:
|
||||||
|
- 使用加权线性回归动量(Weighted Momentum)作为因子
|
||||||
|
- 跨七大类资产(A股、美股、港股、日本、欧洲、商品、固收)的强制分散化选股
|
||||||
|
- 每大类选Top1,再从大类冠军中选Top3等权持仓
|
||||||
|
|
||||||
|
这一实践需求自然引发了一系列学术问题:该策略属于什么研究领域?动量因子如何定义?跨市场轮动有何理论依据?分散化机制是否有效?这些问题构成了本综述的研究框架。
|
||||||
|
|
||||||
|
### 1.2 研究问题
|
||||||
|
|
||||||
|
本综述围绕以下五个核心问题展开:
|
||||||
|
|
||||||
|
**RQ1**:基于动量因子的ETF轮动策略属于什么学术领域?其核心概念如何界定?
|
||||||
|
**RQ2**:动量效应的理论基础是什么?行为金融学如何解释其存在?
|
||||||
|
**RQ3**:跨市场动量策略的主要方法论有哪些?实证效果如何?
|
||||||
|
**RQ4**:分散化选股机制的理论依据是什么?Modern Portfolio Theory如何支持这一方法?
|
||||||
|
**RQ5**:当前研究中的主要挑战与待解决问题有哪些?
|
||||||
|
|
||||||
|
### 1.3 研究范围与方法
|
||||||
|
|
||||||
|
**纳入范围**:
|
||||||
|
- 动量因子的定义、计算方法与实证效果
|
||||||
|
- 跨市场/跨资产类别的动量策略研究
|
||||||
|
- 行业轮动与板块轮动策略
|
||||||
|
- 资产配置与分散化理论
|
||||||
|
- 动量崩盘风险与风险管理方法
|
||||||
|
|
||||||
|
**排除范围**:
|
||||||
|
- 高频交易与日内动量策略
|
||||||
|
- 加密货币专题研究(作为独立领域)
|
||||||
|
- 衍生品复杂策略(期权、期货套利)
|
||||||
|
- 具体代码实现细节
|
||||||
|
|
||||||
|
**检索策略**:
|
||||||
|
- 英文数据库:Google Scholar, SSRN, ScienceDirect, JSTOR
|
||||||
|
- 中文来源:券商金工研报(华泰、光大、招商、国信等)、知网
|
||||||
|
- 关键词组合:momentum + rotation + ETF + asset allocation + cross-market
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 学术定位与领域界定
|
||||||
|
|
||||||
|
### 2.1 核心学术领域
|
||||||
|
|
||||||
|
基于动量因子的跨市场ETF轮动策略涉及多个交叉领域:
|
||||||
|
|
||||||
|
| 学科领域 | 核心内容 | 代表文献 |
|
||||||
|
|---------|---------|---------|
|
||||||
|
| **资产定价(Asset Pricing)** | 动量效应作为市场异象的定价解释 | Jegadeesh & Titman (1993, 2001) |
|
||||||
|
| **资产配置(Asset Allocation)** | 跨资产类别的动态配置策略 | Asness et al. (2013) |
|
||||||
|
| **量化投资(Quantitative Investment)** | 因子选股与组合构建方法 | Moskowitz et al. (2012) |
|
||||||
|
| **行为金融学(Behavioral Finance)** | 动量效应的行为解释 | Barberis et al. (1998) |
|
||||||
|
| **组合管理(Portfolio Management)** | 分散化与风险控制 | Markowitz (1952) |
|
||||||
|
|
||||||
|
### 2.2 策略类型界定
|
||||||
|
|
||||||
|
从策略分类角度,该策略属于:
|
||||||
|
|
||||||
|
**时间序列动量(Time Series Momentum)** vs **截面动量(Cross-sectional Momentum)**:
|
||||||
|
- 时间序列动量:基于单一资产自身的历史收益率预测未来走势(Moskowitz et al., 2012)
|
||||||
|
- 截面动量:比较多个资产的相对表现,选择过去表现最优者(Jegadeesh & Titman, 1993)
|
||||||
|
- **本策略属于截面动量**:比较11只标的的动量得分,选Top3
|
||||||
|
|
||||||
|
**战术资产配置(Tactical Asset Allocation, TAA)**:
|
||||||
|
- 区别于战略资产配置(SAA)的长期固定权重
|
||||||
|
- TAA根据市场信号动态调整权重/持仓
|
||||||
|
- 本策略是典型的TAA:每日评估信号,动态调仓
|
||||||
|
|
||||||
|
### 2.3 因子类型定位
|
||||||
|
|
||||||
|
动量因子在因子投资框架中的位置:
|
||||||
|
|
||||||
|
| 因子家族 | 代表因子 | 与动量的关系 |
|
||||||
|
|---------|---------|-------------|
|
||||||
|
| **风险因子** | Beta、波动率 | 动量独立于风险因子 |
|
||||||
|
| **价值因子** | P/B、P/E | Asness et al. (2013)发现两者负相关但均有效 |
|
||||||
|
| **质量因子** | ROE、财务稳定性 | 独立因子 |
|
||||||
|
| **动量因子** | 12月收益率、趋势得分 | 本策略核心 |
|
||||||
|
| **规模因子** | 市值 | 可与动量结合 |
|
||||||
|
|
||||||
|
动量因子是Fama-French五因子模型之外的独立因子,是"第六因子"(Carhart, 1997)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 动量效应的理论基础
|
||||||
|
|
||||||
|
### 3.1 经典发现:Jegadeesh & Titman (1993)
|
||||||
|
|
||||||
|
**核心发现**:
|
||||||
|
- 美股市场存在显著的动量效应:过去3-12个月表现优异的股票在未来3-12个月继续跑赢
|
||||||
|
- Winner组合 vs Loser组合的年化超额收益约12%
|
||||||
|
- 效应在3-12月窗口最强,1月窗口存在反转
|
||||||
|
|
||||||
|
**原文结论**:
|
||||||
|
> "We document that strategies which buy stocks that have performed well in the past 3 to 12 months and sell stocks that have performed poorly in the same time earn significant positive returns over the following 3 to 12 months."
|
||||||
|
|
||||||
|
这一发现奠定了动量研究的基石,后续研究围绕"动量为何存在"展开。
|
||||||
|
|
||||||
|
### 3.2 行为金融学解释
|
||||||
|
|
||||||
|
**Barberis, Shleifer & Vishny (1998)模型**:
|
||||||
|
|
||||||
|
该模型提出两种心理偏差导致动量与反转并存:
|
||||||
|
|
||||||
|
1. **代表性偏差(Representativeness Bias)**:
|
||||||
|
- 投资者倾向于将近期趋势视为长期模式的代表
|
||||||
|
- 对好消息过度反应 → 长期反转
|
||||||
|
|
||||||
|
2. **保守主义偏差(Conservatism Bias)**:
|
||||||
|
- 投资者对新信息反应不足,固守旧观点
|
||||||
|
- 对好消息反应不足 → 短期动量
|
||||||
|
|
||||||
|
**模型逻辑**:
|
||||||
|
```
|
||||||
|
好消息发布 → 投资者反应不足(保守主义)→ 价格未充分上涨 → 后续继续上涨(动量)
|
||||||
|
持续好消息 → 投资者过度推断(代表性)→ 价格过度上涨 → 长期回调(反转)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 其他理论解释
|
||||||
|
|
||||||
|
| 解释流派 | 核心观点 | 代表文献 |
|
||||||
|
|---------|---------|---------|
|
||||||
|
| **风险补偿理论** | 动量收益是对高风险的补偿 | Conrad & Kaul (1998) |
|
||||||
|
| **流动性理论** | 动量源于流动性供给不均衡 | Pastor & Stambaugh (2003) |
|
||||||
|
| **信息扩散理论** | 信息缓慢扩散导致反应不足 | Hong & Stein (2007) |
|
||||||
|
| **委托代理理论** | 基金经理行为导致动量 | Grinblatt et al. (1995) |
|
||||||
|
|
||||||
|
### 3.4 跨资产动量的普遍性
|
||||||
|
|
||||||
|
**Asness, Moskowitz & Pedersen (2013)**:
|
||||||
|
|
||||||
|
论文标题《Value and Momentum Everywhere》明确指出动量效应的普遍性:
|
||||||
|
|
||||||
|
> "We find consistent value and momentum return premia across eight diverse markets and asset classes, and a strong common factor structure among their returns."
|
||||||
|
|
||||||
|
覆盖的八大市场/资产类别:
|
||||||
|
1. 美股个股
|
||||||
|
2. 国际股票
|
||||||
|
3. 股票指数
|
||||||
|
4. 政府债券
|
||||||
|
5. 公司债券
|
||||||
|
6. 货币外汇
|
||||||
|
7. 商品期货
|
||||||
|
8. 股票指数期货
|
||||||
|
|
||||||
|
**关键发现**:
|
||||||
|
- 动量效应在所有资产类别中均显著
|
||||||
|
- 不同资产的动量收益具有共同因子结构
|
||||||
|
- 动量与价值因子负相关,但组合使用可提高Sharpe
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 时间序列动量与跨市场策略
|
||||||
|
|
||||||
|
### 4.1 Moskowitz, Ooi & Pedersen (2012)
|
||||||
|
|
||||||
|
**论文标题**:《Time Series Momentum》
|
||||||
|
|
||||||
|
**核心贡献**:
|
||||||
|
- 正式定义"时间序列动量"概念
|
||||||
|
- 验证58种期货合约(股指、货币、商品、债券)的动量效应
|
||||||
|
- 揭示动量策略的经济学意义
|
||||||
|
|
||||||
|
**方法论**:
|
||||||
|
```
|
||||||
|
信号 = Sign(过去N日累计收益率)
|
||||||
|
持仓 = 信号 × 权重(波动率倒数)
|
||||||
|
收益 = 持仓 × 未来收益率
|
||||||
|
```
|
||||||
|
|
||||||
|
**实证结果**:
|
||||||
|
- 时间序列动量在所有资产类别中显著
|
||||||
|
- 最优回看窗口:12个月
|
||||||
|
- 持仓周期:1个月
|
||||||
|
- 年化Sharpe Ratio:约1.0
|
||||||
|
|
||||||
|
### 4.2 ETF轮动策略的业界实践
|
||||||
|
|
||||||
|
**经典SPY-TLT-EEM模型**(Quantified Strategies):
|
||||||
|
|
||||||
|
策略配置:
|
||||||
|
- 基础池:SPY(美股)、TLT(美债)、EEM(新兴市场)
|
||||||
|
- 信号:过去1月收益率排名
|
||||||
|
- 持仓:持有排名第一的ETF
|
||||||
|
|
||||||
|
**Global Market Rotation Strategy**(41.4%年化):
|
||||||
|
|
||||||
|
策略配置:
|
||||||
|
- 基础池:6只全球ETF
|
||||||
|
- 调仓周期:月度
|
||||||
|
- 回测期间:2003年至今
|
||||||
|
- 年化收益:41.4%
|
||||||
|
|
||||||
|
### 4.3 中国A股动量效应研究
|
||||||
|
|
||||||
|
**券商金工研报共识**:
|
||||||
|
|
||||||
|
| 发现 | 内容 | 来源 |
|
||||||
|
|-----|------|-----|
|
||||||
|
| **短期动量有效** | 1-3月窗口动量效应显著,长期动量效果弱化 | 华泰金工 |
|
||||||
|
| **行业轮动频繁** | A股行业热点切换快,年度收益排名变化大 | 东方证券 |
|
||||||
|
| **残差动量优越** | 传统动量因子2024年失效,残差动量表现优异 | 华泰金工2026 |
|
||||||
|
| **成长风格敏感** | 时序动量对成长、小盘风格择时效果更好 | 招商金工 |
|
||||||
|
|
||||||
|
**A股特殊性**:
|
||||||
|
- 散户主导市场,情绪波动大
|
||||||
|
- 行业政策驱动强,板块轮动明显
|
||||||
|
- 动量窗口较短(最优1-3月 vs 美股12月)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 分散化选股的理论依据
|
||||||
|
|
||||||
|
### 5.1 Modern Portfolio Theory (Markowitz, 1952)
|
||||||
|
|
||||||
|
**核心定理**:
|
||||||
|
|
||||||
|
在给定风险水平下,分散化投资组合可获得更高预期收益:
|
||||||
|
|
||||||
|
```
|
||||||
|
组合收益 = Σ w_i × E(R_i)
|
||||||
|
组合方差 = Σ Σ w_i × w_j × σ_i × σ_j × ρ_ij
|
||||||
|
```
|
||||||
|
|
||||||
|
**分散化效应**:
|
||||||
|
- 资产间相关性ρ越低,组合方差越小
|
||||||
|
- 不同资产类别相关性通常低于同类别资产
|
||||||
|
- 跨大类分散可显著降低风险
|
||||||
|
|
||||||
|
### 5.2 跨大类分散化的经济学意义
|
||||||
|
|
||||||
|
**本策略的diversified模式**:
|
||||||
|
|
||||||
|
```
|
||||||
|
Step 1: 每大类(A/US/JP/EU/HK/COMMODITY/BOND)选Top1冠军
|
||||||
|
Step 2: 从7个冠军中按得分排序选Top3
|
||||||
|
结果: 持仓必然跨越3个不同大类
|
||||||
|
```
|
||||||
|
|
||||||
|
**理论优势**:
|
||||||
|
|
||||||
|
| 场景 | 风险暴露 | 预期效果 |
|
||||||
|
|-----|---------|---------|
|
||||||
|
| **单一市场集中** | 高单一经济体风险 | 牛市高收益,熊市重创 |
|
||||||
|
| **大类分散** | 分散到多个经济体/资产类别 | 熊市对冲,稳健收益 |
|
||||||
|
|
||||||
|
**实证验证**:
|
||||||
|
|
||||||
|
本策略的A/B测试显示:
|
||||||
|
- diversified=true: CAGR 46.45%, MaxDD -17.33%
|
||||||
|
- diversified=false: CAGR 44.19%, MaxDD -18.12%
|
||||||
|
- **2022年差异关键**:俄乌战争期间商品集中持仓导致false模式大回撤
|
||||||
|
|
||||||
|
### 5.3 Risk Parity思想
|
||||||
|
|
||||||
|
**相关性分配而非市值权重**:
|
||||||
|
|
||||||
|
传统市值加权导致美股占比过高(约50%),Risk Parity强调按风险贡献分配:
|
||||||
|
|
||||||
|
- 本策略采用等权(33%)而非市值加权
|
||||||
|
- 等权在分散模式下隐含Risk Parity精神
|
||||||
|
- 低相关性资产等权可有效降低组合波动
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 动量崩盘风险与风险管理
|
||||||
|
|
||||||
|
### 6.1 动量崩盘现象
|
||||||
|
|
||||||
|
**Barroso & Santa-Clara (2015)**:
|
||||||
|
|
||||||
|
动量策略在特定时期出现灾难性回撤:
|
||||||
|
|
||||||
|
> "Momentum crashes are predictable and occur in rebounding markets after long bear markets."
|
||||||
|
|
||||||
|
**典型崩盘时期**:
|
||||||
|
- 2009年金融危机后反弹期:动量策略亏损超50%
|
||||||
|
- 动量策略在市场反转时最脆弱
|
||||||
|
|
||||||
|
### 6.2 崩盘风险管理方法
|
||||||
|
|
||||||
|
| 方法 | 机制 | 代表文献 |
|
||||||
|
|-----|------|---------|
|
||||||
|
| **波动率调整** | 高波动期降低仓位 | Barroso & Santa-Clara (2015) |
|
||||||
|
| **动态信号** | ATR动态调整回看窗口 | 本策略auto_day机制 |
|
||||||
|
| **崩盘过滤** | 检测短期暴跌并清零得分 | 本策略crash filter |
|
||||||
|
| **Idiosyncratic动量** | 使用残差动量而非原始动量 | Blitz et al. (2011) |
|
||||||
|
|
||||||
|
**本策略的崩盘过滤机制**:
|
||||||
|
|
||||||
|
```
|
||||||
|
条件1: 连续3天中任一天跌幅>5%
|
||||||
|
条件2: 连续3天下跌且累计跌幅>5%
|
||||||
|
满足任一条件 → 得分清零 → 不参与选股
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 最大回撤控制
|
||||||
|
|
||||||
|
**Drawdown-based风险管理**:
|
||||||
|
|
||||||
|
- 本策略实证MaxDD: -17.33%
|
||||||
|
- Calmar Ratio: 2.68(优秀水平)
|
||||||
|
- 最大回撤发生在2020年疫情冲击期
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 待解决问题与研究前沿
|
||||||
|
|
||||||
|
### 7.1 学术前沿问题
|
||||||
|
|
||||||
|
| 问题 | 内容 | 当前进展 |
|
||||||
|
|-----|------|---------|
|
||||||
|
| **动量起源之谜** | 动量是风险补偿还是行为偏差? | 无共识,多解释并存 |
|
||||||
|
| **动量因子标准化** | 何种动量定义最优? | 加权动量vs简单动量各有优劣 |
|
||||||
|
| **动态窗口机制** | 如何自适应调整回看期? | ATR方法存在但效果存疑 |
|
||||||
|
| **跨市场数据对齐** | 不同交易日历如何处理? | Ffill方法存在时序偏差风险 |
|
||||||
|
| **因子衰减** | 动量效应是否在衰减? | 2024年A股传统动量失效 |
|
||||||
|
|
||||||
|
### 7.2 实践挑战
|
||||||
|
|
||||||
|
| 挑战 | 内容 | 解决方案探索 |
|
||||||
|
|-----|------|-------------|
|
||||||
|
| **前视偏差(Look-ahead Bias)** | 回测使用未来信息 | 动态上市池重建(本策略已实现) |
|
||||||
|
| **溢价率风险** | 跨境ETF高溢价买入 | 溢价过滤机制 |
|
||||||
|
| **调仓成本** | 高频调仓侵蚀收益 | 阈值控制+最低持仓期 |
|
||||||
|
| **流动性约束** | 小盘ETF交易成本高 | 选择高流动性ETF |
|
||||||
|
| **数据质量** | 多源数据对齐与缺失 | 混合数据源+缺失剔除 |
|
||||||
|
|
||||||
|
### 7.3 未来研究方向
|
||||||
|
|
||||||
|
1. **多因子融合**:动量+价值+质量因子组合
|
||||||
|
2. **机器学习增强**:非线性动量信号识别
|
||||||
|
3. **实时风险控制**:在线波动率估计与仓位调整
|
||||||
|
4. **A股特色因子**:政策驱动、资金流向、情绪因子
|
||||||
|
5. **宏观周期对齐**:动量策略与经济周期匹配
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 本策略的学术对标
|
||||||
|
|
||||||
|
### 8.1 与经典研究的对比
|
||||||
|
|
||||||
|
| 维度 | Jegadeesh-Titman (1993) | Moskowitz et al. (2012) | 本策略V2 |
|
||||||
|
|-----|------------------------|------------------------|---------|
|
||||||
|
| **动量类型** | 截面动量 | 时间序列动量 | 截面动量 |
|
||||||
|
| **因子定义** | N日收益率 | Sign(收益率) | 加权线性回归动量 |
|
||||||
|
| **资产范围** | 美股个股 | 58种期货 | 11只全球ETF信号源 |
|
||||||
|
| **选股模式** | Winner-Loser对冲 | 单边持仓 | Top3等权 |
|
||||||
|
| **分散机制** | 无 | 无 | 跨大类强制分散 |
|
||||||
|
| **崩盘保护** | 无 | 无 | 崩盘过滤+阈值控制 |
|
||||||
|
|
||||||
|
### 8.2 创新点总结
|
||||||
|
|
||||||
|
| 创新点 | 学术意义 |
|
||||||
|
|-------|---------|
|
||||||
|
| **加权动量因子** | 近期权重更高,对趋势变化更敏感 |
|
||||||
|
| **跨大类分散化** | 结合MPT理论,强制大类分散 |
|
||||||
|
| **期货信号-ETF交易分离** | 商品用期货信号,ETF交易,信号纯粹 |
|
||||||
|
| **崩盘过滤机制** | 行为金融启发的风险控制 |
|
||||||
|
| **双轨数据架构** | 指数信号+ETF交易分离 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 结论
|
||||||
|
|
||||||
|
基于动量因子的跨市场ETF轮动策略是资产定价、资产配置、行为金融学三大领域的交叉研究主题。动量效应作为最持久的市场异象,其理论基础涵盖行为金融学(反应不足与反应过度)、风险补偿理论、流动性理论等多重解释。
|
||||||
|
|
||||||
|
跨市场动量策略的核心方法论源自Jegadeesh & Titman (1993)的截面动量与Moskowitz et al. (2012)的时间序列动量。实证证据表明,动量效应在股票、债券、商品、外汇等所有资产类别中普遍存在(Asness et al., 2013)。
|
||||||
|
|
||||||
|
分散化选股机制的理论依据来自Markowitz (1952)的Modern Portfolio Theory,跨大类资产低相关性特征使分散持仓能有效降低组合波动。本策略的diversified模式实证效果显著优于纯Top N模式,尤其在2022年市场危机期间展现出对冲能力。
|
||||||
|
|
||||||
|
当前研究的待解决问题聚焦于动量起源之谜、因子标准化、动态窗口机制、跨市场数据对齐、以及因子衰减现象。实践挑战包括前视偏差控制、溢价风险管理、调仓成本控制等。
|
||||||
|
|
||||||
|
本策略V2在经典研究基础上进行了多项创新:加权动量因子提高趋势敏感性,跨大类分散化结合MPT理论,崩盘过滤机制借鉴行为金融学洞察,期货信号-ETF交易分离保证信号纯粹性。这些创新使策略在保持学术严谨性的同时,获得了优秀的实证表现(CAGR 46.42%, Sharpe 2.22, Calmar 2.68)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 参考文献
|
||||||
|
|
||||||
|
### 经典学术论文(APA格式)
|
||||||
|
|
||||||
|
Asness, C. S., Moskowitz, T. J., & Pedersen, L. H. (2013). Value and momentum everywhere. *Journal of Finance, 68*(3), 925-985.
|
||||||
|
|
||||||
|
Barberis, N., Shleifer, A., & Vishny, R. (1998). A model of investor sentiment. *Journal of Financial Economics, 49*(3), 307-343.
|
||||||
|
|
||||||
|
Barroso, P., & Santa-Clara, P. (2015). Momentum has its moments. *Journal of Financial Economics, 116*(1), 111-120.
|
||||||
|
|
||||||
|
Carhart, M. M. (1997). On persistence in mutual fund performance. *Journal of Finance, 52*(1), 57-82.
|
||||||
|
|
||||||
|
Hong, H., & Stein, J. C. (2007). Disagreement and the stock market. *Journal of Economic Perspectives, 21*(2), 109-128.
|
||||||
|
|
||||||
|
Jegadeesh, N., & Titman, S. (1993). Returns to buying winners and selling losers: Implications for stock market efficiency. *Journal of Finance, 48*(1), 65-91.
|
||||||
|
|
||||||
|
Jegadeesh, N., & Titman, S. (2001). Profitability of momentum strategies: An evaluation of alternative explanations. *Journal of Finance, 56*(2), 699-720.
|
||||||
|
|
||||||
|
Markowitz, H. (1952). Portfolio selection. *Journal of Finance, 7*(1), 77-91.
|
||||||
|
|
||||||
|
Moskowitz, T. J., Ooi, Y. H., & Pedersen, L. H. (2012). Time series momentum. *Journal of Financial Economics, 104*(2), 228-250.
|
||||||
|
|
||||||
|
### 业界研究与策略报告
|
||||||
|
|
||||||
|
AQR Capital Management. (2013). Value and momentum everywhere. *AQR White Paper*.
|
||||||
|
|
||||||
|
Quantified Strategies. (2024). ETF rotation strategy for high returns (backtested). *Quantified Strategies Blog*.
|
||||||
|
|
||||||
|
QuantPedia. (2024). Sector momentum - rotational system. *Quantpedia Strategy Database*.
|
||||||
|
|
||||||
|
Robeco. (2023). Quant chart: Taming momentum crashes. *Robeco Insights*.
|
||||||
|
|
||||||
|
### 中国券商金工研报
|
||||||
|
|
||||||
|
华泰证券. (2026). 金工:量化行业轮动的"崎岖之路". 华泰证券研究报告.
|
||||||
|
|
||||||
|
东方证券. (2019). 因子选股系列之五十:A股行业内选股分析总结. 东方证券研究报告.
|
||||||
|
|
||||||
|
招商证券. (2024). 动量因子在大类资产和行业轮动策略运用. 招商证券研究报告.
|
||||||
|
|
||||||
|
### 数据来源与工具
|
||||||
|
|
||||||
|
Tushare Pro API. (2024). 中国A股金融数据接口. https://tushare.pro
|
||||||
|
|
||||||
|
YFinance. (2024). Yahoo Finance历史数据接口. https://github.com/ranaroussi/yfinance
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 附录
|
||||||
|
|
||||||
|
### A. 动量因子计算公式对比
|
||||||
|
|
||||||
|
| 因子类型 | 公式 | 特点 |
|
||||||
|
|---------|------|-----|
|
||||||
|
| **简单动量** | (P_t / P_{t-N} - 1) | 简单,但忽略趋势稳定性 |
|
||||||
|
| **斜率×R²动量** | slope × R² × 10000 | 捕捉趋势强度与稳定性 |
|
||||||
|
| **加权动量** | annualized_return × R²(近期权重更高) | 对趋势变化敏感 |
|
||||||
|
|
||||||
|
### B. 本策略V2配置摘要
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
候选池: 11只(7大类)
|
||||||
|
因子类型: weighted_momentum
|
||||||
|
窗口天数: 25
|
||||||
|
选股模式: diversified(跨大类)
|
||||||
|
持仓数量: 3只等权
|
||||||
|
调仓周期: 最低1天
|
||||||
|
交易成本: 0.1%
|
||||||
|
溢价控制: 港股/美股10%阈值过滤
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*AI声明:本报告使用AI辅助研究工具(deep-research skill)进行文献搜索与整合。所有引用文献均经过来源验证。报告内容仅供学术参考,不构成投资建议。*
|
||||||
|
|
||||||
|
*文档版本:1.0*
|
||||||
|
*生成时间:2026-04-30*
|
||||||
109
fetch_159516_nav.py
Normal file
109
fetch_159516_nav.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
获取159516 ETF净值数据
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pandas as pd
|
||||||
|
import tushare as ts
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
# 设置Tushare token
|
||||||
|
def get_tushare_token():
|
||||||
|
# 首先尝试从环境变量获取
|
||||||
|
token = os.environ.get("TUSHARE_TOKEN")
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
|
|
||||||
|
# 尝试从.env文件获取
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
token = os.environ.get("TUSHARE_TOKEN")
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 手动读取.env文件
|
||||||
|
env_path = os.path.join(os.path.dirname(__file__), '.env')
|
||||||
|
if os.path.exists(env_path):
|
||||||
|
with open(env_path, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if line.startswith('TUSHARE_TOKEN='):
|
||||||
|
token = line.strip().split('=', 1)[1].strip().strip('"').strip("'")
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
|
|
||||||
|
raise ValueError("请设置 TUSHARE_TOKEN 环境变量或在.env文件中配置")
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_etf_nav(etf_code="159516.SZ", days=30):
|
||||||
|
"""
|
||||||
|
获取ETF净值数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
etf_code: ETF代码,如 "159516.SZ"
|
||||||
|
days: 获取天数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
DataFrame: 包含日期和净值
|
||||||
|
"""
|
||||||
|
pro = ts.pro_api(get_tushare_token())
|
||||||
|
|
||||||
|
# 计算日期范围
|
||||||
|
end_date = datetime.now()
|
||||||
|
start_date = end_date - timedelta(days=days + 5)
|
||||||
|
|
||||||
|
start_str = start_date.strftime('%Y%m%d')
|
||||||
|
end_str = end_date.strftime('%Y%m%d')
|
||||||
|
|
||||||
|
# 转换代码格式 (tushare使用.SH而不是.SS)
|
||||||
|
ts_code = etf_code.replace(".SS", ".SH")
|
||||||
|
|
||||||
|
print(f"获取 {etf_code} 净值数据...")
|
||||||
|
print(f"日期范围: {start_str} ~ {end_str}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 获取ETF净值数据
|
||||||
|
nav_df = pro.fund_nav(
|
||||||
|
ts_code=ts_code,
|
||||||
|
start_date=start_str,
|
||||||
|
end_date=end_str
|
||||||
|
)
|
||||||
|
|
||||||
|
if nav_df is None or len(nav_df) == 0:
|
||||||
|
print("未获取到净值数据")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 排序并处理数据
|
||||||
|
nav_df = nav_df.sort_values('nav_date')
|
||||||
|
|
||||||
|
# 转换日期格式
|
||||||
|
nav_df['date'] = pd.to_datetime(nav_df['nav_date'])
|
||||||
|
nav_df = nav_df.set_index('date')
|
||||||
|
|
||||||
|
print(f"\n获取到 {len(nav_df)} 条净值数据")
|
||||||
|
print(f"最新净值日期: {nav_df.index.max().strftime('%Y-%m-%d')}")
|
||||||
|
print(f"最新净值: {nav_df['unit_nav'].iloc[-1]}")
|
||||||
|
|
||||||
|
# 显示最近10条数据
|
||||||
|
print(f"\n最近10条净值数据:")
|
||||||
|
print(nav_df[['unit_nav']].tail(10).to_string())
|
||||||
|
|
||||||
|
return nav_df
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"获取净值数据失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 获取159516的净值数据
|
||||||
|
result = fetch_etf_nav("159516.SZ", days=30)
|
||||||
|
|
||||||
|
if result is not None:
|
||||||
|
# 保存到CSV文件
|
||||||
|
output_file = "159516_nav_data.csv"
|
||||||
|
result[['unit_nav']].to_csv(output_file)
|
||||||
|
print(f"\n数据已保存到: {output_file}")
|
||||||
183
fetch_159930.py
Normal file
183
fetch_159930.py
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
获取159930 ETF最新10天的收盘价、净值并计算溢价率
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pandas as pd
|
||||||
|
import tushare as ts
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
# 设置Tushare token
|
||||||
|
def get_tushare_token():
|
||||||
|
# 首先尝试从环境变量获取
|
||||||
|
token = os.environ.get("TUSHARE_TOKEN")
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
|
|
||||||
|
# 尝试从.env文件获取
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
token = os.environ.get("TUSHARE_TOKEN")
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 手动读取.env文件
|
||||||
|
env_path = os.path.join(os.path.dirname(__file__), '.env')
|
||||||
|
if os.path.exists(env_path):
|
||||||
|
with open(env_path, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if line.startswith('TUSHARE_TOKEN='):
|
||||||
|
token = line.strip().split('=', 1)[1].strip().strip('"').strip("'")
|
||||||
|
if token:
|
||||||
|
return token
|
||||||
|
|
||||||
|
raise ValueError("请设置 TUSHARE_TOKEN 环境变量或在.env文件中配置")
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_etf_data(etf_code: str, days: int = 10):
|
||||||
|
"""
|
||||||
|
获取ETF最新N天的价格、净值数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
etf_code: ETF代码,如 "159930.SZ"
|
||||||
|
days: 获取天数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
DataFrame: 包含日期、收盘价、净值、溢价率
|
||||||
|
"""
|
||||||
|
pro = ts.pro_api(get_tushare_token())
|
||||||
|
|
||||||
|
# 计算日期范围(多取几天确保有足够数据)
|
||||||
|
end_date = datetime.now()
|
||||||
|
start_date = end_date - timedelta(days=days + 5)
|
||||||
|
|
||||||
|
start_str = start_date.strftime('%Y%m%d')
|
||||||
|
end_str = end_date.strftime('%Y%m%d')
|
||||||
|
|
||||||
|
# 转换代码格式
|
||||||
|
ts_code = etf_code.replace(".SS", ".SH")
|
||||||
|
|
||||||
|
print(f"获取 {etf_code} 数据...")
|
||||||
|
print(f"日期范围: {start_str} ~ {end_str}")
|
||||||
|
|
||||||
|
# 1. 获取ETF价格数据(fund_daily接口)
|
||||||
|
print("\n1. 获取ETF价格数据...")
|
||||||
|
try:
|
||||||
|
price_df = pro.fund_daily(
|
||||||
|
ts_code=ts_code,
|
||||||
|
start_date=start_str,
|
||||||
|
end_date=end_str
|
||||||
|
)
|
||||||
|
if price_df is not None and len(price_df) > 0:
|
||||||
|
price_df = price_df.sort_values('trade_date')
|
||||||
|
print(f" 获取到 {len(price_df)} 条价格数据")
|
||||||
|
print(f" 最新日期: {price_df['trade_date'].max()}")
|
||||||
|
else:
|
||||||
|
print(" 未获取到价格数据")
|
||||||
|
price_df = None
|
||||||
|
except Exception as e:
|
||||||
|
print(f" 获取价格数据失败: {e}")
|
||||||
|
price_df = None
|
||||||
|
|
||||||
|
# 2. 获取ETF净值数据(fund_nav接口)
|
||||||
|
print("\n2. 获取ETF净值数据...")
|
||||||
|
try:
|
||||||
|
# 净值通常滞后,多取一天
|
||||||
|
nav_end_date = end_date + timedelta(days=1)
|
||||||
|
nav_end_str = nav_end_date.strftime('%Y%m%d')
|
||||||
|
|
||||||
|
nav_df = pro.fund_nav(
|
||||||
|
ts_code=ts_code,
|
||||||
|
start_date=start_str,
|
||||||
|
end_date=nav_end_str
|
||||||
|
)
|
||||||
|
if nav_df is not None and len(nav_df) > 0:
|
||||||
|
nav_df = nav_df.sort_values('nav_date')
|
||||||
|
print(f" 获取到 {len(nav_df)} 条净值数据")
|
||||||
|
print(f" 最新日期: {nav_df['nav_date'].max()}")
|
||||||
|
else:
|
||||||
|
print(" 未获取到净值数据")
|
||||||
|
nav_df = None
|
||||||
|
except Exception as e:
|
||||||
|
print(f" 获取净值数据失败: {e}")
|
||||||
|
nav_df = None
|
||||||
|
|
||||||
|
# 3. 合并数据并计算溢价率
|
||||||
|
print("\n3. 合并数据并计算溢价率...")
|
||||||
|
|
||||||
|
if price_df is None:
|
||||||
|
print("错误: 没有价格数据")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 准备价格数据
|
||||||
|
price_df['date'] = pd.to_datetime(price_df['trade_date'])
|
||||||
|
price_df = price_df.set_index('date')
|
||||||
|
price_series = price_df['close']
|
||||||
|
|
||||||
|
# 准备净值数据
|
||||||
|
if nav_df is not None:
|
||||||
|
nav_df['date'] = pd.to_datetime(nav_df['nav_date'])
|
||||||
|
nav_df = nav_df.set_index('date')
|
||||||
|
nav_series = nav_df['unit_nav']
|
||||||
|
else:
|
||||||
|
nav_series = pd.Series()
|
||||||
|
|
||||||
|
# 创建结果DataFrame
|
||||||
|
result = pd.DataFrame({
|
||||||
|
'收盘价': price_series
|
||||||
|
})
|
||||||
|
|
||||||
|
# 对齐净值数据(按日期)
|
||||||
|
result = result.join(nav_series.rename('净值'), how='left')
|
||||||
|
|
||||||
|
# 计算溢价率
|
||||||
|
result['溢价率'] = (result['收盘价'] - result['净值']) / result['净值'] * 100
|
||||||
|
|
||||||
|
# 取最新N天
|
||||||
|
result = result.tail(days)
|
||||||
|
|
||||||
|
# 格式化输出
|
||||||
|
result['收盘价'] = result['收盘价'].round(3)
|
||||||
|
result['净值'] = result['净值'].round(3)
|
||||||
|
result['溢价率'] = result['溢价率'].round(2)
|
||||||
|
|
||||||
|
# 重置索引,将日期作为列
|
||||||
|
result = result.reset_index()
|
||||||
|
result['日期'] = result['date'].dt.strftime('%Y-%m-%d')
|
||||||
|
result = result[['日期', '收盘价', '净值', '溢价率']]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""主函数"""
|
||||||
|
etf_code = "159930.SZ"
|
||||||
|
days = 10
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"ETF: {etf_code} (中证能源ETF)")
|
||||||
|
print(f"获取最近 {days} 天数据")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
df = fetch_etf_data(etf_code, days)
|
||||||
|
|
||||||
|
if df is not None and len(df) > 0:
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("结果表格:")
|
||||||
|
print("=" * 60)
|
||||||
|
print(df.to_string(index=False))
|
||||||
|
|
||||||
|
# 保存到CSV
|
||||||
|
output_file = f"{etf_code.replace('.', '_')}_latest_{days}days.csv"
|
||||||
|
df.to_csv(output_file, index=False, encoding='utf-8-sig')
|
||||||
|
print(f"\n数据已保存到: {output_file}")
|
||||||
|
else:
|
||||||
|
print("\n获取数据失败")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
2
tests/experiments/__init__.py
Normal file
2
tests/experiments/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# 实验脚本目录
|
||||||
|
# 存放策略研究相关的A/B测试、对比实验等脚本
|
||||||
187
tests/experiments/ab_test_ndx_vs_spx.py
Normal file
187
tests/experiments/ab_test_ndx_vs_spx.py
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
"""
|
||||||
|
A/B测试:纳指100 vs 标普500 替换对比
|
||||||
|
对比:
|
||||||
|
- A组(对照组):纳指100作为美股大类代表
|
||||||
|
- B组(实验组):标普500替换纳指100作为美股大类代表
|
||||||
|
|
||||||
|
核心问题:替换后对策略绩效的影响(无类内竞争)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from strategies.rotation.engine import RotationStrategy
|
||||||
|
import pandas as pd
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
def create_config_replace_ndx_with_spx(base_config: dict) -> dict:
|
||||||
|
"""将纳指100替换为标普500"""
|
||||||
|
config = base_config.copy()
|
||||||
|
config['code_list'] = base_config['code_list'].copy()
|
||||||
|
|
||||||
|
# 移除纳指100
|
||||||
|
if 'NDX' in config['code_list']:
|
||||||
|
del config['code_list']['NDX']
|
||||||
|
|
||||||
|
# 添加标普500(替换纳指100)
|
||||||
|
config['code_list']['SPX'] = {
|
||||||
|
'name': '标普500',
|
||||||
|
'etf': '513500.SH',
|
||||||
|
'market': 'US'
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def run_backtest(config: dict, label: str) -> dict:
|
||||||
|
"""运行回测并返回关键指标"""
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" {label}")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
|
||||||
|
strategy = RotationStrategy(config)
|
||||||
|
result = strategy.run()
|
||||||
|
|
||||||
|
if result is None or len(result) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 计算指标
|
||||||
|
strategy_nav = result['轮动策略净值']
|
||||||
|
strategy_ret = result['轮动策略日收益率']
|
||||||
|
|
||||||
|
total_return = strategy_nav.iloc[-1] - 1
|
||||||
|
days = len(result)
|
||||||
|
years = days / 250
|
||||||
|
cagr = (strategy_nav.iloc[-1] ** (1/years)) - 1
|
||||||
|
excess_ret = strategy_ret.mean() * 250
|
||||||
|
vol = strategy_ret.std() * (250 ** 0.5)
|
||||||
|
sharpe = excess_ret / vol if vol > 0 else 0
|
||||||
|
rolling_max = strategy_nav.cummax()
|
||||||
|
drawdown = (strategy_nav - rolling_max) / rolling_max
|
||||||
|
max_dd = drawdown.min()
|
||||||
|
calmar = cagr / abs(max_dd) if max_dd < 0 else 0
|
||||||
|
win_rate = (strategy_ret > 0).sum() / len(strategy_ret)
|
||||||
|
|
||||||
|
metrics = {
|
||||||
|
'label': label,
|
||||||
|
'美股标的': '纳指100' if 'NDX' in config['code_list'] else '标普500',
|
||||||
|
'累计收益': total_return,
|
||||||
|
'CAGR': cagr,
|
||||||
|
'Sharpe': sharpe,
|
||||||
|
'MaxDD': max_dd,
|
||||||
|
'Calmar': calmar,
|
||||||
|
'日胜率': win_rate,
|
||||||
|
}
|
||||||
|
|
||||||
|
print(f"\n美股代表: {metrics['美股标的']}")
|
||||||
|
print(f"累计收益: {metrics['累计收益']:.2%}")
|
||||||
|
print(f"CAGR: {metrics['CAGR']:.2%}")
|
||||||
|
print(f"Sharpe: {metrics['Sharpe']:.2f}")
|
||||||
|
print(f"MaxDD: {metrics['MaxDD']:.2%}")
|
||||||
|
print(f"Calmar: {metrics['Calmar']:.2f}")
|
||||||
|
print(f"日胜率: {metrics['日胜率']:.2%}")
|
||||||
|
|
||||||
|
return metrics
|
||||||
|
|
||||||
|
|
||||||
|
def compare_results(a_metrics: dict, b_metrics: dict):
|
||||||
|
"""对比两组结果"""
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" 对比结果")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
|
||||||
|
print(f"\n{'指标':<15} {'A组(纳指100)':<15} {'B组(标普500)':<15} {'差异':<15}")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
metrics_keys = ['美股标的', '累计收益', 'CAGR', 'Sharpe', 'MaxDD', 'Calmar', '日胜率']
|
||||||
|
|
||||||
|
for key in metrics_keys:
|
||||||
|
a_val = a_metrics.get(key, 0)
|
||||||
|
b_val = b_metrics.get(key, 0)
|
||||||
|
|
||||||
|
if key == '美股标的':
|
||||||
|
print(f"{key:<15} {a_val:<15} {b_val:<15} {'替换':<15}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
diff = b_val - a_val
|
||||||
|
if key in ['累计收益', 'CAGR', 'MaxDD', '日胜率']:
|
||||||
|
a_str = f"{a_val:.2%}"
|
||||||
|
b_str = f"{b_val:.2%}"
|
||||||
|
diff_str = f"{diff*100:+.2f}%"
|
||||||
|
else:
|
||||||
|
a_str = f"{a_val:.2f}"
|
||||||
|
b_str = f"{b_val:.2f}"
|
||||||
|
diff_str = f"{diff:+.2f}"
|
||||||
|
|
||||||
|
print(f"{key:<15} {a_str:<15} {b_str:<15} {diff_str:<15}")
|
||||||
|
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
print(f"\n【关键发现】")
|
||||||
|
print(f"纳指100 → 标普500 替换效果:")
|
||||||
|
|
||||||
|
if b_metrics['CAGR'] < a_metrics['CAGR']:
|
||||||
|
print(f" - CAGR下降 {a_metrics['CAGR'] - b_metrics['CAGR']:.2%}")
|
||||||
|
print(f" → 标普500动量信号可能不如纳指强")
|
||||||
|
|
||||||
|
if b_metrics['MaxDD'] > a_metrics['MaxDD']: # 注意MaxDD是负数
|
||||||
|
print(f" - MaxDD改善 {b_metrics['MaxDD'] - a_metrics['MaxDD']:.2%}")
|
||||||
|
print(f" → 标普500更稳定,回撤更小")
|
||||||
|
|
||||||
|
if b_metrics['Sharpe'] > a_metrics['Sharpe']:
|
||||||
|
print(f" - Sharpe改善 {b_metrics['Sharpe'] - a_metrics['Sharpe']:.2f}")
|
||||||
|
print(f" → 标普500风险调整后收益更优")
|
||||||
|
elif b_metrics['Sharpe'] < a_metrics['Sharpe']:
|
||||||
|
print(f" - Sharpe下降 {b_metrics['Sharpe'] - a_metrics['Sharpe']:.2f}")
|
||||||
|
print(f" → 纳指100风险调整后收益更优")
|
||||||
|
|
||||||
|
print(f"\n【策略建议】")
|
||||||
|
if b_metrics['累计收益'] < a_metrics['累计收益'] * 0.9:
|
||||||
|
print(f" 建议:保持纳指100(成长风格更适合动量策略)")
|
||||||
|
elif b_metrics['Sharpe'] > a_metrics['Sharpe']:
|
||||||
|
print(f" 建议:考虑标普500(更稳定、风险调整收益更优)")
|
||||||
|
else:
|
||||||
|
print(f" 建议:保持纳指100(累计收益更高)")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""主函数"""
|
||||||
|
# 加载基础配置
|
||||||
|
config_path = Path(__file__).parent.parent / 'config' / 'strategies' / 'rotation.yaml'
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
base_config = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# 添加 end_date
|
||||||
|
from datetime import datetime
|
||||||
|
base_config['end_date'] = datetime.now().strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" A/B测试:纳指100 vs 标普500 替换对比")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
print(f"\n研究问题:")
|
||||||
|
print(f" - 将美股大类代表从纳指100替换为标普500")
|
||||||
|
print(f" - 无类内竞争(每大类还是1只)")
|
||||||
|
print(f" - 评估标的特性变化对绩效的影响")
|
||||||
|
|
||||||
|
# A组:纳指100(当前配置)
|
||||||
|
a_metrics = run_backtest(base_config, "A组: 纳指100作为美股代表")
|
||||||
|
|
||||||
|
# B组:标普500替换纳指100
|
||||||
|
config_replace = create_config_replace_ndx_with_spx(base_config)
|
||||||
|
b_metrics = run_backtest(config_replace, "B组: 标普500替换纳指100")
|
||||||
|
|
||||||
|
# 对比
|
||||||
|
if a_metrics and b_metrics:
|
||||||
|
compare_results(a_metrics, b_metrics)
|
||||||
|
|
||||||
|
# 保存结果
|
||||||
|
results_df = pd.DataFrame([a_metrics, b_metrics])
|
||||||
|
results_path = Path(__file__).parent.parent / 'results' / 'ab_test_ndx_vs_spx.csv'
|
||||||
|
results_df.to_csv(results_path, index=False)
|
||||||
|
print(f"\n对比结果已保存: {results_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
183
tests/experiments/ab_test_spx.py
Normal file
183
tests/experiments/ab_test_spx.py
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
"""
|
||||||
|
A/B测试:添加标普500对轮动策略的影响
|
||||||
|
对比:
|
||||||
|
- A组(对照组):当前11只标的配置
|
||||||
|
- B组(实验组):添加标普500后的12只标的配置
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
||||||
|
from strategies.rotation.engine import RotationStrategy
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
|
||||||
|
def create_config_with_spx(base_config: dict) -> dict:
|
||||||
|
"""在基础配置上添加标普500"""
|
||||||
|
config = base_config.copy()
|
||||||
|
config['code_list'] = base_config['code_list'].copy()
|
||||||
|
|
||||||
|
# 添加标普500(美股大类内)
|
||||||
|
config['code_list']['SPX'] = {
|
||||||
|
'name': '标普500',
|
||||||
|
'etf': '513500.SH',
|
||||||
|
'market': 'US' # 与纳指100同属美股大类
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def run_backtest(config: dict, label: str) -> dict:
|
||||||
|
"""运行回测并返回关键指标"""
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" {label}")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
|
||||||
|
strategy = RotationStrategy(config)
|
||||||
|
result = strategy.run() # result 是 DataFrame
|
||||||
|
|
||||||
|
if result is None or len(result) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 从 DataFrame 中直接计算指标
|
||||||
|
strategy_nav = result['轮动策略净值']
|
||||||
|
strategy_ret = result['轮动策略日收益率']
|
||||||
|
benchmark_nav = result['基准净值']
|
||||||
|
benchmark_ret = result['基准日收益率']
|
||||||
|
|
||||||
|
# 累计收益
|
||||||
|
total_return = strategy_nav.iloc[-1] - 1
|
||||||
|
|
||||||
|
# CAGR (交易日口径)
|
||||||
|
days = len(result)
|
||||||
|
years = days / 250
|
||||||
|
cagr = (strategy_nav.iloc[-1] ** (1/years)) - 1
|
||||||
|
|
||||||
|
# Sharpe
|
||||||
|
excess_ret = strategy_ret.mean() * 250 # 年化收益
|
||||||
|
vol = strategy_ret.std() * (250 ** 0.5) # 年化波动
|
||||||
|
sharpe = excess_ret / vol if vol > 0 else 0
|
||||||
|
|
||||||
|
# 最大回撤
|
||||||
|
rolling_max = strategy_nav.cummax()
|
||||||
|
drawdown = (strategy_nav - rolling_max) / rolling_max
|
||||||
|
max_dd = drawdown.min()
|
||||||
|
|
||||||
|
# Calmar
|
||||||
|
calmar = cagr / abs(max_dd) if max_dd < 0 else 0
|
||||||
|
|
||||||
|
# 日胜率
|
||||||
|
win_rate = (strategy_ret > 0).sum() / len(strategy_ret)
|
||||||
|
|
||||||
|
# 提取关键指标
|
||||||
|
metrics = {
|
||||||
|
'label': label,
|
||||||
|
'标的数': len(config['code_list']),
|
||||||
|
'累计收益': total_return,
|
||||||
|
'CAGR': cagr,
|
||||||
|
'Sharpe': sharpe,
|
||||||
|
'MaxDD': max_dd,
|
||||||
|
'Calmar': calmar,
|
||||||
|
'日胜率': win_rate,
|
||||||
|
}
|
||||||
|
|
||||||
|
print(f"\n标的池: {len(config['code_list'])}只")
|
||||||
|
print(f"累计收益: {metrics['累计收益']:.2%}")
|
||||||
|
print(f"CAGR: {metrics['CAGR']:.2%}")
|
||||||
|
print(f"Sharpe: {metrics['Sharpe']:.2f}")
|
||||||
|
print(f"MaxDD: {metrics['MaxDD']:.2%}")
|
||||||
|
print(f"Calmar: {metrics['Calmar']:.2f}")
|
||||||
|
print(f"日胜率: {metrics['日胜率']:.2%}")
|
||||||
|
|
||||||
|
return metrics
|
||||||
|
|
||||||
|
|
||||||
|
def compare_results(a_metrics: dict, b_metrics: dict):
|
||||||
|
"""对比两组结果"""
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" 对比结果")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
|
||||||
|
print(f"\n{'指标':<12} {'A组(无SPX)':<15} {'B组(有SPX)':<15} {'差异':<15}")
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
metrics_keys = ['标的数', '累计收益', 'CAGR', 'Sharpe', 'MaxDD', 'Calmar', '日胜率']
|
||||||
|
|
||||||
|
for key in metrics_keys:
|
||||||
|
a_val = a_metrics.get(key, 0)
|
||||||
|
b_val = b_metrics.get(key, 0)
|
||||||
|
|
||||||
|
if key == '标的数':
|
||||||
|
diff = b_val - a_val
|
||||||
|
diff_str = f"+{diff}" if diff > 0 else str(diff)
|
||||||
|
else:
|
||||||
|
diff = b_val - a_val
|
||||||
|
if key in ['累计收益', 'CAGR', 'MaxDD', '日胜率']:
|
||||||
|
diff_str = f"{diff*100:+.2f}%"
|
||||||
|
else:
|
||||||
|
diff_str = f"{diff:+.2f}"
|
||||||
|
|
||||||
|
if key in ['累计收益', 'CAGR', 'MaxDD', '日胜率']:
|
||||||
|
a_str = f"{a_val:.2%}"
|
||||||
|
b_str = f"{b_val:.2%}"
|
||||||
|
else:
|
||||||
|
a_str = str(a_val)
|
||||||
|
b_str = str(b_val)
|
||||||
|
|
||||||
|
print(f"{key:<12} {a_str:<15} {b_str:<15} {diff_str:<15}")
|
||||||
|
|
||||||
|
print("-" * 60)
|
||||||
|
|
||||||
|
# 分析美股大类内部切换情况
|
||||||
|
print(f"\n【关键发现】")
|
||||||
|
print(f"添加标普500后:")
|
||||||
|
print(f" - 美股大类从1只→2只(纳指100 + 标普500)")
|
||||||
|
print(f" - 类内竞争:纳指100 vs 标普500,得分高者代表美股大类")
|
||||||
|
print(f" - 跨类分散不变:美股大类还是只输出1只冠军进入Top3")
|
||||||
|
|
||||||
|
if b_metrics['累计收益'] != a_metrics['累计收益']:
|
||||||
|
print(f" - 累计收益变化:{a_metrics['累计收益']:.2%} → {b_metrics['累计收益']:.2%}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""主函数"""
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
# 加载基础配置
|
||||||
|
config_path = Path(__file__).parent.parent / 'config' / 'strategies' / 'rotation.yaml'
|
||||||
|
with open(config_path, 'r') as f:
|
||||||
|
base_config = yaml.safe_load(f)
|
||||||
|
|
||||||
|
# 添加缺失的 end_date(使用今天日期)
|
||||||
|
from datetime import datetime
|
||||||
|
base_config['end_date'] = datetime.now().strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
print(f"\n{'='*60}")
|
||||||
|
print(f" A/B测试:添加标普500对diversified模式的影响")
|
||||||
|
print(f"{'='*60}")
|
||||||
|
print(f"\n测试假设:")
|
||||||
|
print(f" - diversified=true 模式下,每大类只选1只冠军")
|
||||||
|
print(f" - 添加标普500(同属美股大类)不会增加跨类分散")
|
||||||
|
print(f" - 但可能增加类内切换频率和换手率")
|
||||||
|
|
||||||
|
# A组:当前配置(11只,无标普500)
|
||||||
|
a_metrics = run_backtest(base_config, "A组: 当前配置(11只,无标普500)")
|
||||||
|
|
||||||
|
# B组:添加标普500后的配置(12只)
|
||||||
|
config_with_spx = create_config_with_spx(base_config)
|
||||||
|
b_metrics = run_backtest(config_with_spx, "B组: 添加标普500(12只)")
|
||||||
|
|
||||||
|
# 对比结果
|
||||||
|
if a_metrics and b_metrics:
|
||||||
|
compare_results(a_metrics, b_metrics)
|
||||||
|
|
||||||
|
# 保存对比结果
|
||||||
|
results_df = pd.DataFrame([a_metrics, b_metrics])
|
||||||
|
results_path = Path(__file__).parent.parent / 'results' / 'ab_test_spx.csv'
|
||||||
|
results_df.to_csv(results_path, index=False)
|
||||||
|
print(f"\n对比结果已保存: {results_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
2
tests/utils/__init__.py
Normal file
2
tests/utils/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# 工具脚本目录
|
||||||
|
# 存放数据构建、缓存、导出等辅助工具脚本
|
||||||
Reference in New Issue
Block a user