红利ETF多策略研究:从年线轮动到RSI双仓——设计逻辑、回测验证与操作框架

报告日期: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.847/10
红利指数1.666/10
中证红利0.688/10
红利低波100-0.446/10
红利质量0.407/10
标普A股红利-0.187/10

选择中证红利(000922)作为信号指数的理由:

  1. 覆盖沪深两市,代表性最强
  2. 过去10年中有8年实现正收益,稳定性最高
  3. 对应ETF(515080)规模超110亿元,流动性充裕
  4. 相关性:与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)
  • 指数代码 sh000922sh 表示上海市场,000922 为中证红利指数
  • 指数代码 sh000985sh 表示上海市场,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元/次)”,回测发现存在两个问题:

  1. 周定投金额固定,牛市信号多时买入不足、熊市信号少时买得太多
  2. 首次建仓比例主观,不同行情下的表现差异大

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, 年线<3diff>5, 年线>12165.75%16.29%9.93%+3.78%0.78
2卖出>10%diff<-5, 年线<3diff>5, 年线>10152.58%15.38%9.93%-9.39%0.75
3买入严格diff<-5, 年线<0diff>5, 年线>8130.23%13.75%9.93%-31.74%0.73
4平衡型diff<-5, 年线<3diff>5, 年线>8126.83%13.48%9.93%-35.14%0.67
5积极型diff<-5, 年线<5diff>5, 年线>5126.58%13.46%9.93%-35.39%0.67
6年线<1%diff<-5, 年线<1diff>5, 年线>8124.79%13.33%9.93%-37.18%0.68
7年线<2%diff<-5, 年线<2diff>5, 年线>8124.79%13.33%9.93%-37.18%0.68
8保守型diff<-8, 年线<0diff>5, 年线>1033.69%4.59%9.93%+3.62%0.27

纯持ETF参考:总收益 161.97%,年化 ~15.5%,同期指数价格涨幅仅 28.82%(分红贡献 ~133%)


华泰柏瑞上证红利ETF (510880) 回测结果:

排名参数名买入阈值卖出阈值总收益年化最大回撤超额收益夏普
1卖出>12%diff<-5, 年线<3diff>5, 年线>1294.57%9.86%8.37%+15.80%0.45
2卖出>10%diff<-5, 年线<3diff>5, 年线>1085.14%9.09%8.37%+6.38%0.41
3买入严格diff<-5, 年线<0diff>5, 年线>869.58%7.75%8.37%-9.19%0.35
4平衡型diff<-5, 年线<3diff>5, 年线>868.68%7.67%8.37%-10.08%0.33
5积极型diff<-5, 年线<5diff>5, 年线>566.70%7.49%8.37%+7.10%0.32
6年线<1%diff<-5, 年线<1diff>5, 年线>865.49%7.38%8.37%-13.27%0.32
7年线<2%diff<-5, 年线<2diff>5, 年线>865.49%7.38%8.37%-13.27%0.32
8保守型diff<-8, 年线<0diff>5, 年线>1036.87%4.53%8.37%+5.21%0.27

纯持ETF参考:总收益 78.77%,年化 ~8.5%,同期指数价格涨幅 ~29%(分红贡献 ~50%)


关键发现:

  1. 卖出阈值是决定收益的核心变量。 买入端参数几乎不影响结果(所有组合的买入信号高度重叠),真正拉开差距的是卖出的年线偏离度阈值
    • 年线>12%卖出 → 年化最高,给足上涨空间
    • 年线>8%卖出 → 过严,2021年卖飞导致超额为负
    • 年线>5%卖出 → 频繁卖出,收益最低
  2. 515080 大多数参数跑输纯持的原因: 中证红利分红极高(6年贡献133%),卖出后现金闲置只吃1.7%利息,错失了后续分红。而卖出>12%因为卖出条件极严(几乎只在极端高位卖出),大部分时间持仓吃分红,所以跑赢纯持。
  3. 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_s8diff<-6 + 年线<1%diff>0 + 年线>8%2.55%7.24%✅ 510880
