"RSI-Kekkai"这个名字,是我在收到需求四个小时后才拍板定下的。当时业务方只丢过来一句话:"能不能把那些容易追高的信号拦下来?"——没有需求文档,没有验收标准,甚至连"追高"的定义都取决于当天市场行情好坏。我从这句话开始,一路做到有参数、有回测、有监控、有结论的可验证闭环。整个过程值得完整复盘一遍,因为它不仅是一个量化信号过滤层,更是一次"一句话需求"如何被拆解、落地、验证的实战样本。这篇内容适合正在做策略研究、信号系统,或者整天跟模糊需求打交道的朋友。我会从需求澄清、方案选型、核心实现到回测监控,把每一步摊开讲。
1. 需求破壁:从"拦信号"到可量化指标
1.1 先承认"追高"是个共识偏差
业务方说的"追高",本质上是"在情绪亢奋的位置入场,随后大概率被套"。但概率这个词,业务方不会主动讲,他们只会描述现象:买入之后开始跌、涨了很多才敢买、一买就回调。这些现象背后有一个共同的量化判断维度——价格相对近期波动区间的位置。如果我们能把"位置过高"转成数值,再用一个规则去拦截信号,"拦下来"就从行为描述变成了条件判断。
我第一件事不是写代码,而是把"追高"拆成三个可问题化的子集:什么时候算高、多高算危险、危险之后怎么办。这三个问题分别对应计算周期、阈值设定、后续动作。很多时候项目推进慢,不是技术难,而是没有把业务语言转成指标语言。
1.2 需求澄清清单:把一句话问成三页纸
我列了一份问题清单,拿去跟业务方逐条过。问题不多,但每一条都影响后续设计:
- 拦的是新开仓信号,还是持仓中的加仓信号?
- 拦下的信号是彻底放弃,还是延后到条件缓和再放行?
- 允许误拦多少?宁可错过十个,也不能放过一个,还是反过来?
- 评价"有效"用什么标准?是看拦截后少亏的钱,还是看整体收益变化?
- 信号出现的频率高不高?拦截会不会导致几乎不交易?
这些问题问完之后,需求变成了:在现有买入信号基础上增加一个过滤层,当市场处于超买状态时,阻止信号进入成交队列;被拦截的信号可以延时处理,但不会完全丢弃。有效性的定义则是对比有过滤和无过滤两种场景下的收益曲线与回撤数据。有了这层澄清,"可验证"才有了锚点。
1.3 为什么叫"结界"
Kekkai是日语"结界"的读音,取"在关键位置布防、挡住越界者"的意思。RSI(相对强弱指数)恰好是一个描述价格"越界"程度的指标——数值越高,说明近期的上涨越极端。一个叫RSI-Kekkai的过滤层,就是用RSI在信号系统和交易执行之间画一道边界。名字起得中二,但项目成员和业务方都秒懂:它不产生信号,只负责拦截越界的信号。这比叫"超买过滤模块"好沟通得多。
2. 方案选型:为什么用RSI做结界
2.1 RSI、均线、布林带,三选一
面对"位置过高"这个需求,候选指标不止RSI一个。均线偏离度可以表达价格离均值有多远,布林带上下轨也能标记极端位置,RSI则把涨跌力度归一到0到100的区间里。我最后选RSI,有三个理由。
第一,判读门槛低。业务方不需要理解标准差就能看懂"RSI超过70就是超买",沟通成本低。第二,天然带阈值语义。0到100的区间让人很容易定义拦截线,不像均线偏离度需要根据标的波动率动态调整。第三,RSI对极端行情的响应更早。它用近期涨跌幅度的比值衡量动能,而不是纯粹的距离,在行情加速赶顶时提示更及时。
当然RSI有它的短板,比如钝化和震荡市里频繁触发,但这些可以在过滤逻辑层面弥补。选型不追求指标完美,追求的是"够用且好解释"。
2.2 双层架构:信号层与结界充分解耦
系统设计上坚持一个原则:结界层绝不改动底层信号逻辑。买入信号该由趋势模型、突破模型还是机器学习模型产生,是信号层的事;结界只接收一个"信号名称+方向+时间戳",根据当前市场状态决定放行、拦截还是延后。
这种解耦带来的直接好处是,底层信号模型替换时,结界层完全不用动。我们在项目中期就换过一版信号源,从单纯的均线突破改成突破+量能确认的组合,结界层只是重新消费了新信号流,逻辑零改动。如果当初把过滤条件写进信号模型内部,这次替换就要动五脏六腑。
2.3 参数不是拍脑袋:14周期与70/30阈值
RSI最常见的参数是14周期,阈值取70和30。这个组合来自技术分析经典框架,但不是所有标的市场都适用。我们的做法是:先跑一遍参数敏感性测试,周期取6到30的整数,超买阈值取65到85,用网格搜索看哪个区间组合表现稳定。
结果很有代表性——周期14到20之间、阈值70到75之间的组合,收益表现没有显著差异,但越过这个区间后回撤明显变大。这说明最优参数不是一个点,而是一片稳定高原。最终选定14周期、超买阈值70、超卖阈值30,不是因为它在回测里收益最高,而是因为它落在稳定区间中央,对未来环境变化的鲁棒性更好。这个思路后来也写进了项目文档:参数选择优先考虑稳定域,而不是尖峰最优值。
3. 核心实现:计算、过滤与可配置
3.1 RSI的标准算法与落地细节
RSI的计算方式有很多种,最常见的是用简单移动平均算涨跌幅均值,但业界更推荐Wilder平滑法,它对最新价格变化的响应更平滑,不容易被单根大阳线带飞。核心实现用pandas几行就能完成:
import pandas as pd def rsi_wilder(prices: pd.Series, period: int = 14) -> pd.Series: delta = prices.diff() gain = delta.clip(lower=0) loss = -delta.clip(upper=0) avg_gain = gain.ewm(alpha=1 / period, adjust=False).mean() avg_loss = loss.ewm(alpha=1 / period, adjust=False).mean() rs = avg_gain / avg_loss return 100 - 100 / (1 + rs)注意ewm(alpha=1/period)才是Wilder平滑,如果误用span=period,计算结果会不一样,回测结论也会跟着偏移。另一个细节是:前period个周期没有完整的RSI值,这些位置的信号无法被过滤,必须显式跳过标记,不能默认用0填充——用0填充会让初期RSI看起来像极度超卖,干扰回测统计。
3.2 三种过滤模式:硬拦、软拦、背离拦
结界层不是单一规则,而是三种过滤模式,按风险等级从高到低排列,可以通过配置项切换。
硬拦截模式下,只要RSI高于超买阈值,任何买入信号都会被压入延时队列,等到RSI回落到阈值以下再释放。这是最严格的模式,适合趋势行情中防止追高。
软拦截模式不阻止信号,但会给信号打上"高RSI"标签,交由仓位管理模块决定是否缩减开仓比例。回测数据表明,软拦截对收益曲线的平滑作用不如硬拦截,但不会错过极端行情继续上涨的收益。
背离拦截是第三种,它的逻辑是:价格创出新高,但RSI没有同步创新高,说明上涨动能衰竭。此时即使是趋势多头信号,也强制拦截。这种模式对抄底判断同样适用,只是镜像到价格新低、RSI未创新低的场景。
三种模式可以叠加。我们在生产环境用的是"软拦截+背离拦截"组合,原因后面在监控部分详述。
3.3 参数配置化:改策略不改成代码
为了不让每次调参都变成一次代码发布,配置直接外置成结构化文件:
rsi_config = { "period": 14, "buy_ceiling": 70, "sell_floor": 30, "mode": "soft_plus_divergence", "cooldown_bars": 5, "divergence_lookback": 20, "signal_sources": ["trend_breakout", "volume_confirm"] }cooldown_bars是冷却期。RSI跌破阈值后,不会立刻恢复放行,而是再多等5根K线,防止RSI在阈值附近反复穿越导致信号频繁抖动的"开关门效应"。这个参数在实盘中极其重要,冷启动阶段我们没配冷却期,结果同一波上涨里信号被拦截、释放、再拦截,来回折腾,交易成本烧掉一大截。补上冷却期之后,这种抖动基本消除。
3.4 回测环境:收益数据会骗人
回测环境是闭环验证的底座,也是最容易出猫腻的地方。搭建时我们定了几条铁律:手续费按双边千分之二计算,滑点按单笔万分之五估算,撮合按下一根K线开盘价成交。为什么这么设?因为如果按收盘价撮合,等于假设你能在信号产生的瞬间以收盘价成交,这在真实市场里几乎不可能,属于典型的未来函数。下一根K线开盘价撮合虽然保守,但至少不会高估收益。
数据方面单独讲一个坑:涨跌停当天不能以涨停价买入或跌停价卖出,但普通回测框架不会意识到这一点。我们的处理是:如果信号产生当天涨停,买方向信号直接标记为不可成交,卖方向信号则按情绪市况特殊处理,至少不在涨停板上裸卖。这类细节看着琐碎,对回测真实性的影响却非常大。
4. 闭环验证:构建一条可证明的证据链
4.1 评价指标:不是只看收益曲线
业务方最关心收益,但项目验证不能只汇报收益。我们看四个维度:累计收益、最大回撤、夏普比率、胜率。这四个指标放在一起看,才能描述一个策略的完整性格。有的策略收益高但回撤吓人,有的胜率低但盈亏比优秀,单看任何一个都容易被误导。
我给业务方的报告里用了一张对比表,模拟项目X在2023年至2024年样本区间内的回测结果:
| 指标 | 无结界基线 | 硬拦截结界 | 软拦截+背离结界 |
|---|---|---|---|
| 累计收益率 | 38.6% | 41.2% | 44.7% |
| 最大回撤 | -21.3% | -16.8% | -14.9% |
| 夏普比率 | 1.12 | 1.36 | 1.52 |
| 交易次数 | 187 | 142 | 156 |
| 胜率 | 54.1% | 58.3% | 59.6% |
这张表说明两件事:加结界不是单纯减少交易,而是在减少那些位置不当的交易,所以交易次数少了,但胜率和收益反而上升。最大回撤的改善尤其明显,这正是"防追高"需求最直接的价值体现。需要强调,这组数字只是模拟项目X在特定样本区间的结果,不代表任何实盘预期,但它足以作为"过滤层有效"的证据。
4.2 对比实验:同一个信号,过不过结界
为了排除市场整体行情好坏的干扰,我们设计了对照实验:同一个底层信号流,一份原样输出,一份经过结界层,同时在同一时间段、同一标的上运行。这样唯一的变量就是结界层,收益差异只能归因于过滤逻辑。这是"可验证闭环"最关键的一步——不是做完一套策略再拍脑袋说有效,而是构建一个AB测试结构。
对照组的数据出来之后,还发现一个有意思的细节:被拦截的信号里,有超过六成在拦截后的一到三天内出现了至少一次比入场点更低的价格。这说明拦截动作在多数情况下确实避开了短期回撤。这个统计比收益数字更有说服力,因为它直接回应了业务方"容易追高"的直觉。
4.3 鲁棒性测试:参数扰动下的稳定性
样本期内参数最优不代表未来最优,所以我们做了参数扰动测试。把主参数在选定值上下各浮动20%,记录每组参数下的收益和回撤波动。稳定域内的参数跑出来的结果应该相差不大,如果某个参数变动5%就让收益从正变负,那说明策略依赖的只是偶然运气,不是真实规律。
我们的RSI结界在周期参数13到17、阈值68到73之间表现稳定,收益波动范围在一两个百分点以内。这让我敢把参数写进生产配置。后来在实盘区间的表现也验证了这一点:参数没有重新优化,但指标仍保持稳定。
4.4 上线监控:布防之后还要守夜
回测只是闭环的第一环,上线后的监控才让闭环真正闭合。我们把结界层部署成独立服务,每根K线收盘后计算最新RSI和背离状态,输出到一张状态表:当前是"正常/警戒/拦截"哪种状态,今天拦了多少信号,分别是什么原因。这张表每天收盘后自动推送,业务方只需要在异常时看一眼。
监控还带了一组告警规则:拦截比例突然超过历史均值的两倍,或者连续N根K线都处于拦截状态,会触发人工复核。前者说明市场可能进入非理性阶段,后者说明RSI钝化严重,结界可能过度抑制交易。上线头两周我们就抓到过一次钝化事件:连续超买状态下,硬拦截把一批正常趋势信号压了近两天,直接导致踏空。后来才在监控结论的推动下,把生产模式从硬拦截切换成软拦截加背离拦截,避免矫枉过正。
5. 避坑实录:那些回测不会告诉你的细节
5.1 RSI钝化问题:持续超买并不等于马上跌
趋势行情里RSI可以在超买区待很久,如果按照经典说法"超买就卖出",很早就被甩下车。这个现象在所有动量指标里都存在,RSI尤其明显。我们的处理方式在上面提过:引入冷却期和模式切换,不把RSI阈值当成绝对命令,而是当成风险温度计。温度高不等于马上降温,但需要加强监控。实在要硬拦,也优先拦新开仓信号,不拦已有持仓的跟踪信号。这个分层思路避免了钝化期的踏空问题。
5.2 前视偏差的隐形来源
前视偏差不只来自撮合价,还常见于指标计算本身。比如用包含当前K线收盘价的数据来计算RSI,再用这个RSI去判断当前K线的信号,等于偷看了收盘结果。正确做法是:信号产生用的RSI值必须滞后一根K线,或至少保证使用的数据在信号产生时刻已经确定。实现上就是rsi.shift(1),别小看这一个shift,它纠正的是整个回测逻辑的基本自洽性。
5.3 过拟合的三个蛛丝马迹
网格搜索很容易跑出漂亮的参数组合,但过拟合通常有三个迹象:最优参数在参数空间里呈孤立的尖峰、样本外表现断崖式下跌、不同行情周期内最优参数漂移严重。我们的应对是坚持"参数平原"原则——只选落在稳定区域内的参数,拒绝尖峰值。后来回测框架还加了个功能:自动标注参数空间内排名前5%的连续区域,如果这些区域没有连成片,直接标红提示"参数结果可能依赖偶然"。
5.4 数据清洗的脏活
回测用的行情数据远没有想象中干净。停牌股在复牌当天可能跳空高开十几个点,这类K线如果不特殊标记,会被回测框架当成正常波动,产生大量假信号。复权因子错误则会导致历史价格的连续性断裂,让RSI的计算基准失真。我们的做法是建数据质量检查表,每日对比原始行情和前收盘价的偏差,超过阈值的数据点进入人工复核队列。这些脏活不出彩,但恰恰是"可验证"三个字的地基。
6. 写在闭环之外:几句实在话
这个项目做完,我最大的体会不是RSI多好用,而是"可验证的闭环"必须先定义验证标准。如果业务方那句"防止追高"没有被翻译成回撤控制和胜率提升,项目交付的时候一定会陷入"有没有效"的无休止争论。把需求翻译成指标,把指标翻译成AB测试,把测试结果翻译成业务方能看懂的表,这个翻译链路才是闭环的真正含义。
另一个经验是别追求大而全。第一版结界只做了硬拦截模式,代码不到三百行,但已经能跑完一个完整的样本外验证。拿到初步证据后,再迭代出软拦截和背离拦截。小步快跑在这里不是口号,是让每个环节都能被检验的操作方式。如果你也在做类似的项目,建议先别纠结指标选RSI还是布林带,先问清楚"有效"到底由谁说了算,这个问题想清楚了,技术选型会快得多。