3、震荡市场识别:布林带收窄识别震荡、RSI指标识别震荡、ATR指标识别波动率变化
做量化交易这些年,我踩过最大的坑是什么?
就是在震荡行情里用趋势策略。你想想看,明明市场在上下晃悠,你的趋势跟踪系统却频繁开仓、止损、再开仓……账户资金就这么一点点被磨没了。
所以今天咱们聊聊怎么识别震荡市场。说白了,就是给市场把脉——它现在是在蓄力,还是在瞎折腾?
3.1 布林带收窄:最直观的震荡信号
布林带这个工具,我个人特别喜欢。它由三条线组成:中轨是均线,上下轨是均线加减两倍标准差。
当市场进入震荡,价格波动变小,标准差自然就缩小了。表现在图上,就是布林带像被挤了一样收窄。
核心逻辑:布林带宽度 = (上轨 - 下轨) / 中轨。当这个值低于某个阈值,就说明市场在震荡。
我在项目中遇到过这样的情况:某只股票连续三周布林带宽度都在历史低位徘徊,很多散户以为要横盘了,结果突然一根大阳线突破上轨,直接起飞。嗯,这就是震荡后的爆发。
def is_bollinger_squeeze(df, period=20, std_dev=2, threshold=0.1):
"""
判断布林带是否处于收窄状态
"""
df['middle'] = df['close'].rolling(period).mean()
df['std'] = df['close'].rolling(period).std()
df['upper'] = df['middle'] + std_dev * df['std']
df['lower'] = df['middle'] - std_dev * df['std']
# 计算布林带宽度
df['band_width'] = (df['upper'] - df['lower']) / df['middle']
# 判断是否收窄
df['squeeze'] = df['band_width'] < threshold
return df['squeeze'].iloc[-1]
实战技巧:阈值不要死板。我个人习惯用过去100天的布林带宽度中位数作为基准,低于中位数的30%就算收窄。不同品种差异很大,BTC和茅台肯定不一样。
3.2 RSI指标:震荡中的超买超卖游戏
RSI,相对强弱指标。很多人只知道它用来判断超买超卖,但其实在震荡行情里,它是个绝佳的区间交易工具。
为什么会这样?因为趋势行情里,RSI可以长时间在超买区或超卖区待着,你按传统方法做反向交易会死得很惨。但在震荡行情里,RSI就像个听话的孩子,到了70以上就回头,到了30以下就反弹。
| RSI值 | 震荡市场含义 | 操作建议 |
|---|---|---|
| 70以上 | 超买,但震荡中大概率回落 | 考虑做空或减仓 |
| 30以下 | 超卖,但震荡中大概率反弹 | 考虑做多或加仓 |
| 40-60之间 | 中性区域,方向不明 | 观望或轻仓 |
我曾经犯过一个错误:在震荡行情里看到RSI到了80,直接重仓做空。结果市场虽然震荡,但重心在缓慢上移,RSI在80附近钝化了三天,我的仓位被磨得很难受。后来我学乖了——震荡行情里,RSI必须结合布林带一起看。
def rsi_oscillation_signal(df, period=14, overbought=70, oversold=30):
"""
基于RSI的震荡交易信号
"""
delta = df['close'].diff()
gain = (delta.where(delta > 0, 0)).rolling(period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(period).mean()
rs = gain / loss
df['rsi'] = 100 - (100 / (1 + rs))
# 震荡信号
df['overbought'] = df['rsi'] > overbought
df['oversold'] = df['rsi'] < oversold
return df[['rsi', 'overbought', 'oversold']].iloc[-1]
注意:RSI在震荡行情里好用,但一旦市场转为趋势,这套方法就会失效。所以一定要先确认市场状态,再决定用哪个策略。我曾经在趋势行情里用RSI做反向交易,结果被连续打脸。
3.3 ATR指标:波动率的温度计
ATR,平均真实波幅。这个指标不告诉你方向,只告诉你市场有多活跃。
你想想看,如果ATR持续下降,说明市场波动在减小,这就是震荡的前兆。如果ATR突然放大,说明市场可能要搞事情了。
核心用法:比较当前ATR与过去N天的ATR均值。当前ATR低于均值50%以上,说明波动率极低,市场大概率在震荡。
我记得有一次做ETH的交易,ATR从80多一路降到20左右,布林带也收得很窄。我当时判断市场在蓄力,就提前布局了期权。结果三天后ATR突然飙升到150,价格直接拉了20%。嗯,这就是波动率变化的力量。
def atr_volatility_regime(df, period=14, atr_mult=1.5):
"""
基于ATR识别波动率变化
"""
high_low = df['high'] - df['low']
high_close = abs(df['high'] - df['close'].shift())
low_close = abs(df['low'] - df['close'].shift())
tr = pd.concat([high_low, high_close, low_close], axis=1).max(axis=1)
df['atr'] = tr.rolling(period).mean()
# 计算ATR的相对变化
df['atr_ma'] = df['atr'].rolling(period * 3).mean()
df['atr_ratio'] = df['atr'] / df['atr_ma']
# 判断状态
df['low_volatility'] = df['atr_ratio'] < 0.5
df['high_volatility'] = df['atr_ratio'] > atr_mult
return df[['atr', 'atr_ratio', 'low_volatility', 'high_volatility']].iloc[-1]
3.4 三指标联立:震荡识别的终极方案
单独用任何一个指标,都有局限性。我个人习惯把三个指标结合起来看:
- 布林带收窄:确认价格波动范围在缩小
- RSI在40-60之间徘徊:确认没有明显的超买超卖
- ATR处于低位:确认整体波动率偏低
当这三个条件同时满足,我才会判定市场进入震荡状态。缺一个都不行。
避坑指南:我曾经只靠布林带收窄就判断震荡,结果遇到的是「假突破前的蓄力」,直接被打止损。后来加上ATR和RSI做双重验证,准确率提升了不少。记住,单一指标都是片面的。
def comprehensive_oscillation_check(df):
"""
综合判断是否处于震荡市场
"""
# 布林带检查
boll_squeeze = is_bollinger_squeeze(df)
# RSI检查
rsi_data = rsi_oscillation_signal(df)
rsi_mid = 40 <= rsi_data['rsi'] <= 60
# ATR检查
atr_data = atr_volatility_regime(df)
low_vol = atr_data['low_volatility']
# 综合判断
is_oscillation = boll_squeeze and rsi_mid and low_vol
return {
'is_oscillation': is_oscillation,
'bollinger_squeeze': boll_squeeze,
'rsi_mid_zone': rsi_mid,
'low_volatility': low_vol
}
这套框架我用了好几年,在股票、期货、加密货币上都验证过。说白了,震荡市场识别不是靠一个指标拍脑袋,而是多个维度交叉验证的结果。
你想想看,如果布林带收窄了,但RSI还在80以上,说明什么?说明市场虽然波动小,但买盘依然强势,随时可能向上突破。这时候你按震荡做空,不是找死吗?
所以记住:震荡识别不是目的,目的是为了选择正确的交易策略。识别出震荡,你就该用区间交易、网格策略或者期权卖方策略。识别出趋势,你就该用趋势跟踪。搞反了,就是亏钱的开始。