b6ma1_s10diff<-6 + 年线<1%diff>0 + 年线>10%2.55%6.34%✅ 510880
b6ma1_s12diff<-6 + 年线<1%diff>0 + 年线>12%2.55%4.73%✅ 510880
b6ma2_s8diff<-6 + 年线<2%diff>0 + 年线>8%3.09%10.56%✅ 510880
b6ma2_s10diff<-6 + 年线<2%diff>0 + 年线>10%3.09%9.63%✅ 510880
b6ma2_s12diff<-6 + 年线<2%diff>0 + 年线>12%3.09%7.48%✅ 510880
b8ma1_s8diff<-8 + 年线<1%diff>0 + 年线>8%0%4.80%✅ 510880
b8ma1_s10diff<-8 + 年线<1%diff>0 + 年线>10%0%3.62%✅ 510880
b8ma1_s12diff<-8 + 年线<1%diff>0 + 年线>12%0%1.89%✅ 510880
b8ma2_s8diff<-8 + 年线<2%diff>0 + 年线>8%3.05%12.49%✅ 510880
b8ma2_s10diff<-8 + 年线<2%diff>0 + 年线>10%3.05%12.49%✅ 510880
b8ma2_s12diff<-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更适合量化策略?

  1. 价格驱动力不同: 510880跟踪上证红利(000015),集中在周期行业(煤炭、钢铁、银行),估值弹性大,价格摆动幅度更大,为”低估买、高估卖”提供了更充分的空间。515080跟踪的中证红利(000922)包含更多防御性行业,波动偏小。
  2. 卖出信号有效性: 515080在2022年至今几乎不触发卖出信号(年线>8%),导致策略无法兑现超额收益。510880则能正常触发卖出,实现”低位买入→高位卖出”的完整循环。
  3. 参数容错率高: 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.0170.0650.002
年线偏离度0.1370.2520.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在不同市场环境下的致命问题

市场环境天数平均diffdiff<-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.041次2.1172.495+17.9%
② 2022.04→2023.043次2.2622.593+14.6%
③ 2023.12→2024.022次2.5202.817+11.8%
④ 2024.08→2024.104次2.6373.073+16.5%
⑤ 2025.02→2025.072次2.8143.158+12.2%
⑥ 2025.09→2026.031次2.9393.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具有以下特征:

  1. 股息率锚定:价格偏离合理区间时,股息率会吸引或驱逐资金
  2. 行业结构稳定:以银行、煤炭、公用事业为主,盈利增长有限
  3. 机构资金主导:险资、养老金以股息率为锚做配置,形成天然的”低买高卖”机制

这些特征决定了红利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 与其他常见策略的对比

策略预期年化最大回撤年操作次数是否需要判断
纯持红利ETF8~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.0170.0650.002
年线偏离度0.1370.2520.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%利息,确实错失了分红——所以多数参数跑输。

但有两个关键点:

  1. 最优参数(卖出>12%)成功跑赢了纯持+3.78%,年化16.29% vs ~15.5%。说明只要卖出条件足够严格(只在极端高位卖),就比纯持更好。
  2. 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)
每半年检查数据源是否正常,检查买卖次数是否达到上限
每年回顾全年表现,重新跑参数验证年线阈值是否仍然有效

附录:参考来源


第八章: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个百分点。

image-20260622165954458

核心结果总览(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日频变化)
捕捉波段大波段(年线级)中短波段(周/月级)
资金利用率满仓后等卖出双仓联动,动态分配

