报告日期:2026年6月22日 策略版本:v4.0(纯年线偏离度单信号 + 25%×4分批建仓 + 30%×3分批止盈 + 买入间隔保护) 策略版本:v8(RSI+年线双仓联动 + 回归通道 + 峰值RSI跟踪追卖) 策略类型:A股红利ETF 量化择时策略
策略速览
这是一份关于红利ETF量化择时的完整研究记录。如果你不想从头看到尾,这里先给出最终答案:
当前最优策略:RSI+年线双仓策略(v8) 年化收益16.45%,连续5年每年跑赢纯持,累计超额+40.49%
文章结构
| 章节 | 内容 |
|---|---|
| 第1章 | 红利资产的基础知识、ETF选择 |
| 第2章 | 做过的所有尝试——哪些有效、哪些无效 |
| 第3~7章 | 纯年线策略(v4)的完整说明和执行清单 |
| 第8章 | 最新RSI双仓策略(v8)——本报告最终成果 |
快速导航
- 如果你只想看最终结论 → 直接跳到 第8章(第1220行)
- 如果你想知道优化过程 → 从 第2章 开始,了解我放弃了什么、保留了什么
- 如果你想直接运行回测 → 请跳至 8.11 使用说明 或直接运行
python backtest_rsi_ma250_8.py
一句话说清楚
红利ETF(510880)适合波段操作而非买入持有。
纯年线策略(v4)用最简单的逻辑实现了年化12.80%、最大回撤9.02%。
在此基础上发展出的RSI双仓策略(v8)进一步达到年化16.45%、最大回撤10.71%。
所有版本都连续5年跑赢纯持。
第一章:红利类资产概述
1.1 什么是红利策略
红利策略(Dividend Strategy)又称高股息策略,是指以股息率为核心选股指标,选取持续派发稳定且较高现金股息的上市公司股票构成投资组合。该策略是全球量化投资中经典的因子投资策略之一,与价值因子、低波因子等被认为是长期有效的Smart Beta策略。
1.2 红利策略的收益来源
从DDM模型(股息贴现模型)出发,股票收益可分解为:
股票收益 = 股息收入 + 盈利增长 + 估值变动
对于红利类资产,核心收益来源是股息收入(通常贡献年化4%~6%),盈利增长和估值变动是次要因素。这与成长股”盈利增长+估值扩张”的收益结构有本质区别。
中证红利指数长期表现:
- 2005年以来年化收益:~12.86%
- 其中股息贡献:约4~5%/年
- 价格增长贡献:约7~8%/年
1.3 A股主要红利指数对比
截至2026年6月,A股市场跟踪规模较大的红利类指数主要有以下五类:
| 指数 | 选股范围 | 成分股数 | 核心因子 | 行业特征 | 适合场景 |
|---|---|---|---|---|---|
| 上证红利(000015) | 沪市 | 50 | 单纯高股息 | 金融+能源权重高 | 510880跟踪,流动性好 |
| 中证红利(000922) | 沪深两市 | 100 | 单纯高股息 | 银行煤炭占比较高 | 覆盖面更广 |
| 红利低波(H30269) | 沪深 | 50 | 高股息+低波动 | 银行占比~50% | 震荡市中抗跌 |
| 红利质量(931468) | 沪深 | 50 | 高股息+盈利质量 | 行业分散 | 反弹行情有弹性 |
| 标普A股红利(CSP&DPRC) | 沪深 | 100 | 多因子约束 | 独立走势 | 分散化需求 |
各指数2026年夏普比率对比(截至6月):
| 指数 | 2026夏普 | 过去10年正收益年数 |
|---|---|---|
| 上证红利 | 1.84 | 7/10 |
| 红利指数 | 1.66 | 6/10 |
| 中证红利 | 0.68 | 8/10 |
| 红利低波100 | -0.44 | 6/10 |
| 红利质量 | 0.40 | 7/10 |
| 标普A股红利 | -0.18 | 7/10 |
选择中证红利(000922)作为信号指数的理由:
- 覆盖沪深两市,代表性最强
- 过去10年中有8年实现正收益,稳定性最高
- 对应ETF(515080)规模超110亿元,流动性充裕
- 相关性:与510880(上证红利ETF)走势高度同步(相关系数>0.95),信号通用
第二章:策略设计历程——做了什么尝试
2.1 问题起源
策略设计始于一个基本观察:红利ETF价格涨跌幅度有限,天然存在均值回归属性。
- 上涨时:价格↑→股息率↓→追求高股息的资金卖出→价格回落
- 下跌时:价格↓→股息率↑→追求高股息的资金买入→价格企稳
这一特性使红利ETF天然适合波段操作而非”买入持有”。但关键问题在于:如何量化”涨多了”和”跌多了”?
2.2 尝试过的指标及验证结果
尝试一:股息率作为估值指标 ❌
测试方法:
dy = ak.index_value_hist_funddb(symbol="中证红利", indicator="股息率", year=10)
price = ak.stock_zh_index_daily_tx(symbol="sh000922")
# 计算价格与股息率的相关系数
corr = price.merge(dy)['close'].corr(dy['股息率'])
结果:相关系数 = +0.53(正相关)
分析: 股息率与价格呈正相关,违背了”价格越贵、股息率越低”的基本常识。原因是中证红利的股息率采用TTM滚动计算——当企业盈利增长、分红提高时,即使价格涨了,股息率也可能维持在高位甚至上升。因此,股息率在A股红利指数层面不是一个可靠的估值指标。
结论:❌ 放弃
尝试二:静态PE估值 ❌
测试方法: 使用中证指数官网PE数据与后续收益进行相关性检验。
结果: 中证红利PE在近10年中长期停留在8~12倍之间,波动区间过窄,区分度不足。例如当PE=8.5倍时,有时后续涨、有时后续跌,无法形成有效的买卖信号。
结论:❌ 放弃
尝试三:40日收益差(相对价值指标) ✅部分有效
测试方法:
# 中证红利40日涨幅 - 万得全A40日涨幅
hongli_40d = hongli['close'].pct_change(40) * 100
quanA_40d = quanA['close'].pct_change(40) * 100
diff = hongli_40d - quanA_40d
回测结果(2021.1~2026.5,来源:格隆汇):
| 40日收益差区间 | 持有1年平均收益 | 有效性 |
|---|---|---|
| < -10% | +10.96% | 强买入信号 |
| -10% ~ -5% | +7.2% | 有效买入信号 |
| -5% ~ 0% | +3.1% | 弱信号 |
| 0% ~ +5% | -1.8% | 中性 |
| +5% ~ +10% | -4.5% | 卖出信号 |
| > +10% | -8.3% | 强卖出信号 |
结论:✅ 40日收益差对后续收益有良好的预测能力,呈现清晰的”单调性”。但2024年10月出现了”假信号”——收益差达-14%,但价格在一个月前从不到4700涨到5753,处于阶段高位。说明相对指标无法区分”真低估”和”假低估”。
结论:✅ 保留,但需要辅助指标
⚠️ 后续深度相关性分析发现,40日收益差与510880的实际收益相关性极弱(仅0.236),且完全没有预测能力(对未来20日收益相关性几乎为零)。详见第2.4.6节。建议新用户直接采用纯年线策略,现有用户可考虑逐步过渡。
📖 40日收益差完整说明
定义与公式
40日收益差衡量的是红利类资产相对全市场在过去40个交易日内的超额收益:
40日收益差 = 中证红利指数过去40个交易日涨跌幅 - 中证全指过去40个交易日涨跌幅
单位:百分点(%)
- 正值(如+8%):红利近40天跑赢全市场8个百分点,说明红利相对强势
- 负值(如-6%):红利近40天跑输全市场6个百分点,说明红利相对弱势
- 接近0:红利与全市场走势一致
为什么是40个交易日? 约等于2个自然月,是经过市场广泛验证的参数——既能过滤日频噪音,又不会滞后太多。格隆汇、EarlETF等公开发表的研究以及华泰证券研报中均以40日为标准周期。
数据获取方式
方式一:Python代码获取
import akshare as ak
# 步骤1:获取中证红利指数日K线(腾讯财经数据源)
hongli = ak.stock_zh_index_daily_tx(symbol="sh000922")
# 步骤2:获取中证全指日K线(作为全市场基准)
quanA = ak.stock_zh_index_daily_tx(symbol="sh000985")
# 步骤3:计算各自40日涨跌幅(pct_change(40)自动滚动计算)
hongli_40d = hongli['close'].pct_change(40).iloc[-1] * 100
quanA_40d = quanA['close'].pct_change(40).iloc[-1] * 100
# 步骤4:相减得到40日收益差
diff = hongli_40d - quanA_40d
print(f"40日收益差: {diff:.2f}%")
依赖项安装:
pip install akshare pandas --break-system-packages
数据源说明:
stock_zh_index_daily_tx走的是腾讯财经接口(proxy.txapi.com)- 指数代码
sh000922中sh表示上海市场,000922为中证红利指数 - 指数代码
sh000985中sh表示上海市场,000985为中证全指 - 返回数据包含:date(日期)、open(开盘)、close(收盘)、high(最高)、low(最低)、volume(成交量)
- 注意:不要使用
stock_zh_index_daily(新浪接口),该接口数据仅到2019年,已失效。也不要用stock_zh_index_daily_em(东方财富接口),该接口在部分网络环境下被阻断。
方式二:手动查询
步骤1:打开东方财富网 → 搜索"中证红利"(000922)
→ 进入日K线图 → 点击"阶段统计"
→ 日期范围选最近40个交易日(约2个自然月)
→ 记下区间涨跌幅(如 -3.2%)
步骤2:搜索"中证全指"(000985) → 同样操作
→ 记下区间涨跌幅(如 +1.5%)
步骤3:相减 → -3.2% - 1.5% = -4.7%
→ 这就是当天的40日收益差
手动查询的替代方案: 关注雪球用户 EarlETF(ID: 3559889031),他每周在雪球发布”图表周刊”,其中直接包含了画好的40日收益差走势图,省去自己计算的步骤。
方式三:全历史数据批量计算
import akshare as ak
hongli = ak.stock_zh_index_daily_tx(symbol="sh000922")
quanA = ak.stock_zh_index_daily_tx(symbol="sh000985")
# 把date转成标准格式
hongli['date'] = pd.to_datetime(hongli['date'])
quanA['date'] = pd.to_datetime(quanA['date'])
# 滚动计算每一天的40日涨跌幅
hongli['40d_pct'] = hongli['close'].pct_change(40) * 100
quanA['40d_pct'] = quanA['close'].pct_change(40) * 100
# 按日期合并
result = hongli[['date','close','40d_pct']].merge(
quanA[['date','40d_pct']], on='date'
)
result['diff'] = result['40d_pct_x'] - result['40d_pct_y']
# 查看最新
print(result.tail(5))
40日收益差的回测有效性
根据格隆汇公开数据(2021.1.4 ~ 2026.5.14,共1296个交易日),在40日收益差的不同区间买入中证红利并持有252个交易日(约1年)的平均收益如下:
| 40日收益差区间 | 持有1年平均收益 | 样本量 | 信号意义 |
|---|---|---|---|
| < -10%(极端负值) | +10.96% | 充足 | 强买入 |
| -10% ~ -5% | +7.2% | 充足 | 有效买入 |
| -5% ~ -1% | +3.1% | 充足 | 弱买入 |
| -1% ~ +3% | +0.5% | 充足 | 无效(噪音区) |
| +3% ~ +5% | -1.8% | 充足 | 弱卖出 |
| +5% ~ +10% | -4.5% | 充足 | 有效卖出 |
| > +10%(极端正值) | -8.3% | 充足 | 强卖出 |
核心发现: 收益差与后续收益呈现清晰的单调性——收益差越负,后续收益越高;收益差越正,后续收益越低。但该指标存在一个重大缺陷:无法区分”真低估”和”假低估”。如2024年10月,红利因924行情大幅跑输大盘,收益差达-14%,但红利自身价格处于年线上方10%的高位——”相对便宜但绝对贵”。
尝试四:年线偏离度(绝对价格指标) ✅
测试方法:
年线 = close.rolling(250).mean()
年线偏离度 = (close / 年线 - 1) * 100
回测结果(2020.1~2025.6,来源:雪球府库):
| 策略 | 效果 |
|---|---|
| 仅用年线(低于年线买、高于年线10%卖) | 收益 > 持有不动,操作极少 |
| 年线+分批止盈 | 收益进一步优化 |
| 年线+动态回撤止盈 | 收益最优 |
年线偏离度在2024年10月的表现:
2024年10月8日:年线偏离度 = +10.3%(高于年线10%,明显高估)
2024年10月9日:年线偏离度 = +1.8%(接近年线,中性)
...
18个"假买入信号"中,0个信号发生时价格低于年线。
结论:✅ 年线偏离度能有效判断绝对价格的高低,弥补40日收益差的盲区。
组合:纯年线策略(替代双信号过滤)
⚠️ 40日收益差经深度分析确认无预测价值(与510880相关性0.236,对未来收益相关性≈0),且在全指大跌时必然为正、完美错过最佳买点。建议改用纯年线单信号策略,具体阈值可根据风险偏好选择。
经过完整回测验证及信号相关性分析,纯年线策略(年线<-1%买入,>8%卖出,510880)的最终表现:
| 指标 | 数值 |
|---|---|
| 回测区间 | 2022-01-04 ~ 2026-06-18(4.5年) |
| 总收益率 | +70.97% |
| 超额收益 | +24.63% |
| 年化收益率 | 12.80% |
| 最大回撤 | 9.02% |
| 夏普比率 | 1.09 |
| 年均操作 | 7.6次 |
| 年度跑赢 | 5/5(100%) |
v3.0 策略机制重大变更
从 v2.0 到 v3.0,策略在资金管理层面做了三项核心改进:
变更一:建仓模式改为 25%×4 分批建仓
原来 v2.0 采用”首次建仓(30~50%) + 周定投(5000元/次)”,回测发现存在两个问题:
- 周定投金额固定,牛市信号多时买入不足、熊市信号少时买得太多
- 首次建仓比例主观,不同行情下的表现差异大
v3.0 改为:每次买入始终使用初始资金的 25%(25000元),最多买4次即可满仓。这是根据信号频率分析结果设计的——平均每次买入窗口约持续数周,足够完成4次建仓,且仓位积累速度与信号强度自动匹配。
变更二:增加买入间隔保护(≥7天)
为避免信号连续出现导致在同一价位反复买入(如连续3天买入都在同价位),增加了最小间隔7天的限制。这确保了:
- 4次买入必然分布在至少3周内,分散了建仓成本
- 如果价格在买入后继续下跌,还有现金在更低位置补仓
- 模拟了真实的”周定投”节奏,避免了日频操作
变更三:卖出逻辑改为 30%×最多3次,保留10%底仓
- 每次卖出持仓的30%(而非总资产的30%),回撤时降低风险暴露
- 最多卖出3次,确保不会全部清仓
- 保留至少10%底仓,不会完全踏空后续涨幅
- 如果卖出30%后剩余仓位不足总资产10%,则自动调减至刚好保留10%
2.4.1 阈值测算的完整代码(v2.0/v3.0 兼容 — 函数版)
以下是在最终确定阈值时使用的完整测试代码。与初版相比,v2.0 将买入/卖出封装为独立函数,支持灵活指定参数组合,并输出具体触发日期,方便不同风险偏好的投资者自行选择。
"""
红利ETF周定投策略 —— 完整阈值测算脚本
===========================================
测算买入/卖出所有参数组合的触发次数和具体日期
供不同风险承受者自行选择:重仓少次 vs 轻仓多次
运行方式:python 阈值测算_完整参数组合.py
依赖:pip install akshare pandas --break-system-packages
"""
import akshare as ak
import pandas as pd
from datetime import datetime, timedelta
# =============================================
# 一、数据准备
# =============================================
print("=" * 60)
print("红利ETF周定投策略 — 完整阈值测算")
print(f"运行时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
print("=" * 60)
print("\n[1/3] 正在获取数据(中证红利 + 中证全指)...")
hongli = ak.stock_zh_index_daily_tx(symbol="sh000922")
quanA = ak.stock_zh_index_daily_tx(symbol="sh000985")
hongli['date'] = pd.to_datetime(hongli['date'])
quanA['date'] = pd.to_datetime(quanA['date'])
# 按日期排序
hongli = hongli.sort_values('date').reset_index(drop=True)
quanA = quanA.sort_values('date').reset_index(drop=True)
# 计算40日收益差
hongli['40d_pct'] = hongli['close'].pct_change(40) * 100
quanA['40d_pct'] = quanA['close'].pct_change(40) * 100
merged = hongli[['date', 'close', '40d_pct']].merge(
quanA[['date', '40d_pct']], on='date'
)
merged['diff'] = merged['40d_pct_x'] - merged['40d_pct_y']
# 计算年线偏离度
hongli['年线'] = hongli['close'].rolling(250).mean()
hongli['年线偏离度'] = (hongli['close'] / hongli['年线'] - 1) * 100
# 合并
all_data = merged.merge(hongli[['date', '年线', '年线偏离度']], on='date')
all_data = all_data.dropna().reset_index(drop=True)
print(f"数据范围: {all_data['date'].min().strftime('%Y-%m-%d')} ~ "
f"{all_data['date'].max().strftime('%Y-%m-%d')}")
print(f"有效交易日: {len(all_data)} 天")
print(f"中证红利最新收盘价: {all_data['close'].iloc[-1]:.2f}")
print(f"最新40日收益差: {all_data['diff'].iloc[-1]:.2f}%")
print(f"最新年线偏离度: {all_data['年线偏离度'].iloc[-1]:.2f}%")
# 近3年数据
cutoff_3y = all_data['date'].max() - pd.Timedelta(days=3*365)
data_3y = all_data[all_data['date'] >= cutoff_3y].copy()
# 近5年数据
cutoff_5y = all_data['date'].max() - pd.Timedelta(days=5*365)
data_5y = all_data[all_data['date'] >= cutoff_5y].copy()
print(f"\n近3年数据: {len(data_3y)} 天 ({data_3y['date'].min().strftime('%Y-%m-%d')} ~ "
f"{data_3y['date'].max().strftime('%Y-%m-%d')})")
print(f"近5年数据: {len(data_5y)} 天 ({data_5y['date'].min().strftime('%Y-%m-%d')} ~ "
f"{data_5y['date'].max().strftime('%Y-%m-%d')})")
# =============================================
# 二、买入信号测算函数
# =============================================
def test_buy_thresholds(data, diff_thresholds, ma_dev_thresholds, label="近3年"):
"""
测试买入阈值组合
diff_thresholds: 40日收益差阈值列表(如 [-5, -8, -10])
ma_dev_thresholds: 年线偏离度阈值列表(如 [0, -2, 3],单位%)
"""
print(f"\n{'='*60}")
print(f"【买入信号测算 — {label}】")
print(f"{'='*60}")
print(f"{'收益差<':<10} {'年线<':<10} {'触发天数':<12} {'年均次数':<12} {'占比%':<10} {'说明':<20}")
print("-" * 72)
results = []
for diff_t in diff_thresholds:
for ma_t in ma_dev_thresholds:
mask = (data['diff'] < diff_t) & (data['年线偏离度'] < ma_t)
cnt = mask.sum()
years = (data['date'].max() - data['date'].min()).days / 365.25
yearly = cnt / years if years > 0 else 0
pct = cnt / len(data) * 100
# 获取具体日期
dates = data.loc[mask, 'date'].dt.strftime('%Y-%m-%d').tolist()
# 自动判断风格
if yearly < 10:
note = "极保守,重仓少次"
elif yearly < 30:
note = "偏保守"
elif yearly < 50:
note = "★推荐适中"
else:
note = "偏积极,轻仓多次"
results.append({
'diff_t': diff_t, 'ma_t': ma_t,
'cnt': cnt, 'yearly': yearly,
'pct': pct, 'note': note, 'dates': dates
})
print(f"diff<{diff_t}% 年线<{ma_t}% {cnt:<12} {yearly:<12.1f} "
f"{pct:<10.2f}% {note}")
return results
# =============================================
# 三、卖出信号测算函数
# =============================================
def test_sell_thresholds(data, diff_thresholds, ma_dev_thresholds, label="近3年"):
"""
测试卖出阈值组合
diff_thresholds: 40日收益差阈值列表(如 [5, 8, 10])
ma_dev_thresholds: 年线偏离度阈值列表(如 [5, 8, 10, 12])
"""
print(f"\n{'='*60}")
print(f"【卖出信号测算 — {label}】")
print(f"{'='*60}")
print(f"{'收益差>':<10} {'年线>':<10} {'触发天数':<12} {'年均次数':<12} {'占比%':<10} {'说明':<20}")
print("-" * 72)
results = []
for diff_t in diff_thresholds:
for ma_t in ma_dev_thresholds:
mask = (data['diff'] > diff_t) & (data['年线偏离度'] > ma_t)
cnt = mask.sum()
years = (data['date'].max() - data['date'].min()).days / 365.25
yearly = cnt / years if years > 0 else 0
pct = cnt / len(data) * 100
dates = data.loc[mask, 'date'].dt.strftime('%Y-%m-%d').tolist()
if yearly < 3:
note = "极严,难触发"
elif yearly < 6:
note = "★推荐适中"
elif yearly < 10:
note = "偏灵敏"
else:
note = "很灵敏"
results.append({
'diff_t': diff_t, 'ma_t': ma_t,
'cnt': cnt, 'yearly': yearly,
'pct': pct, 'note': note, 'dates': dates
})
print(f"diff>{diff_t}% 年线>{ma_t}% {cnt:<12} {yearly:<12.1f} "
f"{pct:<10.2f}% {note}")
return results
# =============================================
# 四、执行测算
# =============================================
# --- 买入测算 ---
buy_diff = [-5, -8, -10]
buy_ma = [0, -2, 3] # 0=年线位置, -2=年线下方2%, 3=年线上方3%
buy_results_3y = test_buy_thresholds(data_3y, buy_diff, buy_ma, "近3年")
buy_results_5y = test_buy_thresholds(data_5y, buy_diff, buy_ma, "近5年")
# --- 卖出测算 ---
sell_diff = [5, 8, 10]
sell_ma = [5, 8, 10, 12]
sell_results_3y = test_sell_thresholds(data_3y, sell_diff, sell_ma, "近3年")
sell_results_5y = test_sell_thresholds(data_5y, sell_diff, sell_ma, "近5年")
# =============================================
# 五、详细日期输出
# =============================================
print(f"\n\n{'='*60}")
print("详细触发日期(近3年)")
print("=" * 60)
print("\n--- 买入信号 详细日期 ---")
for r in buy_results_3y:
key = f"diff<{r['diff_t']}% & 年线<{r['ma_t']}%"
print(f"\n[{key}] 共 {r['cnt']} 天触发")
if r['cnt'] > 0:
dates_series = pd.Series(r['dates'])
years = dates_series.str[:4].unique()
for y in sorted(years):
ydates = dates_series[dates_series.str.startswith(y)].tolist()
print(f" {y}: {', '.join(ydates[:30])}", end="")
if len(ydates) > 30:
print(f" ... 共{len(ydates)}天")
else:
print()
print("\n\n--- 卖出信号 详细日期 ---")
for r in sell_results_3y:
key = f"diff>{r['diff_t']}% & 年线>{r['ma_t']}%"
print(f"\n[{key}] 共 {r['cnt']} 天触发")
if r['cnt'] > 0:
dates_series = pd.Series(r['dates'])
years = dates_series.str[:4].unique()
for y in sorted(years):
ydates = dates_series[dates_series.str.startswith(y)].tolist()
print(f" {y}: {', '.join(ydates[:30])}", end="")
if len(ydates) > 30:
print(f" ... 共{len(ydates)}天")
else:
print()
将上述代码保存为
阈值测算_完整参数组合.py,运行python 阈值测算_完整参数组合.py即可获得最新结果。
2.4.2 完整回测结果(v3.0 — 全部参数组合对比)
以下结果基于 2019~2026年 共约6~7年的历史数据,对两个红利ETF在8个参数组合下分别回测。
策略统一参数: 买入25%初始资金×4次满仓 | 间隔≥7天 | 卖出30%持仓×最多3次 | 保留10%底仓
招商中证红利ETF (515080) 回测结果:
| 排名 | 参数名 | 买入阈值 | 卖出阈值 | 总收益 | 年化 | 最大回撤 | 超额收益 | 夏普 |
|---|---|---|---|---|---|---|---|---|
| 1 | 卖出>12% ⭐ | diff<-5, 年线<3 | diff>5, 年线>12 | 165.75% | 16.29% | 9.93% | +3.78% | 0.78 |
| 2 | 卖出>10% | diff<-5, 年线<3 | diff>5, 年线>10 | 152.58% | 15.38% | 9.93% | -9.39% | 0.75 |
| 3 | 买入严格 | diff<-5, 年线<0 | diff>5, 年线>8 | 130.23% | 13.75% | 9.93% | -31.74% | 0.73 |
| 4 | 平衡型 | diff<-5, 年线<3 | diff>5, 年线>8 | 126.83% | 13.48% | 9.93% | -35.14% | 0.67 |
| 5 | 积极型 | diff<-5, 年线<5 | diff>5, 年线>5 | 126.58% | 13.46% | 9.93% | -35.39% | 0.67 |
| 6 | 年线<1% | diff<-5, 年线<1 | diff>5, 年线>8 | 124.79% | 13.33% | 9.93% | -37.18% | 0.68 |
| 7 | 年线<2% | diff<-5, 年线<2 | diff>5, 年线>8 | 124.79% | 13.33% | 9.93% | -37.18% | 0.68 |
| 8 | 保守型 | diff<-8, 年线<0 | diff>5, 年线>10 | 33.69% | 4.59% | 9.93% | +3.62% | 0.27 |
纯持ETF参考:总收益 161.97%,年化 ~15.5%,同期指数价格涨幅仅 28.82%(分红贡献 ~133%)
华泰柏瑞上证红利ETF (510880) 回测结果:
| 排名 | 参数名 | 买入阈值 | 卖出阈值 | 总收益 | 年化 | 最大回撤 | 超额收益 | 夏普 |
|---|---|---|---|---|---|---|---|---|
| 1 | 卖出>12% ⭐ | diff<-5, 年线<3 | diff>5, 年线>12 | 94.57% | 9.86% | 8.37% | +15.80% | 0.45 |
| 2 | 卖出>10% | diff<-5, 年线<3 | diff>5, 年线>10 | 85.14% | 9.09% | 8.37% | +6.38% | 0.41 |
| 3 | 买入严格 | diff<-5, 年线<0 | diff>5, 年线>8 | 69.58% | 7.75% | 8.37% | -9.19% | 0.35 |
| 4 | 平衡型 | diff<-5, 年线<3 | diff>5, 年线>8 | 68.68% | 7.67% | 8.37% | -10.08% | 0.33 |
| 5 | 积极型 | diff<-5, 年线<5 | diff>5, 年线>5 | 66.70% | 7.49% | 8.37% | +7.10% | 0.32 |
| 6 | 年线<1% | diff<-5, 年线<1 | diff>5, 年线>8 | 65.49% | 7.38% | 8.37% | -13.27% | 0.32 |
| 7 | 年线<2% | diff<-5, 年线<2 | diff>5, 年线>8 | 65.49% | 7.38% | 8.37% | -13.27% | 0.32 |
| 8 | 保守型 | diff<-8, 年线<0 | diff>5, 年线>10 | 36.87% | 4.53% | 8.37% | +5.21% | 0.27 |
纯持ETF参考:总收益 78.77%,年化 ~8.5%,同期指数价格涨幅 ~29%(分红贡献 ~50%)
关键发现:
- 卖出阈值是决定收益的核心变量。 买入端参数几乎不影响结果(所有组合的买入信号高度重叠),真正拉开差距的是卖出的年线偏离度阈值:
- 年线>12%卖出 → 年化最高,给足上涨空间
- 年线>8%卖出 → 过严,2021年卖飞导致超额为负
- 年线>5%卖出 → 频繁卖出,收益最低
- 515080 大多数参数跑输纯持的原因: 中证红利分红极高(6年贡献133%),卖出后现金闲置只吃1.7%利息,错失了后续分红。而卖出>12%因为卖出条件极严(几乎只在极端高位卖出),大部分时间持仓吃分红,所以跑赢纯持。
- 510880 几乎所有参数都从策略中受益: 上证红利分红较少(~50%),纯持收益主要靠价格涨幅。策略在低位建仓、高位兑现,明显增厚了收益。卖出>12%的超额收益更高达+15.80%。
2.4.3 阈值选定逻辑
买入阈值选 diff<-5% & 年线<3% 的理由:
| 候选方案 | 天数/3年 | 年均次数 | 风格 | 说明 |
|---|---|---|---|---|
| diff<-10% & 年线<0% | 2天 | ~1次 | 极保守 | 几乎不触发,只在大熊市出现 |
| diff<-10% & 年线<-2% | (运行脚本) | 极保守 | 比上面更严 | |
| diff<-8% & 年线<0% | 12天 | ~4次 | 极保守 | 低于年线且大幅跑输才买,确定性最高 |
| diff<-8% & 年线<-2% | (运行脚本) | 极保守 | 价格在年线下方2%才出手 | |
| diff<-5% & 年线<0% | 25天 | ~8次 | 偏保守 | 低于年线才买,年均操作约8次 |
| diff<-5% & 年线<-2% | (运行脚本) | 偏保守 | 要求价格在年线下方2% | |
| diff<-5% & 年线<-3%(备选) | (运行脚本) | 偏保守 | 要求价格在年线下方3% | |
| diff<-5% & 年线<3%(推荐) | 121天 | ~40次 | 适中平衡 | 月均3~4次,持续3~5天形成买入窗口 |
| diff<-5% & 年线<5% | 176天 | ~59次 | 偏积极 | 容忍小幅追高,买入机会多但质量略降 |
| diff<-8% & 年线<3% | 38天 | ~13次 | 偏保守 | 收益差要求更严,年线适度放宽 |
卖出阈值选 diff>5% & 年线>12% 的理由(通过完整回测验证):
| 候选方案 | 515080年化 | 510880年化 | 风格 | 说明 |
|---|---|---|---|---|
| diff>5% & 年线>5% | 13.46% | 7.49% | 灵敏 | 稍有高估就卖,可能错失最后涨幅 |
| diff>5% & 年线>8% | 13.48% | 7.67% | 适中 | 仍偏早,2021年卖飞明显 |
| diff>5% & 年线>10% | 15.38% | 9.09% | 保守 | 收益率显著改善 |
| diff>5% & 年线>12%(推荐) | 16.29% | 9.86% | 极保守 | 给足上涨空间,两个ETF均跑赢纯持 |
2024年10月假信号的双信号验证:
仅用40日收益差(<-5%):18天触发买入(大部分是误判)
加年线<3%过滤后: 0天触发(全部过滤)
其中2024年10月8日那天,40日收益差达-14.35%,但年线偏离度为+10.3%(价格在年线上方10%),双信号规则下不买入——成功规避了一次在阶段高位买入的风险。
2.4.4 场景选择指南——不同风格怎么选参数
不同的投资者对操作频率的容忍度不同,以下给出三种典型风格的完整参数方案:
┌────────────────────────────────────────────────────────────────────┐
│ 场景一:保守型(重仓少次) │
│ ────────────────────────────────────────────────────────────── │
│ 特点:信号极少触发,一旦触发就重仓操作 │
│ 适合:工作忙没空看盘、喜欢低位一把梭、操作越少越好的投资者 │
│ │
│ 买入:diff<-8% & 年线<0% 仅2022年中触发过,6年只建仓4次 │
│ 卖出:diff>5% & 年线>10% 几乎不触发,基本持有不动 │
│ │
│ 资金管理(以10万为例): │
│ - 每次买入25000元,最多4次满仓 │
│ - 不设卖出(因为几乎不触发) │
│ │
│ 回测结果:515080年化 4.59%(vs 纯持 ~15.5%),510880年化 4.53% │
│ 说明:保守型看似安全,实则因现金长时间闲置大幅跑输纯持 │
└────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────┐
│ 场景二:平衡型(推荐⭐) │
│ ────────────────────────────────────────────────────────────── │
│ 特点:信号频率适中,既有安全边际又能抓住大部分行情 │
│ 适合:每周能花5分钟看一次、追求稳健收益的投资者 │
│ │
│ 买入:diff<-5% & 年线<3% 年均买入信号约40天 │
│ 卖出:diff>5% & 年线>12% 年均卖出信号约2~3次,3次卖完即停 │
│ │
│ 资金管理(以10万为例): │
│ - 每次买入:25000元(25%初始资金),间隔≥1周 │
│ - 最多买4次即满仓(合计10万) │
│ - 每次卖出:持仓ETF市值的30%,最多卖3次 │
│ - 保留至少10%底仓,永不空仓 │
│ │
│ 回测结果: │
│ 515080:年化16.29% 最大回撤9.93% 跑赢纯持+3.78% │
│ 510880:年化9.86% 最大回撤8.37% 跑赢纯持+15.80% │
└────────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────────┐
│ 场景三:积极型(轻仓多次) │
│ ────────────────────────────────────────────────────────────── │
│ 特点:买入机会多,卖出灵敏,追求波段收益 │
│ 适合:希望能频繁操作、对回撤极度敏感的投资者 │
│ │
│ 买入:diff<-5% & 年线<5% 年均买入信号约60天 │
│ 卖出:diff>5% & 年线>5% 年均卖出信号约10次 │
│ │
│ 资金管理(以10万为例): │
│ - 每次买入25000元,间隔≥1周 │
│ - 每次卖出持仓30%,最多3次 │
│ │
│ 回测结果: │
│ 515080:年化13.46% 最大回撤9.93% 跑输纯持-35.39% │
│ 510880:年化7.49% 最大回撤8.37% 跑赢纯持+7.10% │
│ 说明:积极型对515080有害(卖太早错过分红),对510880仍有帮助 │
└────────────────────────────────────────────────────────────────────┘
如何选择适合自己的方案:
| 考虑因素 | 选保守 | 选平衡 | 选积极 |
|---|---|---|---|
| 能否接受长时间现金闲置? | ✅ 可以 | ⚠️ 会跑输分红 | ❌ 会大幅跑输 |
| 是否相信卖出能增厚收益? | ❌ 会卖飞 | ✅ 高位兑现 | ⚠️ 可能卖早 |
| 更关注哪个ETF? | — | 515080或510880均可 | 仅适合510880 |
| 预期年化(515080) | ~4.5% | ~16.3% | ~13.5% |
| 预期年化(510880) | ~4.5% | ~9.9% | ~7.5% |
💡 建议: 从平衡型方案开始执行,运行3~6个月后,根据自身感受再决定是收紧还是放宽参数。不必一开始就追求”最优参数”,执行纪律比参数精确更重要。
2.4.5 2022年至今的专项测试:谁是最好的策略标的?
核心结论: 2022年至今,510880(上证红利)是本策略更优的标的选择。虽然两者纯持有收益几乎完全相同(~28%),但510880在本策略下全线优于515080,最高年化可达12.49%(年线<1% + 卖出>8%)。
为什么要单独测2022年至今?
515080(跟踪中证红利000922)在2020–2021年取得了异常收益(累计超70%),这部分收益主要来自成分股估值修复而非股息贡献。排除这段”特殊期”后,2022年至今的数据更能反映两个ETF在常态市场下的真实表现差异。
一、纯持有收益对比(2022年至今)
| 指标 | 515080(中证红利) | 510880(上证红利) |
|---|---|---|
| 累计收益 | ~28% | ~28% |
| 最大回撤 | ~15% | ~18% |
| 年化波动 | ~16% | ~19% |
| 股息贡献占比 | ~87% | ~87% |
- 累计收益几乎完全一致
- 510880波动略大、回撤略深——这恰恰是量化策略最需要的价格摆动空间
二、策略超额收益对比(2022年至今)
以下是 v3.0 策略下16组参数×两个ETF的全部回测结果:
| 参数ID | 买入条件 | 卖出条件 | 515080年化 | 510880年化 | 胜负 |
|---|---|---|---|---|---|
| b6ma1_s8 | diff<-6 + 年线<1% | diff>0 + 年线>8% | 2.55% | 7.24% | ✅ 510880 |
| b6ma1_s10 | diff<-6 + 年线<1% | diff>0 + 年线>10% | 2.55% | 6.34% | ✅ 510880 |
| b6ma1_s12 | diff<-6 + 年线<1% | diff>0 + 年线>12% | 2.55% | 4.73% | ✅ 510880 |
| b6ma2_s8 | diff<-6 + 年线<2% | diff>0 + 年线>8% | 3.09% | 10.56% | ✅ 510880 |
| b6ma2_s10 | diff<-6 + 年线<2% | diff>0 + 年线>10% | 3.09% | 9.63% | ✅ 510880 |
| b6ma2_s12 | diff<-6 + 年线<2% | diff>0 + 年线>12% | 3.09% | 7.48% | ✅ 510880 |
| b8ma1_s8 | diff<-8 + 年线<1% | diff>0 + 年线>8% | 0% | 4.80% | ✅ 510880 |
| b8ma1_s10 | diff<-8 + 年线<1% | diff>0 + 年线>10% | 0% | 3.62% | ✅ 510880 |
| b8ma1_s12 | diff<-8 + 年线<1% | diff>0 + 年线>12% | 0% | 1.89% | ✅ 510880 |
| b8ma2_s8 | diff<-8 + 年线<2% | diff>0 + 年线>8% | 3.05% | 12.49% | ✅ 510880 |
| b8ma2_s10 | diff<-8 + 年线<2% | diff>0 + 年线>10% | 3.05% | 12.49% | ✅ 510880 |
| b8ma2_s12 | diff<-8 + 年线<2% | diff>0 + 年线>12% | 3.05% | 8.55% | ✅ 510880 |
| 纯持有基准 | — | — | ~3.9%* | ~3.9%* | 持平 |
- 2022年起持有至今年化约3.9%(因期间经历了2022年的大幅下跌和2024年的震荡),期间累计收益约28%。
510880全胜,无一组例外。 即便在买入最严格的参数(b8ma1系列)下515080完全没有触发买入、收益为零,510880仍有正收益。
三、为什么510880更适合量化策略?
- 价格驱动力不同: 510880跟踪上证红利(000015),集中在周期行业(煤炭、钢铁、银行),估值弹性大,价格摆动幅度更大,为”低估买、高估卖”提供了更充分的空间。515080跟踪的中证红利(000922)包含更多防御性行业,波动偏小。
- 卖出信号有效性: 515080在2022年至今几乎不触发卖出信号(年线>8%),导致策略无法兑现超额收益。510880则能正常触发卖出,实现”低位买入→高位卖出”的完整循环。
- 参数容错率高: 510880在不同买入/卖出参数组合下均能保持正超额收益,而515080在严格买入条件下可能完全不触发信号,导致空仓。
四、更严买入条件的效果验证
之前的”更严格买入条件”测试(diff=-6/-8 + 年线<2%/<0%)在2022年至今数据中呈现以下特征:
| 买入条件 | 515080表现 | 510880表现 |
|---|---|---|
| diff<-6 + 年线<1% | 触发少量买入,年化~2.5% | 正常交易,年化~7.2% |
| diff<-6 + 年线<2% | 买入稍多,年化~3.1% | 最优区间,年化~10.6% |
| diff<-8 + 年线<1% | 完全不触发买入 | 少量买入,年化~4.8% |
| diff<-8 + 年线<2% | 买入偏少,年化~3.1% | 最优,年化~12.49% |
- 过严条件(diff<-8 + 年线<1%)导致515080完全空仓,再次印证之前的结论:严格条件不提升收益,只是减少了交易机会
- 510880在diff<-8 + 年线<2%下表现最好(年化12.49%),因为510880波动更大,即使在严格条件下也有买入机会
- 即便买入条件宽松(diff<-6 + 年线<2%),510880仍能通过卖出机制获得超额收益
五、最终建议
✅ 最优策略标的:510880(上证红利ETF) ✅ 推荐参数:买入 diff<-8 + 年线<2% | 卖出 diff>0 + 年线>8% ✅ 预期年化(2022年至今风格):~10%~12%,对纯持有超额约6~8个百分点
510880的更大波动不是风险,而是量化策略超额收益的来源。在红利类ETF上做量化,“波动是朋友”——没有波动的资产,量化策略无法创造超额收益。
2.4.6 相关性分析验证:40日收益差的局限性
核心结论:40日收益差(diff)与510880的实际走势相关性弱(r=0.236),对未来收益完全没有预测能力(r≈0)。该指标在全指大跌时(此时红利通常价格较低)必然为正,反而将最佳买点全部过滤。建议废止该指标,改用纯年线策略。
一、分析背景
在之前的回测中发现,AND逻辑(diff<-8 AND 年线<2%)仅触发86个买入信号日,而年线<2%但diff未触发的天数高达521天——绝大多数年线低位都被diff过滤掉了。为了弄清楚diff到底有没有价值,我编写了 signal_correlation.py,对2022年至今的789个交易日进行了完整的相关性分析。
二、diff vs 510880 涨跌幅的相关性
| 对比项 | 相关性 | 解读 |
|---|---|---|
| diff vs 510880-40日涨跌幅 | 0.236 | 弱相关,仅解释5.6%的走势 |
| diff vs 中证红利-40日涨跌幅 | -0.005 | 几乎无关,令人震惊 |
| 中证红利 vs 中证全指的40日涨跌幅 | 0.557 | 中等相关,两者走势并不完全同步 |
| 中证红利(000922) vs 上证红利(510880) 日涨跌幅 | 0.954 | 极高,信号源的ETF之间差异很小 |
diff与510880的同期40日涨幅相关性仅0.236,意味着这个指标大部分时候并不反映510880的实际涨跌。
三、diff的预测能力
| 指标 | 明日收益 | 未来5日收益 | 未来20日收益 |
|---|---|---|---|
| 40日收益差(diff) | 0.017 | 0.065 | 0.002 |
| 年线偏离度 | 0.137 | 0.252 | 0.217 |
- diff对未来收益的预测能力几乎为零(所有相关性≈0)
- 年线偏离度在所有时间维度上均优于diff,尤其对未来5~20日收益有中等预测力(r≈0.22~0.25)
四、纯年线信号在不同阈值下的表现
| 阈值 | 信号天数(7年) | 未来20日平均收益 | 胜率 |
|---|---|---|---|
| 年线<-3% | 12天 | +1.46% | 91.7% |
| 年线<-2% | 13天 | +1.50% | 92.3% |
| 年线<-1% | 26天 | +0.38% | 73.1% |
| 年线<0% | 60天 | -0.62% | 58.3% |
| 年线<+1% | 123天 | -1.37% | 41.5% |
年线<-2%的信号虽少(7年13次)但近乎百发百中;年线<-1%有26次、胜率73.1%,是不错的折中。
五、diff在不同市场环境下的致命问题
| 市场环境 | 天数 | 平均diff | diff<-8概率 | 年线<2%概率 |
|---|---|---|---|---|
| 全指大涨>5% | 126 | -7.67% | 51.6% | 27.0% |
| 全指大跌<-5% | 92 | +6.16% | 0.0% | 40.2% |
| 全指震荡 | 551 | -0.07% | 7.1% | 22.9% |
最关键的数据:全指大跌时,diff的平均值为+6.16%,从未<-8%。 这意味着:
当全市场暴跌、红利价格大概率便宜的时候,diff一定不会触发买入信号。
原因很简单:全指跌得比红利更多 → diff为正 → 不触发 → 错过买点
这就是Jan 22 / Sep 12 / Sep 30等最佳买点被完美错过的主要原因。
而同期年线<2%的概率是40.2%——年线指标明确显示”价格便宜”,但diff把它们全过滤了。
六、更值得警惕的数据
当diff真正触发买入条件(<-8)时,510880未来20日的平均收益是 -1.26%,胜率仅 34.6%——比随机买入更差。
六-B、纯年线策略最终回测结果
基于上述分析编写了 backtest_ma_only.py,对纯年线策略(年线<-1%买入、>8%卖出、25%×4分批建仓、30%×3分批止盈)进行了完整回测:
回测区间:2022-01-04 ~ 2026-06-18(4.5年) 最终结果:+70.97%总收益,年化12.80%,跑赢纯持+24.63%
| 指标 | 纯年线策略 | 纯持ETF(510880) | 对比 |
|---|---|---|---|
| 总收益率 | +70.97% | +46.34% | +24.63% |
| 年化收益率 | 12.80% | 9.03% | +3.77%/年 |
| 最终资产 | 170,968元 | 146,339元 | — |
| 最大回撤 | 9.02% | ~20% | ↓减半 |
| 夏普比率 | 1.09 | ~0.5 | ↑翻倍 |
| Calmar比率 | 1.42 | ~0.3 | ↑4倍 |
| 年化波动率 | 10.00% | ~18% | ↓降低 |
| 月度胜率 | 57.4% | — | — |
| 年均操作 | 7.6次 | 0次 | 每周5分钟 |
逐年表现:全部跑赢纯持
| 年份 | 策略收益 | 纯持涨跌 | 最大回撤 | 超额收益 |
|---|---|---|---|---|
| 2022 | +9.85% | +1.36% | 9.02% | +8.49% |
| 2023 | +11.49% | +8.31% | 6.88% | +3.18% |
| 2024 | +27.69% | +20.05% | 6.23% | +7.65% |
| 2025 | +5.74% | +1.54% | 2.97% | +4.21% |
| 2026 | +3.37% | +2.01% | 1.46% | +1.37% |
| 累计 | +70.97% | +46.34% | 9.02% | +24.63% |
7个完整买卖周期,全部盈利:
| 周期 | 买入次数 | 买入均价 | 卖出均价 | 波段收益 |
|---|---|---|---|---|
| ① 2022.03→2022.04 | 1次 | 2.117 | 2.495 | +17.9% |
| ② 2022.04→2023.04 | 3次 | 2.262 | 2.593 | +14.6% |
| ③ 2023.12→2024.02 | 2次 | 2.520 | 2.817 | +11.8% |
| ④ 2024.08→2024.10 | 4次 | 2.637 | 3.073 | +16.5% |
| ⑤ 2025.02→2025.07 | 2次 | 2.814 | 3.158 | +12.2% |
| ⑥ 2025.09→2026.03 | 1次 | 2.939 | 3.325 | +13.1% |
| ⑦ 2026.06→至今 | 1次 | 3.098 | — | 持有中 |
结论: 纯年线策略经过4.5年完整回测,5年连续每年跑赢纯持。最大回撤仅9.02%(vs纯持约20%),夏普比率1.09(vs纯持约0.5)。策略逻辑简单、参数直观、可解释性强,推荐作为实盘基准策略。
七、最终建议
旧方案(已废弃):买入 = diff<-8% AND 年线<2% (双信号)
新方案(推荐): 买入 = 年线偏离度 < -1% (纯年线,单信号)
卖出 = 年线偏离度 > +8% (纯年线,单信号)
| 对比 | 旧策略(AND) | 纯年线(-1%) | 纯年线(0%) |
|---|---|---|---|
| 信号逻辑 | diff<-8 AND 年线<2 | 年线<-1% | 年线<0% |
| 买入信号天数(7年) | 86天 | 26天 | 60天 |
| 核心问题 | 熊市时全部过滤 | 信号偏少 | 信号充足 |
| 建议 | ❌ 废止 | ✅ 保守型首选 | ✅ 平衡型首选 |
纯年线策略的逻辑更直接: 价格低于年线(或年线下方一定幅度)时,说明相对历史价格处于低位,分批买入;价格远高于年线时,分批卖出。去掉了”相对全市场强弱”这个噪音维度,信号更干净、更可靠。
3.1 年线偏离度的逻辑——化繁为简
经过完整的信号相关性分析(详见2.4.6节),40日收益差指标被确认为无效信号,最终策略简化为单一的年线偏离度指标。
信号逻辑:
买入 → 年线偏离度 < 阈值(价格低于年线 = 相对历史低位)
卖出 → 年线偏离度 > 阈值(价格远高于年线 = 相对历史高位)
为什么只看年线就够了:
1. 年线是250个交易日的平均成本,是市场参与者的"心理锚点"
2. 低于年线时买入,等于以低于市场平均成本的价格建仓
3. 高于年线一定幅度时卖出,兑现利润
4. 去掉了"相对全市场强弱"这一噪音维度,信号更干净
3.2 为什么红利ETF适合均值回归而非趋势跟踪
趋势跟踪对具有长期增长趋势的资产有效(如纳指、成长股)。而红利ETF具有以下特征:
- 股息率锚定:价格偏离合理区间时,股息率会吸引或驱逐资金
- 行业结构稳定:以银行、煤炭、公用事业为主,盈利增长有限
- 机构资金主导:险资、养老金以股息率为锚做配置,形成天然的”低买高卖”机制
这些特征决定了红利ETF的价格弹性远小于成长股,呈现”涨不高、跌不深”的箱体震荡特征——这正是均值回归策略的理想标的。
3.3 DDM模型视角下的解释
从DDM模型看,红利ETF的估值主要由分母端(折现率) 驱动:
股价 = D1 / (r - g)
其中D1为预期股息,r为折现率,g为增长率。红利ETF的g很小(企业增长有限),所以折现率r的变化对股价影响更大。当市场利率下行(r↓)时,红利ETF上涨;当利率上行(r↑)时,红利ETF下跌。
年线偏离度衡量的正是”价格相对于长期平均成本的偏离程度”——当价格大幅低于年线时,意味着市场已充分消化了利空因素,后续均值回归的概率较高;反之当价格远超年线时,说明市场情绪过热,回归风险加大。这与DDM框架中”价格围绕内在价值波动”的基本原理一致。
3.4 为什么”信号驱动型分批买入”而非一次性投入
适用范围说明: 本节讨论的是纯年线策略(v4,第1~7章)的资金管理逻辑。纯年线策略在信号触发时买入,两次买入之间至少间隔7天,形成”信号驱动型周节奏”——买入频率由市场信号决定而非固定日历周期。与之对应,RSI双仓策略(v8,第8章)不设买入间隔,完全由RSI+价格条件决定,买入更加灵活。
一个自然的疑问是:既然信号已经在”低估”时才触发买入,为什么不一次性把资金全部投入,而要分批买入?
原因一:信号窗口的长度不可预测
买入信号(40日收益差<-5% & 年线偏离度<3%)在近3年中累计出现121天,但这些信号不是均匀分布的,而是以”窗口”形式出现——每次连续3天到3周不等。
历史买入窗口形态(示例):
2023年10月:连续8天出现买入信号 → 窗口长,有充足时间建仓
2024年1月: 连续3天出现买入信号 → 窗口短,但3天也够分批
2024年6月: 连续12天出现买入信号 → 窗口很长
2024年10月: 0天(被年线过滤) → 假信号,不应该买
一次性投入的困境在于:你不知道当前的窗口是3天还是3周。 如果今天一次性买完,明天信号就消失了且后面更便宜,就没有子弹补仓了。等待一周,如果窗口还在就继续买,如果窗口关闭就停止——用时间换确定性。纯年线策略的7天最小间隔正是为此设计:确保4次买入分布在至少3周内。
原因二:均值回归需要时间
从历史数据看,年线偏离度从极负值(<-5%)回升到中性区(>-1%)平均需要数周时间:
典型均值回归路径:
第0周:年线偏离度 = -5%(低于年线5%,低估)→ 开始买入
第2周:年线偏离度 = -3%(仍然低估)→ 继续买入
第4周:年线偏离度 = -1%(接近年线)→ 停止买入
这数周的回归期,就是天然的”分批买入窗口”。一次性在第0周全部买入,买入均价 = 第一周的价格;而分多次买入,买入均价 = 整个回归期的平均价格。对于均值回归资产,分批买入的均价理论上优于一次性买入的均价。
原因三:”底仓 + 分批加仓”的组合设计(纯年线策略)
纯年线策略并不是”等额定投”,而是 “信号触发 + 分批加仓” 的组合:
首次买入:信号触发时买25000元(25%初始资金)
后续加仓:信号仍有效且距上次买入≥7天时,再买25000元
最多买4次即满仓,自然形成"信号驱动型周节奏"
| 方式 | 优点 | 缺点 |
|---|---|---|
| 纯一次性 | 如果买在最低点,收益最大 | 如果买后继续跌,没有补仓资金 |
| 纯等额周投 | 均价平稳,心理压力小 | 牛市买入过多、熊市买入不足 |
| 信号驱动分批(本策略) | 只在低估时买入,且每次买入都是相对低位 | 信号窗口短时可能买不够 |
这种设计的实质是:承认无法精准预测最低点,用分批的方式来管理不确定性。
原因四:心理层面的纪律性
行为金融学研究表明,普通投资者最容易犯的错误是在上涨时追高买入、在下跌时恐慌卖出。周定投提供了一个天然的”操作隔离”:
- 每周只操作一次,隔离了日频波动带来的情绪干扰
- 固定的操作节奏(周五收盘前)形成纪律,减少”感觉要涨了就提前买”的冲动
- 信号中断立刻停止(而非”再跌我就补仓”),避免越跌越买的抄底陷阱 <!– 修正用字 –>
💡 类比: 一次性投入像是”猜拳一次定胜负”,周定投像是”五局三胜”。对于红利ETF这种均值回归资产,用多次小决策代替一次大决策,长期来看更稳健。
关于分批买入的”节奏”选择
为什么纯年线策略采用约7天(≈1周)的买入间隔,而不是日频或月频?
| 频率 | 问题 |
|---|---|
| 日频买入 | 信号以”连续数天”出现,日频会导致同一窗口内买入过多笔,4次建仓很快就用完,后续窗口无资金可用 |
| 约周频买入(推荐) | 7天间隔确保每个买入窗口内操作1~3次,节奏适中;周五收盘前操作可参考当周完整信号 |
| 月频买入 | 可能错过整个买入窗口(有的窗口仅持续3~5天),且月内价格波动无法利用 |
此外,年线偏离度的计算周期(250个交易日 ≈ 1年)本身就是长期指标——用长期指标指导按周为单位的操作,时间尺度是协调的。
RSI双仓策略(v8)对此的改进: 与纯年线策略不同,RSI双仓策略不设买入间隔。因为仓1和仓2共用两个独立的条件体系,天然错开了买入机会,且仓2(20%资金)本身金额较小,不需要额外的时间分散保护。
第四章:策略评价
4.1 优点
| 维度 | 评价 |
|---|---|
| 逻辑清晰 | 单信号(年线偏离度),简单直接,每笔交易都有明确依据 |
| 可回测验证 | 所有阈值均经过2019~2026年完整回测,附信号相关性分析验证 |
| 操作频率低 | 保守型年均操作约4次,大部分时间不需要操作 |
| 容错性好 | 分批买卖(每次25%买入、30%卖出),不会一次就看错全部 |
| 避免噪音 | 去除了40日收益差这一经过验证无效的指标,信号更干净 |
| 工具免费 | 数据全部来自免费开源接口,无需付费终端 |
4.2 缺点
| 维度 | 评价 |
|---|---|
| 无法躲避单边下跌 | 年线偏离度是价格指标,如果红利ETF持续大跌,策略会不断买入 |
| 信号依赖数据质量 | 万一数据源变更或中断,需要备查方案 |
| 卖出窗口可能极短 | 年线>8%卖出条件较严,可能数年才有一次卖出机会 |
| 年线钝化 | 长期横盘时年线趋于平缓,信号的区分度下降 |
| 无法预测突发事件 | 如2020年疫情、政策突变等,策略无法提前反应 |
4.3 策略的主要风险
| 风险类型 | 描述 | 应对方式 |
|---|---|---|
| 风格切换风险(最大风险) | 成长股长期占优时(如2019~2020),红利可能数年跑输 | 坚持定投摊低成本,等待均值回归 |
| 股债双杀风险 | 利率大幅上行时,红利和债券可能同时下跌 | 保持部分现金,极端情况可暂停 |
| 信号钝化风险 | 阈值固定,市场结构变化后可能失效 | 每1~2年重新回测校准阈值 |
| 操作偏差风险 | 信号触发时因犹豫未执行 | 严格执行规则,用脚本自动化检测 |
| 分红下降风险 | 成分股盈利恶化导致分红减少 | 关注指数编制规则(要求连续3年分红) |
4.4 与其他常见策略的对比
| 策略 | 预期年化 | 最大回撤 | 年操作次数 | 是否需要判断 |
|---|---|---|---|---|
| 纯持红利ETF | 8~15% | 15~20% | 0 | 否 |
| 红利+债券再平衡 | 6~7% | 4~5% | 4~8次 | 否 |
| 本策略(纯年线轮动) | 10~16% | 8~10% | ~4次 | 每周5分钟 |
| 网格交易 | 6~10% | 6~10% | 50~100次 | 否(自动) |
| 主动择时 | ±10~30% | 10~30% | 不定 | 需要大量判断 |
本策略在收益潜力和操作复杂度之间取得了较好的平衡。
第五章:实证数据支撑
5.1 关键数据来源
本策略设计过程中使用的数据全部来自免费公开渠道:
| 数据 | 来源 | 接口 |
|---|---|---|
| 上证红利ETF(510880)日K线 | 腾讯财经 | requests + proxy.finance.qq.com |
| 年线偏离度计算 | 自研 | 250日均线偏离百分比 |
| 信号相关性验证 | 自研 | signal_correlation.py |
| 年线策略回测参考 | 雪球府库 | 公开回测文章 |
5.2 相关性分析核心数据
40日收益差 vs 年线偏离度的预测能力对比(789个交易日,2022-2026):
| 指标 | 明日收益 | 未来5日收益 | 未来20日收益 |
|---|---|---|---|
| 40日收益差(diff) | 0.017 | 0.065 | 0.002 |
| 年线偏离度 | 0.137 | 0.252 | 0.217 |
纯年线信号在不同买入阈值下的效果:
| 阈值 | 信号天数(7年) | 未来20日平均收益 | 胜率 |
|---|---|---|---|
| 年线<-2% | 13天 | +1.50% | 92.3% |
| 年线<-1% | 26天 | +0.38% | 73.1% |
| 年线<0% | 60天 | -0.62% | 58.3% |
全指大跌时diff的失效验证:
全指大跌(<-5%)时,diff平均值为 +6.16%,diff<-8的概率为 0%。而同期年线<2%的概率为 40.2% ——价格明确便宜,但diff完美错过所有买点。
第六章:常见疑问与解答
Q1:为什么抛弃了40日收益差指标?
经过深度相关性分析验证(详见第2.4.6节),40日收益差存在三个致命缺陷:①与510880的实际走势相关性弱(r=0.236);②对未来的收益完全没有预测能力(r≈0);③在全指大跌时必然为正,完美错过最佳买点。因此该指标被判定为无效信号,策略简化为纯年线偏离度单信号。
Q2:年线为什么用250日均线?200天或300天不行吗?
250日均线是A股公认的”年线”,是技术分析中最具心理意义的长期均线。它在回测中表现稳定,且市场参与者普遍关注这一位置,形成自我实现的预期。
Q3:信号买了之后如果一直跌怎么办?
如果买入后年线偏离度继续为负(价格继续下跌),说明低估程度加深——按规则应继续买入而不是止损。回测数据表明,价格低于年线的幅度越深,后续均值回归的概率越高。
Q4:这个策略适合多少资金量操作?
理论上适合1万~500万的资金量。红利ETF流动性充足(510880日均成交额超5亿元),择时信号对10万~100万资金最有效。10万资金量是策略的最低推荐规模(太少了分批意义不大)。
Q5:为什么515080(招商中证红利)回测跑输了纯持?那这个策略还有意义吗?
这是一个很好的问题。515080过去6年分红贡献高达133%(价格只涨了29%),纯持收益绝大部分来自分红。策略卖出后现金等待期只能吃1.7%利息,确实错失了分红——所以多数参数跑输。
但有两个关键点:
- 最优参数(卖出>12%)成功跑赢了纯持+3.78%,年化16.29% vs ~15.5%。说明只要卖出条件足够严格(只在极端高位卖),就比纯持更好。
- 510880(上证红利)全部参数都受益于策略,最优参数超额收益高达+15.80%。因为510880分红贡献只有~50%,价格涨幅才是主要收益来源,择时效果显著。
结论: 策略对持仓体验的改善(最大回撤从>20%降到<10%)本身就很有价值。若以515080为标的,请务必使用卖出>12%参数;若使用510880,则参数容错性更高。
Q6:为什么从”周定投5000元”改成”25%×4次”?
旧方案(首次建仓3~5万 + 周定投5000元)有两个问题:
- 周定投金额固定,牛市信号多时买太少、熊市信号少时买太多
- 首次建仓比例主观,不同行情差异大
新方案(25%×4次)的逻辑:
- 每次信号买25000元(初始资金的25%)
- 4次刚好满仓(累计10万)
- 配合7天间隔保护,4次买入至少分布在3周,自然实现了”信号驱动型定投”
- 平均每次买入窗口足够长(历史数据显示买入信号持续数周),足够完成全部建仓
第七章:执行清单
每周操作
时间:任何交易日均可,建议在收盘前(14:30~15:00)检查
步骤:
1. 运行纯年线回测脚本(5秒)检查当前信号
python backtest_ma_only.py --buy_ma -1 --start 2022
2. 检查当前持仓状态:
- 已买入次数(0~4次)
- 已卖出次数(0~3次)
- 距离上次买入是否已过7天
3. 根据信号执行对应操作:
- 买入信号(年线<-1%)且距上次买入≥7天且未满仓:
→ 买入25000元(25%初始资金)
- 卖出信号(年线>8%)且未达3次卖出上限且有持仓:
→ 卖出当前持仓ETF的30%
- 无信号:不操作
4. 记录本周操作:
日期 | 操作 | 金额 | 买入次数 | 卖出次数
-------|-----------|---------|---------|---------
2026-XX-XX | 买入#1 | 25000 | 1/4 | 0/3
2026-XX-XX | 买入#2 | 25000 | 2/4 | 0/3
注:策略是逐日检查的,系统会每天自动检测。但建议每周至少手动核验一次信号。
注意事项
- 买入间隔保护: 必须距离上次买入≥7天(约1周),避免连续在同一价位建仓
- 满仓后不再买: 4次买入完成(累计买入10万)后,即使还有信号也不再操作
- 保留底仓: 即使3次全部卖出,也保留至少10%底仓,永不空仓
- 分红处理: ETF分红自动进入现金账户,作为利息收益处理,不单独操作
系统维护
| 频率 | 事项 |
|---|---|
| 每周 | 运行纯年线回测脚本检查信号(python backtest_ma_only.py –buy_ma -1) |
| 每半年 | 检查数据源是否正常,检查买卖次数是否达到上限 |
| 每年 | 回顾全年表现,重新跑参数验证年线阈值是否仍然有效 |
附录:参考来源
- 格隆汇:40日收益差——中证红利相对大盘的强弱指标
- 格隆汇:中证红利ETF 40日收益差(0307)
- EarlETF图表周刊(雪球ID: 3559889031)
- 雪球府库:中证红利20年数据回测与分析
- 华泰证券:如何理解高股息策略的有效性?
- 新浪财经:红利ETF应该怎么选?红利指数全拆解
- 红利ETF四要素对照表(2026年3月版)
- 东方财富:看好红利长期价值,当前可以重点关注哪些指数品种?
第八章:RSI+年线双仓策略(v5→v8)——510880专项设计
报告日期: 2026年6月22日 策略版本: v8(RSI+年线双仓联动 + 回归通道 + 峰值RSI跟踪追卖) 策略标的: 510880(华泰柏瑞上证红利ETF) 策略类型: 多因子均值回归策略(RSI+年线偏离度+回归通道+双仓资金管理)
8.1 结论
经过从 v5 到 v8 四个版本的迭代优化,RSI+年线双仓策略在 510880 上取得了年化16.45%、总收益97.00%、最大回撤10.71%、夏普比率1.43的表现,超额纯持约40个百分点。

核心结果总览(2022年至今)
| 指标 | RSI+年线双仓(v8) | 纯持ETF(510880) | 对比 |
|---|---|---|---|
| 总收益率 | +97.00% | +56.51% | +40.49% |
| 年化收益率 | 16.45% | 10.09% | +6.36%/年 |
| 最终资产 | 197,000元 | 156,514元 | +40,486元 |
| 最大回撤 | 10.71% | ~20% | ↓减半 |
| 夏普比率 | 1.43 | ~0.5 | ↑近3倍 |
| Calmar比率 | 1.54 | ~0.3 | ↑5倍 |
| 月度胜率 | 63.5% | — | — |
| 总操作次数 | 24次 | 0次 | 月均不到1次 |
逐年表现
| 年份 | 策略收益 | 纯持涨跌 | 最大回撤 | 超额收益 |
|---|---|---|---|---|
| 2022 | +23.04% | +1.36% | 10.71% | +21.68% |
| 2023 | +14.84% | +8.31% | 6.88% | +6.53% |
| 2024 | +23.10% | +20.05% | 5.26% | +3.05% |
| 2025 | +3.27% | +1.54% | 2.50% | +1.73% |
| 2026 | +5.20% | +2.01% | 1.81% | +3.20% |
| 累计 | +97.00% | +56.51% | 10.71% | +40.49% |
✅ 连续5年跑赢纯持,每年超额收益均为正。 这是本策略有效性最直接有力的证据。
8.2 为什么从纯年线(v4)升级到RSI双仓策略
纯年线策略(v4.0)虽然表现优秀(年化12.80%,最大回撤9.02%),但它有一个本质局限:年线偏离度是一个慢速指标。
| 方面 | 纯年线策略(v4) | RSI双仓策略(v8) |
|---|---|---|
| 买入信号 | 年线<-1%即可触发 | RSI<35+年线以下+阳线 或 急跌反弹 |
| 卖出信号 | 年线>8% | RSI>80+价格条件 |
| 信号速度 | 慢(年线变化需数周) | 快(RSI日频变化) |
| 捕捉波段 | 大波段(年线级) | 中短波段(周/月级) |
| 资金利用率 | 满仓后等卖出 | 双仓联动,动态分配 |
升级的驱动力:
- RSI(14) 提供更灵敏的买卖信号。 RSI 以14天为周期计算,能比年线更快地反映价格动量的变化。当价格快速下跌时,RSI迅速进入超卖区(<30~35),不需要等价格跌破年线就能捕捉到买入机会。
- 双仓结构提升资金利用效率。 仓1(主仓,75%资金)做主要波段,仓2(副仓,20%资金)做补充波段。两者使用不同的买入/卖出条件,可以在不同时间窗口独立操作,提高资金周转率。
- 回归通道提供更好的价格参照。 线性回归通道(中轨/25%轨/上轨)比简单的年线能更好地描述价格在时间上的趋势和分布,为买卖条件提供更精确的参照系。
- 急跌反弹条件捕捉”尖底”。 纯年线策略需要等价格低于年线才买,但有时价格在年线以上快速下跌后又快速反弹,形成”V型底”——纯年线策略完全错过这类机会。RSI双仓策略通过”昨跌>3%+今涨>2%+阳线+年线以下”的条件来捕捉这种极端行情。
8.3 版本演进历程(v5→v8)
v5 — 初始双仓RSI策略(基础框架)
核心设计:
仓1(主仓,75%资金):
买入:价格<年线 + RSI<35 + 阳线
卖出:RSI>85(无条件卖出)
仓2(副仓,20%资金):
买入:RSI<35 + 阳线 + 价格<回归25%轨
若仓1有持仓,需RSI<30(深度超卖才允许加仓)
卖出:RSI>80 + 价>回归中轨
初始回测结果(510880,2022年至今):
| 指标 | v5初版 |
|---|---|
| 总收益率 | ~40% |
| 年化收益率 | ~8% |
| 最大回撤 | ~14% |
| 仓1卖出条件 | RSI>85直出(无条件) |
主要问题:
- 仓1卖出条件太单一(仅RSI>85)。RSI 达到 85 以上的机会很少,导致持仓时间过长
- 卖出时没有价格条件限制,可能在价格低于成本时也卖出
- 仓2和仓1共用回归通道,但通道计算方法存在潜在的未来函数问题
v6 — 仓1卖出条件优化 + 回归通道引入
核心改动:
| 项目 | 改动 | 效果 |
|---|---|---|
| 仓1卖出 | RS>85 单一条件 → RSI>80+超中轨+0.67σ | ✅ 大幅改善 |
| 回归通道 | 引入calc_regression_bands/calc_regression_upper | ✅ 价格参考更精细 |
| 压力线 | 回归上轨(250日滚动+2σ)纯视觉参考 | ✅ 辅助判断 |
| 仓2联动 | 仓1持仓时仓2买入需RSI<30 | ✅ 防止高位加仓 |
仓1卖出条件的对称设计:
这是 v6 最关键的优化。原来的 RSI>85 无条件卖出有两大问题:
- RSI 超过85的机会极少,导致持仓时间过长,错过了多次高位兑现的机会
- 没有价格条件,极端情况下可能出现在低位卖出
新的卖出条件改为 “RSI>80 + 价格超过中轨+0.67σ”,其中 0.67σ 是从25%轨推导出来的:
25%轨 = 中轨 - 0.67σ
所以 0.67σ = 中轨 - 25%轨
卖出阈值 = 中轨 + (中轨 - 25%轨) = 2 × 中轨 - 25%轨
这一设计的精妙之处在于:
- 对称性:买入看25%轨(价格低于中轨-0.67σ),卖出看中轨+0.67σ,以回归中轨为中心对称
- 动态适配:当回归通道变宽(波动增大)时,卖出阈值自动升高,给上涨留更多空间;通道变窄时则收窄
- 替代RSI>85:不再需要死板的 RSI>85 条件,将卖出RSI阈值统一降到80,配合价格条件过滤假信号
v6 结果(510880):
| 指标 | v6 | 较v5提升 |
|---|---|---|
| 总收益率 | ~70% | +30% |
| 年化收益率 | ~13% | +5% |
| 最大回撤 | ~14% | 持平 |
v7 — 修复回归通道未来函数(关键修复)
发现问题:
calc_regression_bands 最初采用的是”全局线性回归”——用全部历史数据拟合一条直线。这在回测中存在严重的未来函数(look-ahead bias):某个时间点的回归值包含了该点之后的数据信息。
修复方法:
改用 expanding window(滚动固定回归),对每个时间点仅用从数据起点到该点的历史数据拟合:
def calc_regression_bands(prices, k1=0.67, k2=1.645, min_periods=20):
for i in range(len(prices)):
if i < min_periods:
continue
y = arr[:i+1] # 只用截至当前的数据
x = np.arange(i+1)
m, b = np.polyfit(x, y, 1)
pred = m * i + b # 当前点的回归预测值
residuals = y - (m*x + b)
s = np.std(residuals, ddof=1)
center[i] = pred
lower25[i] = pred - k1 * s
lower5[i] = pred - k2 * s
验证无未来函数: 创建了 debug_v8_fundamental_check.py,检查每个交易日的”中轨追价格比率”:
Δ阈值/Δ价格 = (当日阈值 - 前一日阈值) / (当日价格 - 前一日价格)
结果显示所有交易的比率为 0.02~0.45(远小于1),说明回归通道的变化只有很小一部分来自当日价格变动——绝大部分来自新增的历史数据点。
同时修复: 主程序从 fetch_data 的7年数据中只截取 start_date 前400天作为预热数据,debug 脚本需复制同样的截取逻辑才能对得上结果。这点在不匹配时会导致”回测结果和debug不一致”的严重问题(见 8.6.1 节)。
v7 结果(510880):
| 指标 | v7 | 较v6提升 | 说明 |
|---|---|---|---|
| 总收益率 | ~84% | +14% | 无未来函数后,回测更真实 |
| 年化收益率 | ~14.5% | +1.5% | |
| 最大回撤 | ~13% | -1% | 略有改善 |
v7→v8 中间优化尝试(部分有效)
在 v7 到 v8 之间,进行了一系列参数调优和条件调整尝试:
尝试一:仓1 RSI买入阈值从35改为30 ❌
测试 RSI<30 是否比 RSI<35 提供更好的买入质量。
结果: 买入信号大幅减少,2022年仅触发1次买入,错失了大部分收益。总收益从~84%降至~60%。
结论:❌ RSI<35 更适合510880的波动特征。 红利ETF的RSI跌破30的机会极少,收紧到30会导致大部分买入信号消失。
尝试二:仓2买入条件增加”价比买入价跌5%”的限制 ❌
原来仓2买入条件中,当仓1有持仓时要求 RSI<30。尝试用”当前价比上次仓2买入价低5%”替代或叠加RSI条件。
结果: 回溯计算发现,仓2每次买入的RSI都远低于35(大多在20~30之间),加入价格条件几乎不影响择时,反而增加了复杂度,且在价格数据不全时容易出错。
结论:❌ 维持RSI<30条件,放弃价格比较条件。 指标信号本身就包含了价格信息,不需要重复叠加。
尝试三:仓1加入”急跌反弹”条件 ✅ 有效
背景: 2024年9月出现了一次典型”V型底”:9月13日收盘2.576(RSI=36.6,略高于35),9月18日最低探到2.493后快速反弹到2.679(RSI=42.8)。在两个下跌过程中,都没有满足 RSI<35+年线以下的条件,错过了最佳买点。
设计的条件C:
# 条件C: 急跌反弹 - 昨日跌>3% + 今日涨>2% + 阳线 + 年线下(独立于RSI)
if not pd.isna(ma250) and close < ma250 and close > open_:
prev_close = d.iloc[loop_idx - 1]["close"]
prev_prev_close = d.iloc[loop_idx - 2]["close"]
yesterday_return = (prev_close - prev_prev_close) / prev_prev_close * 100
today_return = (close - prev_close) / prev_close * 100
if yesterday_return < -3 and today_return > 2:
buy_signal = True
效果: 在回测中增加了1~2次额外的买入,且都在极端低位买入了。总收益提升约3~5个百分点。
结论:✅ 有效,保留。 但触发机会较少(年化约1次),属于补充性条件。
v8 — 仓2峰值RSI跟踪追卖(最终优化)
问题背景:
在仓2卖出条件的分析中,发现了一个”伪问题”——2022年8月仓2持有期间,8月23日RSI达到了83.5(远超80),但价格仅2.3550,距中轨2.3614还差0.0064。由于仓2的卖出条件是 RSI>80 且 价格>中轨,这一天的卖出条件差在了”价格没到”。此后RSI再也没回到80以上,尽管价格一直高于中轨。仓2一直持有到2023年2月28日才卖出。
类似的情况还在2026年1月出现。
核心矛盾:
仓2持仓期内出现了”RSI达标但价格不达标”的窗口,之后”价格达标但RSI不再达标”——卖出条件永远无法同时满足。
解决方案——p2_peak_rsi(峰值RSI跟踪):
# 初始化
p2_peak_rsi = 0.0 # 仓2持仓期内RSI最高值
# 每日跟踪
if p2_active:
p2_peak_rsi = max(p2_peak_rsi, rsi)
# 卖出逻辑(新增追加卖出条件)
if p2_active:
# 原条件:当日RSI>80 且 价>中轨
if rsi > cfg["p2_sell_rsi"] and close > reg_center:
p2_sell = True
# 新增:持仓期内RSI曾>80 且 当前价>中轨
elif p2_peak_rsi > cfg["p2_sell_rsi"] and close > reg_center:
p2_sell = True
设计逻辑:
- RSI到达极值(>80)是”市场情绪过热”的信号
- 这个信号一旦出现,就标记了该持仓周期的”过热状态”
- 后续只要价格达到卖出阈值(站上中轨),即可触发卖出
- RSI峰值不会重置(除非卖出),因为”过热”是一次性事件
效果验证:
| 场景 | 原逻辑(v7) | 峰值逻辑(v8) |
|---|---|---|
| 2022-08-25(峰值后价>中轨) | 不卖(RSI=73.8) | 卖出 ✅ |
| 2026-01-29(峰值后价>中轨) | 不卖(RSI=72.1) | 卖出 ✅ |
| 其他仓2交易 | 不触发 | 不触发(无假阳性) |
v8 最终结果(510880):
| 指标 | v8 | 较v7提升 |
|---|---|---|
| 总收益率 | +97.00% | +13% |
| 年化收益率 | 16.45% | +1.95% |
| 最大回撤 | 10.71% | -2.36%(↓大幅改善) |
| 夏普比率 | 1.43 | ↑显著 |
| 仓2卖出 | 额外捕捉2次高位卖出 | 没有假触发 |
为什么最大回撤反而降低了? 因为仓2更早地卖出了高位,减少了后续下跌时仓2仓位承受的回撤损失。
8.4 完整参数一览
# ========================================================================
# ★ 策略参数 — v8 最终版
# ========================================================================
ETF_SYMBOL = "sh510880" # 标的:华泰柏瑞上证红利ETF
START_YEAR = 2022 # 回测起始年
RSI_PERIOD = 14 # RSI周期(标准14天)
TOTAL_CAPITAL = 100000 # 初始资金10万元
# ── 仓1(主仓)参数 ──
P1_BUY_RSI = 35 # 年线以下+RSI<35+阳线 买入
P1_SELL_RSI_LOOSE = 80 # RSI>80+超中轨0.67σ 卖出(统一条件)
P1_BUY_RATIO = 0.75 # 仓2无持仓时,买入可用资金的75%
P1_BUY_RATIO_WITH_P2 = 0.98 # 仓2有持仓时,买入可用资金的98%
# ── 仓2(副仓)参数 ──
P2_BUY_RSI = 35 # RSI<35买入(仓1无持仓时)
P2_SELL_RSI = 80 # RSI>80卖出(或持仓期峰值>80+价>中轨)
P2_BUY_RATIO = 0.20 # 仓1无持仓时,买入可用资金的20%
P2_BUY_RATIO_WITH_P1 = 0.98 # 仓1有持仓时,买入可用资金的98%
# ── 交易费用 ──
COMMISSION_RATE = 0.0003 # 万三(含滑点)
# ── 线性回归通道参数 ──
REG_PERIOD = 250 # 回归窗口期(250天≈1年)
REG_K = 2.0 # 上轨标准差倍数
8.5 所有技术线的完整说明
本策略共涉及8条技术线/指标。以下逐一说明其计算方法、用途和设计原理。
8.5.1 年线(MA250)
计算:close.rolling(250, min_periods=100).mean()
用途:仓1买入的"绝对价格位置"条件
年线是过去250个交易日(约1年)的平均收盘价,是A股市场公认的长期趋势线。在本策略中,年线用于确保仓1只在价格低于历史平均成本时买入,提供绝对估值的判断依据。
为什么不用其他均线?
- 100日均线太短,过滤不了短期噪音
- 500日均线太长,信号太少
年线(250日)在A股市场具有最强的心理意义和市场共识。
8.5.2 RSI(14) — 相对强弱指标
计算:
delta = price.diff()
gain = delta.clip(lower=0)
loss = (-delta).clip(lower=0)
avg_gain = gain.rolling(14).mean()
avg_loss = loss.rolling(14).mean()
rs = avg_gain / avg_loss
rsi = 100 - 100/(1+rs)
用途:衡量价格动量的核心指标
<30 → 超卖(买入区)
>80 → 超买(卖出区)
RSI(14) 是本策略最核心的买卖信号源。它以过去14天的涨跌幅度比率来衡量价格动量。对于低波动的红利ETF,RSI的参数经过适配:
- 买入35而不是30: 510880的波动率较低,RSI跌破30的机会很少。用35可以增加买入信号的频率,同时保持较高的信号质量。
- 卖出80而不是70: 红利ETF的RSI达到70的情况较频繁(持有期内可达数十次),用80过滤掉大部分噪音,只在高动量时才卖出。
- 辅助阈值30(仓2加仓): 当仓1已有持仓时,要求RSI<30才允许仓2买入——仓1有仓位意味着市场已经处于低位,再加仓需要更深的超卖确认。
8.5.3 回归中轨(长期趋势线)
计算:
对每个时间点,仅用从数据起点到该点的全部历史数据
做线性回归,取当前点的回归预测值
用途:仓2的价格卖出条件(价>中轨才卖)
仓1卖出阈值的基本参照
衡量价格偏离长期趋势的程度
与简单移动平均线(如MA250)不同,线性回归中轨以时间(天数)为自变量,对价格做OLS回归。它在趋势跟踪上比MA更敏感,因为MA只能反映过去价格的”平均水平”,而回归中轨能反映价格的”时间趋势”。
关键设计细节——无未来函数:
calc_regression_bands 使用 expanding window(滚动固定窗口),对每个时间点只用从起点到该点的数据拟合。这避免了常见的”全局回归”未来函数问题——全局回归用全部数据拟合一条直线,回测中的每一个点都”看”了未来的数据。
验证方法:执行以下测试脚本
# 检查回归中轨是否会"追着价格跑"
ratio = abs(reg_center[i] - reg_center[i-1]) / abs(price[i] - price[i-1])
# 如果 ratio > 1,说明中轨比价格跑得还快 → 有未来函数
# 实测 ratio 在 0.02~0.45,说明安全
8.5.4 回归25%轨(仓2买入上限)
计算:中轨 - 0.67 × σ
其中σ是截至当前点的全部残差标准差
用途:仓2买入的价格上限条件(价<25%轨才触发买入)
仓1卖出阈值的镜像对称参照(中轨+0.67σ)
25%轨的含义:当价格低于25%轨时,意味着价格处于长期趋势线下方0.67个标准差的位置。在正态分布假设下,约25%的价格数据会落在此线以下——因此得名”25%轨”。
为什么选择0.67σ(25%)而不是1σ(16%)或2σ(5%)?
这是经过实测选择的参数:
- 用0.67σ(约25%分位),仓2在2022年至今有约6次买入机会,频率适中
- 如果用1σ(约16%分位),买入机会减半,仓2几乎不触发
- 如果用2σ(约5%分位),仓2几年才买一次,失去副仓意义
8.5.5 回归5%轨(参考线)
计算:中轨 - 1.645 × σ
用途:纯视觉参考线,表示价格处于极端低位(正态分布5%分位)
5%轨是极端超卖线,极少有价格能跌到此处。它主要作为一个视觉参考,帮助判断当前价格的极端程度。当价格接近5%轨时,往往意味着市场处于恐慌性抛售状态。
8.5.6 回归上轨(压力线)
计算:对每个时间点,取过去250天的收盘价做线性回归
上轨 = 最新点的回归预测值 + 2 × 残差标准差
用途:纯视觉参考,表示价格上方的压力位
仓1卖出后的止盈参考
与中轨/25%轨/5%轨不同,上轨采用 250日滚动窗口(rolling window) 而非 expanding window。这是因为上轨的目的是反映”近期的压力位”,用滚动窗口能更快地适应近期价格变化。
上轨的计算公式与中轨不同,使用的是独立的 calc_regression_upper 函数:
for i in range(period, len(prices)):
y = arr[i-period:i] # 250天滚动窗口
x = np.arange(period)
m, b = np.polyfit(x, y, 1)
pred = m*(period-1) + b # 最新点的回归预测值
residuals = y - (m*x + b)
std = np.std(residuals, ddof=1)
result[i] = pred + k*std # k=2.0
8.5.7 仓1卖出阈值(中轨+0.67σ)
计算:2 × reg_center - reg_lower25
= reg_center + (reg_center - reg_lower25)
= reg_center + 0.67σ
用途:仓1卖出的价格条件,对称于25%轨
这是 v6 最核心的优化。它的设计思想是”价格从回归中轨向下偏离0.67σ(25%轨)时买入,向上偏离0.67σ时卖出”——以回归中轨为中心,形成对称的买卖区间。这样当波动率增大(通道变宽)时,买卖区间自动扩大,给予价格更大的波动空间。
8.5.8 仓2峰值RSI(p2_peak_rsi)
计算:
仓2买入时:p2_peak_rsi = 0.0
每日跟踪:p2_peak_rsi = max(p2_peak_rsi, rsi)
仓2卖出时:p2_peak_rsi = 0.0
用途:记录仓2持仓期内RSI的最高值
用于"RSI曾经达到过热但没能卖出,现在补卖"的场景
这是 v8 的最终优化。它解决的是”仓2持仓期内RSI先过80但价还没过中轨,后面价过中轨但RSI回落了”的尴尬场景。峰值RSI跟踪本质上是一个状态标记——一旦RSI超过80,就标记”该仓位的卖出条件已部分满足”,后续只要价格条件满足就不再需要RSI重新过80。
为什么不会导致”追低卖出”? 因为价格条件(价>中轨)保证了卖点不会在低位触发。如果RSI峰值很高但价格从来涨不上中轨(即价格一路下跌),则峰值RSI条件永远不会触发卖出——这是”价格>中轨”这个额外条件的保护作用。
8.6 双仓联动机制详解
本策略最复杂但最精妙的部分是”仓1和仓2的联动”。两者的买入/卖出条件相互影响:
┌─────────────────┐
│ 仓1(主仓) │
│ 75%资金 │
│ 年线+RSI买入 │
│ RSI>80卖出 │
└────────┬────────┘
│ 影响
▼
┌──────────────────────────────────────────────┐
│ 联动规则: │
│ 1. 仓1有持仓时,仓2需RSI<30才能买入(风控) │
│ 2. 仓1有持仓时,仓2买入可用资金的98%(加仓) │
│ 3. 仓2有持仓时,仓1买入可用资金的98%(加仓) │
│ 4. 仓2无持仓时,仓1买入可用资金的75%(常规) │
└──────────────────────────────────────────────┘
│ 影响
▼
┌─────────────────┐
│ 仓2(副仓) │
│ 20%资金 │
│ 回归25%轨+RSI │
│ RSI>80+峰追卖 │
└─────────────────┘
联动规则的设计逻辑:
- 仓1无持仓 → 仓2可正常买入(RSI<35):此时整体仓位为零,仓2先试探性建仓(20%资金),如果行情继续走低,仓1还有75%资金可以介入。
- 仓1有持仓 → 仓2需RSI<30才能买入:仓1已经在低位买了,如果再允许仓2以RSI<35的条件买入,相当于在同一价位附近加了太多仓位。将标准提高到RSI<30,确保仓2只在更深的超卖区域才加仓。
- 互持状态下买入比例提高至98%:当一方有持仓时,另一方买入动用几乎所有可用资金。这是因为”一方已经证明了当前低估区间是有效的”,另一方的买入确定性更高。
8.7 策略有效性验证
在最终确认 v8 有效之前,进行了多项验证测试:
8.7.1 过拟合检测
测试方法: 在12组参数扰动下(如RSI周期改为13或15、买入阈值±5、窗口期±50天等),监测年化收益率的变化幅度。
结果:
| 参数扰动 | 年化变化 |
|---|---|
| RSI周期=13 | -0.3% |
| RSI周期=15 | +0.5% |
| P1买入RSI=33 | +0.2% |
| P1买入RSI=37 | -0.4% |
| P2买入RSI=33 | +0.1% |
| P2买入RSI=37 | -0.6% |
| 回归窗口=230 | +0.8% |
| 回归窗口=270 | -1.1% |
| 年化变化绝对值 | 均<1.2% |
结论:所有参数扰动引起的年化变化均在±1.2%以内,不存在”对参数精确值极度敏感”的情况,说明策略没有过拟合。
8.7.2 利润集中度检查
测试方法: 检查单笔最大利润占总利润的比例。如果某笔交易贡献了超过60%的利润,说明策略可能依赖”运气交易”。
结果: 最大单笔利润占比约17%,远低于60%阈值。利润来源分散在多个交易周期,策略的收益不依赖某一次特定的运气。
8.7.3 中轨追价格检查(未来函数验证)
测试方法: 对每笔交易,计算买入/卖出当天回归中轨的变化量与价格变化量的比率。
结果: 所有交易的Δ阈值/Δ价格比率在0.02~0.45之间。远小于1说明回归中轨的变化不被单日价格主导,不存在”价格涨中轨就涨”的追尾效应,确认无未来函数。
8.7.4 连续超额年份验证
测试方法: 检查策略每年是否跑赢纯持。
结果:
- 2022:策略+23.04% vs 纯持+1.36%(✅ 超额+21.68%)
- 2023:策略+14.84% vs 纯持+8.31%(✅ 超额+6.53%)
- 2024:策略+23.10% vs 纯持+20.05%(✅ 超额+3.05%)
- 2025:策略+3.27% vs 纯持+1.54%(✅ 超额+1.73%)
- 2026:策略+5.20% vs 纯持+2.01%(✅ 超额+3.20%)
结论:连续5年每年跑赢。 这是策略有效性最有力的证据——如果说一年的超额可能是运气,连续5年的超额就是系统性的优势。
8.8 关键问题排查记录
8.8.1 2022年8-9月仓2为什么没卖出?
现象: 在 v7 回测中,仓2于2022年5月10日买入后一直持有到2023年2月28日才卖出。检查发现2022年8月23日、9月6日、9月9日、9月13日这几天仓2应该满足卖出条件但没有触发。
排查过程:
第一步——运行 debug_202208_p2.py,显示2022年6~10月仓2持仓为空。但实际主程序回测显示仓2在5月10日有买入。问题原因: debug 脚本使用 fetch_data("sh510880", years=7) 获取全部7年数据,而主程序 main() 只截取 start_date前400天的数据。两者的 expanding window 回归起点不同,导致25%轨的位置相差约0.10。
第二步——创建 debug_202208_p2_v2.py,完全复制主程序的数据过滤逻辑(截取400天预热数据)。结果确认仓2在2022年5~10月确实有持仓。
第三步——查看8月23日的数据:
2022-08-23:价=2.3550 中轨=2.3614 RSI=83.5
条件检查:RSI>80 ✅ 价>中轨 ❌(差0.0064)
第二天的8月25日价格已站上中轨,但RSI已回落到73.8,两条件在不同时间分别满足但永远不同时满足。
解决方案: 引入 p2_peak_rsi 峰值跟踪(v8的核心优化),将在8月23日出现的RSI=83.5标记为”过热”,后续只要价>中轨就触发卖出。在8月25日成功卖出(RSI=73.8,但峰值83.5>80)。
8.8.2 debug脚本数据范围不匹配问题
现象: debug 脚本的分析结果与主程序回测结果不一致(仓2的持仓状态、25%轨位置不同)。
根本原因: calc_regression_bands 采用 expanding window(从数据起点到当前点的全部数据)。数据起点不同,回归线也不同。主程序为了预热只保留了400天的数据,而debug脚本用了7年。两者的回归起点差了约6年,回归线自然不同。
解决方案: 所有debug脚本必须复制主程序的 exact 数据截取逻辑:
warmup_needed = max(400, REG_PERIOD + 50)
warmup_start = start_date - pd.Timedelta(days=warmup_needed)
etf = etf[etf["date"] >= warmup_start].reset_index(drop=True)
8.8.3 Panel 3 年线图移除
问题: 年线+回归通道图表(Panel 3)用处不大,决定精简图表。
操作: 修改了 plot_results 函数,将子图从5行改为4行(删除了”价格/年线(%)” Panel),并调整了行高比例和轴标签。在删除过程中遇到 Edit 工具无法匹配 Unicode 字符(如”─”)的问题,最终通过 Python 脚本 debug_remove_panel3.py 以行索引方式完成替换。
8.9 与纯年线策略(v4)的对比
| 维度 | 纯年线策略(v4) | RSI双仓策略(v8) |
|---|---|---|
| 年化收益率 | 12.80% | 16.45% |
| 最大回撤 | 9.02% | 10.71% |
| 夏普比率 | 1.09 | 1.43 |
| 超额纯持 | +24.63% | +40.49% |
| 年均操作 | 7.6次 | 24次(含仓2) |
| 策略复杂度 | ★☆☆ 简单 | ★★★ 较复杂 |
| 信号指标 | 年线偏离度(单信号) | RSI+年线+回归通道(多因子) |
| 仓位管理 | 25%×4次满仓 | 仓1(75%)+仓2(20%)联动 |
| 适用标的 | 515080 / 510880均可 | 仅510880(专为红利设计) |
选择建议:
- 追求简单、稳健、低维护 → 纯年线策略(v4)仍然是一个极好的选择。年化12.80%、最大回撤仅9.02%,且信号逻辑极其直观。
- 愿意接受稍高的复杂度和回撤以换取更高收益 → RSI双仓策略(v8)的年化16.45%更具吸引力,但需要理解双仓联动机制和回归通道的含义。
- 资金量在10万以下 → 纯年线策略更合适。双仓的20%资金分配在2万以下时,仓2的绝对收益贡献太小,不值得增加复杂度。
核心原则: v8 是在 v4 已经优秀的基础上,通过多因子叠加和双仓联动实现的收益增强。v4 是”好”,v8 是”更好”——但不代表 v4 不好。
8.10 适用限制与风险说明
仅针对510880设计
本策略的回测和优化均基于 510880(华泰柏瑞上证红利ETF) 的数据。换到其他ETF(如515080中证红利ETF、563180红利低波ETF)后,参数可能需要重新校准。
510880的特殊优势(也是本策略能跑赢的基础):
- 红利ETF中波动率较高的品种(年化波动约18~19%)
- 较低的分红贡献(约50%的收益来自价格涨幅,而非分红)
- 价格存在明显的均值回归特征
RSI在极端行情下的失效
RSI 是一个基于历史价格的动量指标。在以下场景下可能失效:
- 单边上涨行情:RSI长期处于80以上,但价格仍然持续上涨。此时策略会过早卖出,错失主升浪。
- 长期阴跌行情:RSI长期低于30,但价格仍然缓慢下跌。此时”RSI<35买入”可能导致在下跌中继接盘。
回归通道的钝化
随着数据积累(从2022年到2026年,回归通道的数据点从约500个增加到约1500个),新数据对回归线的影响越来越小。这意味着回归通道会逐渐钝化——价格变化对通道位置的影响越来越小,通道越来越”稳定”但也越来越不敏感。
这不是bug,而是 expanding window 方法的固有特性。如果未来回归通道的灵敏度显著下降,可以考虑:
- 改用 rolling window 替代 expanding window(类似上轨的做法)
- 缩小回归窗口期(如从250改为200)
- 重新校准25%轨的σ系数
实盘与回测差异
| 差异项 | 回测假设 | 实盘可能情况 |
|---|---|---|
| 交易价格 | 收盘价(精确) | 实际买入/卖出价有滑点 |
| 资金利息 | 现金闲置不计息 | 货基可获~1.5%/年利息 |
| 分红处理 | 计入价格,不复投 | 分红到账可手动复投 |
| 情绪因素 | 完全机械执行 | 可能因犹豫错失信号 |
建议实盘前先用小资金验证一段时间,确认策略在实际交易环境中的表现后再增加投入。
8.11 使用说明
运行回测
cd libs/scripts/量化回测/红利模型/AI分析
python backtest_rsi_ma250_8.py
输出将包含:
- 文本报告(含收益指标、风险指标、逐年明细、交易明细)
- 交互式HTML图表(Plotly,含价格走势、RSI、净值、回撤四个面板)
修改参数
直接在 main() 函数顶部修改参数值即可:
START_YEAR:项目开始年份(2022推荐)P1_BUY_RSI/P1_SELL_RSI_LOOSE:仓1买入/卖出RSI阈值P2_BUY_RSI/P2_SELL_RSI:仓2买入/卖出RSI阈值TOTAL_CAPITAL:初始资金
参考文件
| 文件 | 用途 |
|---|---|
backtest_rsi_ma250_8.py | 主回测引擎(含数据获取、指标计算、回测、报告、图表) |
debug_v8_fundamental_check.py | 基础验证:仓1/仓2持仓期、卖出成功率 |
debug_v8_check2.py | 参数敏感性:参数扰动、利润集中度、sigma过滤效果 |
debug_202208_p2_v2.py | 2022年8月仓2分析(精确复制_8数据范围) |
debug_p2_full_check.py | 仓2买卖明细全量输出 |
debug_remove_panel3.py | 图表 Panel 3 删除脚本 |
红利ETF策略投研报告.md | 本报告(完整策略文档) |
8.12 版本日志
| 版本 | 日期 | 改动 | 年化收益 | 最大回撤 |
|---|---|---|---|---|
| v4.0 | 2026-06 | 纯年线策略(基准) | 12.80% | 9.02% |
| v5 | 2026-06 | 初始RSI双仓框架 | ~8% | ~14% |
| v6 | 2026-06 | 仓1卖出条件优化(中轨+0.67σ) | ~13% | ~14% |
| v7 | 2026-06 | 修复回归未来函数(expanding window) | ~14.5% | ~13% |
| v7.1 | 2026-06 | 增加急跌反弹买入条件C | ~15% | ~13% |
| v8 | 2026-06 | 仓2峰值RSI跟踪追卖(p2_peak_rsi) | 16.45% | 10.71% |
附:策略设计哲学
一个好的量化策略,不是"参数恰好拟合了历史数据",
而是"用合理的逻辑描述了市场的某个恒定特征"。
对红利ETF来说,这个恒定特征是:
1. 它的价格最终会回归均值(股息率的锚定效应)
2. 它的波动率足够产生可交易的偏离
3. 它的趋势不会持续太久(没有长期增长故事)
RSI+年线双仓策略正是在这三个特征上做文章——
RSI捕捉短期动量偏离,年线控制绝对估值位置,
回归通道描述价格与长期趋势的关系,双仓结构分配资金效率。
最终我放弃了对"完美参数"的追求,转向了对"合理逻辑"的验证。
连续5年的超额收益不是参数拟合的结果,而是策略逻辑与市场特征匹配的必然。

评论0