确认越多越好吗?多信号金叉死叉框架的实测手记
"多指标共振才入场"、"大周期定方向,小周期找买点"——技术分析里这两句话几乎是公理。直觉上无懈可击:多个证据总比一个强。但很少有人问:每加一层确认,到底值多少收益? 这篇手记用一套可复现的回测框架,在 500增强ETF(562500)五年日线数据上把这个问题量化了一遍,答案和直觉相差甚远。
配套代码在仓库 example/2026/10/21-1/:纯指标库 + 数据管道 + 回测引擎共约一千行,34 个单测,全部数字可离线复现。
框架:一个下午能复现的回测管道
三段式结构:indicators.py(纯指标函数库)→ fetch_data.py(akshare 拉数、指标计算落 CSV)→ analyze.py(回测报告)。两条铁律贯穿始终:
- 无未来函数:信号在 T 日收盘判定,T+1 日开盘价成交——决策信息与执行价格在时间上严格分离
- 口径对齐券商:EMA 递推(初值 = 首日值,α = 2/(N+1))、MACD 柱乘 2,与东财/同花顺一致;纯 Python 手工递推全量验证过,1163 根K线最大偏差 1e-17
金叉死叉检测的向量化实现,核心就四行:
diff = fast - slow
prev = diff.shift(1)
golden = (prev <= 0) & (diff > 0) # 昨日 ≤0 且今日 >0:上穿
death = (prev >= 0) & (diff < 0) # 昨日 ≥0 且今日 <0:下穿
插曲:双引擎交叉验证逮到一个边界
事件驱动(金叉买、死叉卖)和状态驱动(多头状态掩码)两套引擎互为验证,单指标结果本应完全一致,实测差了 0.8%。追查发现唯一差异在 2022-03-06:那天 MA5 与 MA20 精确相等(diff = 0),事件版认为"相等不算穿越"晚一天离场,状态版严格比较提前离场。五年只出现一次的边界,交叉验证让它无处遁形。
实验一:信号分级——慢就是快
四个信号源(均线三对 + MACD),同规则回测,基准是买入持有 -16.3%(最大回撤 -45.4%——这个数字后面还会出现):
| 信号 | 级别 | 笔数 | 胜率 | 收益 | 最大回撤 |
|---|---|---|---|---|---|
| MA5x10 | 短期 | 53 | 32.1% | +23.5% | -26.8% |
| MA5x20 | 中期 | 26 | 38.5% | +83.8% | -26.7% |
| MA10x20 | 长期 | 26 | 42.3% | +92.8% | -17.9% |
| MACD | 中期 | 37 | 37.8% | +89.2% | -28.1% |
规律干净:信号越慢,笔数越少、胜率越高、收益越高、回撤越浅。快的信号不是没抓到机会,是机会和噪音一起抓——53 笔交易里一半以上在给震荡市交学费。
实验二:逐级确认——峰值停在双确认
把 4 个信号源做全部 AND 组合:单指标 4 种 + 双确认 6 种 + 三确认 4 种 + 四确认 1 种,共 15 种,逐级回测:
| 层级 | 冠军组合 | 笔数 | 胜率 | 收益 | 回撤 | 超额(vs持有) |
|---|---|---|---|---|---|---|
| N=1 | MA10x20 | 26 | 42.3% | +92.8% | -17.9% | +109.1% |
| N=2 | MA5x20 + MACD | 25 | 44.0% | +128.4% | -20.4% | +144.7% |
| N=3 | MA5x20 + MA10x20 + MACD | 25 | 40.0% | +95.6% | -21.3% | +111.9% |
| N=4 | 全部冗余 | - | - | - | - | - |
| 对偶 | 任一确认(OR) | 43 | 32.6% | +57.3% | -31.5% | +73.6% |
三个发现,一个比一个有意思:
- 峰值停在双确认,向两边衰减——更严的三确认不如它,更松的 OR 也不如它
- 确认的收益来自信息异源:最优组合是均线 × MACD(价格趋势 × 动量离差,两种看市场的方式),+128.4%;而均线 × 均线(MA5x20 + MA10x20)只有 +73.7%,还不如单用 MA10x20——同源指标高度相关,重复确认滤掉的不是假信号,是 真行情
- 传递性冗余:
MA5>MA10 且 MA10>MA20数学上蕴含MA5>MA20,所以四确认组合与三确认(去掉 MA5x20)结果完全相同(+67.1%,32 笔一笔不差)。加冗余条件不会改变策略,只会让人误以为更严谨
实验三:趋势过滤——"顺势"的代价
第二组实验把市场状态接入回测:持仓 = 信号多头 AND ADX >= 阈值(趋势强度不足不开火):
| 信号 | 原始收益 | ADX>=20 后 | 超额 | 胜率变化 |
|---|---|---|---|---|
| MA5x10(噪音多) | +20.3% | +40.4% | +20.0% | 32% → 37% |
| MA10x20 | +92.8% | +98.5% | +5.8% | 42% → 68% |
| MA5x20+MACD(已双确认) | +128.4% | +115.0% | -13.4% | 44% → 61% |
反直觉的地方在于:过滤对弱信号有效,对强组合是负贡献。机制不复杂——ADX 是滞后确认,等它站上 20,趋势初段(利润最厚的部分)已经走完;双确认本身已经过滤了震荡,再叠一层 ADX 是冗余过滤。
更扎心的是胜率与收益的背离:过滤后胜率普遍大涨(最高 42% → 68%),强信号的收益反而下降。高胜率和赚大钱是两回事——被 ADX 拦掉的那些低胜率交易里,恰好装着让利润奔跑的大波段。过滤的稳定收益在回撤端:冠军组合回撤从 -20.4% 收窄到 -13.9%。
实验四:周期许可——"大周期定方向"被证伪
最经典的多周期结构:周线多头才允许日线信号开火。对齐规则(无未来函数):交易日 t 使用 date <= t 的最新周线状态,含周线日当天的边界(当日周线收盘成型、次日开盘执行),已抽样逐一验证。
| 信号 | 原始收益 | 周线MA许可后 | 超额 |
|---|---|---|---|
| MA5x20+MACD | +128.4% | +16.2% | -112.2% |
| MA10x20 | +92.8% | +20.3% | -72.5% |
| MA5x10 | +20.3% | -26.0% | -46.3% |
全线溃败,连弱信号都没能幸免。三层原因:
- 周线均线滞后:周线多头确认时反弹已过半——日线策略在趋势初段的入场全被拦下
- 状态语义强制清仓:周线翻空即踢出正在盈利的持仓
- 长熊环境的结构性问题:该标的五年下行,"周线顺势"等于 53% 的时间不开火
结论边界,必须说清
这是在 长期下行的标的 上的实测,不可直接外推到长期上行的市场。但"滞后确认吃掉趋势初段"的机制是普适的——上行市场里同样存在,只是被贝塔行情掩盖了。教条不是错在方向,是错在没人量化过代价。
注意事项
- ⚠️ 单标的 5 年样本,统计意义有限——结论当"机制证据"看,不当"普适参数"看
- ⚠️ 零手续费口径:分钟线级别的信号密度(5 天 190 个信号)在实盘只会更惨
- ✅ 全部数字可离线复现:
example/2026/10/21-1/,--recompute一条命令从本地缓存重算
小结
一句话概括:确认的边际价值递减得比直觉快得多——第一层异源确认是金子(+144.7% 超额),第二层开始吃趋势初段,"大周期许可"这种重确认直接把超额吃到负。
方法论上的收获比数字更值钱:
- 教条需要数据制衡——"共振才可靠"只对了一半:异源共振可靠,同源共振是冗余
- 高胜率是安慰剂,趋势策略的收益来自让利润奔跑的那几笔,别用胜率评价它
- 负结果也是结果——知道哪个过滤器没用,和知道哪个有用一样值钱
完整的复合系统设计见《当趋势策略遇上震荡市》——那篇设计手记承认自己缺回测数据,本文是补全的第一块:信号层与过滤器层已经验证完,三档阶梯止盈的状态机回测是下一块。
最后更新:2026-10-21