升级的驱动力:

  1. RSI(14) 提供更灵敏的买卖信号。 RSI 以14天为周期计算,能比年线更快地反映价格动量的变化。当价格快速下跌时,RSI迅速进入超卖区(<30~35),不需要等价格跌破年线就能捕捉到买入机会。
  2. 双仓结构提升资金利用效率。 仓1(主仓,75%资金)做主要波段,仓2(副仓,20%资金)做补充波段。两者使用不同的买入/卖出条件,可以在不同时间窗口独立操作,提高资金周转率。
  3. 回归通道提供更好的价格参照。 线性回归通道(中轨/25%轨/上轨)比简单的年线能更好地描述价格在时间上的趋势和分布,为买卖条件提供更精确的参照系。
  4. 急跌反弹条件捕捉”尖底”。 纯年线策略需要等价格低于年线才买,但有时价格在年线以上快速下跌后又快速反弹,形成”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

设计逻辑:

  1. RSI到达极值(>80)是”市场情绪过热”的信号
  2. 这个信号一旦出现,就标记了该持仓周期的”过热状态”
  3. 后续只要价格达到卖出阈值(站上中轨),即可触发卖出
  4. 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. 仓1无持仓 → 仓2可正常买入(RSI<35):此时整体仓位为零,仓2先试探性建仓(20%资金),如果行情继续走低,仓1还有75%资金可以介入。
  2. 仓1有持仓 → 仓2需RSI<30才能买入:仓1已经在低位买了,如果再允许仓2以RSI<35的条件买入,相当于在同一价位附近加了太多仓位。将标准提高到RSI<30,确保仓2只在更深的超卖区域才加仓。
  3. 互持状态下买入比例提高至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.091.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 方法的固有特性。如果未来回归通道的灵敏度显著下降,可以考虑:

  1. 改用 rolling window 替代 expanding window(类似上轨的做法)
  2. 缩小回归窗口期(如从250改为200)
  3. 重新校准25%轨的σ系数

实盘与回测差异

差异项回测假设实盘可能情况
交易价格收盘价(精确)实际买入/卖出价有滑点
资金利息现金闲置不计息货基可获~1.5%/年利息
分红处理计入价格,不复投分红到账可手动复投
情绪因素完全机械执行可能因犹豫错失信号

建议实盘前先用小资金验证一段时间,确认策略在实际交易环境中的表现后再增加投入。


8.11 使用说明

运行回测

cd libs/scripts/量化回测/红利模型/AI分析
python backtest_rsi_ma250_8.py

输出将包含:

  1. 文本报告(含收益指标、风险指标、逐年明细、交易明细)
  2. 交互式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.py2022年8月仓2分析(精确复制_8数据范围)
debug_p2_full_check.py仓2买卖明细全量输出
debug_remove_panel3.py图表 Panel 3 删除脚本
红利ETF策略投研报告.md本报告(完整策略文档)

8.12 版本日志

版本日期改动年化收益最大回撤
v4.02026-06纯年线策略(基准)12.80%9.02%
v52026-06初始RSI双仓框架~8%~14%
v62026-06仓1卖出条件优化(中轨+0.67σ)~13%~14%
v72026-06修复回归未来函数(expanding window)~14.5%~13%
v7.12026-06增加急跌反弹买入条件C~15%~13%
v82026-06仓2峰值RSI跟踪追卖(p2_peak_rsi)16.45%10.71%

附:策略设计哲学

一个好的量化策略,不是"参数恰好拟合了历史数据",
而是"用合理的逻辑描述了市场的某个恒定特征"。

对红利ETF来说,这个恒定特征是:
1. 它的价格最终会回归均值(股息率的锚定效应)
2. 它的波动率足够产生可交易的偏离
3. 它的趋势不会持续太久(没有长期增长故事)

RSI+年线双仓策略正是在这三个特征上做文章——
RSI捕捉短期动量偏离,年线控制绝对估值位置,
回归通道描述价格与长期趋势的关系,双仓结构分配资金效率。

最终我放弃了对"完美参数"的追求,转向了对"合理逻辑"的验证。
连续5年的超额收益不是参数拟合的结果,而是策略逻辑与市场特征匹配的必然。
原文链接:http://www.itawp.com/621.html,转载请注明出处。
0

评论0

没有账号?注册  忘记密码?