说到炒股,很多刚入门或者甚至有一定经验的朋友,看到“除权除息”这几个字就头大。尤其是当你满心欢喜地用布林带(Bollinger Bands)去筛选那些突破上轨、看似即将起飞的股票时,突然某天开盘,股价直接低开20%,K线图中间出现了一个巨大的垂直缺口。这时候,布林带的上轨、中轨、下轨全乱了,之前的形态分析瞬间失效,指标发出了错误的“卖出”或“破位”信号。
这其实不是你的技术有问题,而是数据源没有处理好“复权”这个关键步骤。今天,我们就把这个看似枯燥的技术细节,掰开了、揉碎了讲清楚,顺便聊聊怎么利用Python代码自动处理这个问题,让你的选股策略真正靠谱起来。
为什么布林带会在除权日“失灵”?
首先,我们要理解布林带是怎么算出来的。布林带由三条线组成:
- 中轨:通常是20日的移动平均线(MA)。
- 上下轨:中轨加减两倍的标准差(Standard Deviation)。
标准差衡量的是价格的波动率。当一只股票因为分红送股导致股价“除权”时,比如10送10,股价会从10元变成5元。但在K线图上,如果不做处理,前一天的收盘价是10元,当天的开盘价是5元。
这就导致了一个灾难性的后果:价格断层。
对于布林带算法来说,它不知道这是因为分红导致的“名义价格”下降,它只看到数据:昨天10块,今天5块。于是,它会认为这只股票发生了极端的下跌,波动率(标准差)急剧放大,或者均线(中轨)被瞬间拉低。原本应该平稳运行的布林带,突然张开一个巨大的喇叭口,或者中轨突然断崖式下跌。
如果你拿着未复权的K线图去跑选股公式,你会发现:
- 假突破:股价看似突破了上轨,其实是除权造成的视觉错觉。
- 假破位:股价看似跌破了下轨,触发止损,结果第二天填权行情来了,你割在地板上。
- 指标钝化:由于价格跳空,历史数据的连续性被切断,移动平均线的平滑作用失效,发出的信号全是噪音。
所以,“前复权”或“后复权”是布林带选股的前置条件,缺一不可。
复权到底选哪种?前复权 vs 后复权
在解决这个问题之前,很多散户朋友会纠结:到底该用前复权还是后复权?
前复权(Forward Adjusted):以当前价格为基准,调整历史价格。也就是说,现在的股价不变,过去的股价都向下调整了。
- 优点:看现在的走势最直观,符合当前的交易心理。大多数看盘软件默认显示的就是前复权。
- 缺点:如果公司历史上多次分红送股,早期的价格可能会变成负数或者极其微小,这在计算长期均线时可能会有极端值干扰(虽然概率极低)。
后复权(Backward Adjusted):以发行价为基准,调整当前价格。也就是说,过去的股价不变,现在的股价被向上调整了。
- 优点:保留了股票上市以来的真实累计涨幅,适合长线投资者看总收益。
- 缺点:现在的股价可能高达几百甚至上千倍于原始价格,数字巨大,不利于日常技术分析中的比例判断。
对于布林带选股而言,推荐使用【前复权】。
为什么?因为布林带是一个基于近期波动率的动态指标。我们关心的是“最近20天”的价格行为。前复权保证了当前的价格水平是真实的交易价格,而历史价格进行了相应的缩放,使得K线图形连续,消除了除权造成的断层。这样计算出的20日均线,才是平滑反映近期趋势的真实均值。
实战演示:如何用Python清洗数据并构建布林带选股策略
光说不练假把式。为了让大家彻底明白,我用Python写一个简单的脚本。这个脚本模拟了从获取数据、处理复权、计算布林带到筛选股票的全过程。
假设我们要找那些“经过前复权处理后,股价突破布林带上轨,且成交量放大”的股票。
import pandas as pd
import numpy as np
import yfinance as yf # 这里以雅虎财经为例,A股可用akshare或tushare
def calculate_bollinger_bands(data, window=20, num_std=2):
"""
计算布林带指标
:param data: 包含'Close'列的DataFrame
:param window: 移动平均线的周期,默认20
:param num_std: 标准差的倍数,默认2
:return: 包含BB中轨、上轨、下轨的DataFrame
"""
df = data.copy()
# 1. 计算中轨 (20日简单移动平均线)
df['BB_Middle'] = df['Close'].rolling(window=window).mean()
# 2. 计算标准差
rolling_std = df['Close'].rolling(window=window).std()
# 3. 计算上轨和下轨
df['BB_Upper'] = df['BB_Middle'] + (num_std * rolling_std)
df['BB_Lower'] = df['BB_Middle'] - (num_std * rolling_std)
return df
def filter_bollinger_breakout(stock_code='AAPL'):
"""
筛选布林带突破的股票示例
"""
print(f"正在获取 {stock_code} 的数据...")
# 获取最近一年的日线数据
# 注意:yfinance默认返回的价格通常已经是处理过的,但为了保险,我们需要确认
# 在实际A股应用中,必须显式指定 'adjclose' 或使用前复权接口
df = yf.download(stock_code, period="1y", progress=False)
if df.empty:
return None
# 【关键步骤】确保使用的是前复权价格
# 在yfinance中,'Adj Close' 列通常就是前复权后的价格
# 如果你使用Tushare,需要设置 pro_api.daily(ts_code, adj='qfq')
df['Close'] = df['Adj Close']
# 重新索引以便计算
df = df[['Close']].dropna()
# 计算布林带
df_bb = calculate_bollinger_bands(df)
# 获取最新一天的数据
last_day = df_bb.iloc[-1]
prev_day = df_bb.iloc[-2]
current_price = last_day['Close']
upper_band = last_day['BB_Upper']
# 判断是否突破上轨
# 条件:今天收盘价 > 昨天上轨,且今天收盘价 > 昨天收盘价 (确认是向上突破)
is_breakout = (current_price > upper_band) and (current_price > prev_day['Close'])
print("-" * 30)
print(f"股票代码: {stock_code}")
print(f"当前价格: {current_price:.2f}")
print(f"布林上轨: {upper_band:.2f}")
print(f"布林中轨: {last_day['BB_Middle']:.2f}")
print(f"是否突破上轨: {'是' if is_breakout else '否'}")
print("-" * 30)
return is_breakout
# 模拟A股某股票的数据处理逻辑(伪代码,展示核心思想)
"""
import akshare as ak
# 1. 获取前复权的历史行情
df_hist = ak.stock_zh_a_hist(symbol="600519", period="daily", adjust="qfq")
# 注意:adjust="qfq" 这一步至关重要!它会自动处理除权带来的价格断层
# 2. 提取收盘价
close_prices = df_hist['收盘'].astype(float)
# 3. 计算布林带
# ... (复用上面的calculate_bollinger_bands函数)
# 4. 筛选
# 只有当数据是前复权时,计算出的标准差和均线才是连续的,
# 才能真实反映市场的情绪波动,而不是被分红送股干扰。
"""
在上述代码中,我特意强调了 Adj Close 或者 adjust="qfq" 的重要性。如果你在A股平台(如通达信、同花顺)手动选股,一定要在设置里勾选“前复权”。如果你是用程序化交易,务必在数据源层面就完成复权处理,否则后面所有的技术指标都是空中楼阁。
除权后布林带选股的三个黄金法则
处理好了数据,我们再来看看具体的选股策略。很多高手在除权后使用布林带,并不是简单地看突破,而是结合以下几个细节:
1. 等待“填权”初期的缩量回踩
除权后,股价虽然名义上降低了,但如果基本面没变,市场往往会有一个“填权”的过程,即股价涨回到除权前的水平。
- 错误做法:一除权就追高。因为除权当天波动极大,布林带上轨可能被瞬间击穿,但这往往是假突破。
- 正确做法:观察除权后1-3天的走势。如果股价在突破上轨后,出现缩量回调,且股价始终站在布林带中轨(20日均线)之上,这说明主力资金在洗盘,后续上涨概率大。此时,布林带的开口如果开始收窄,往往是变盘的前兆。
2. 警惕“除权缺口”对标准差的扭曲
如前所述,除权会导致巨大的价格落差。即使做了前复权,如果复权处理不当(比如用了不复权的数据),标准差会被异常拉大。
- 现象:布林带上下轨之间的距离变得极宽,失去了参考意义。
- 对策:在选股时,检查布林带的带宽(Bandwidth = (Upper - Lower) / Middle)。如果带宽突然异常放大,且不是因为重大利好消息,而是恰逢除权日,那么这个信号是无效的。你应该跳过除权当天的信号,等待数据稳定后再重新评估。
3. 结合成交量验证突破的有效性
布林带突破上轨,如果没有成交量的配合,很可能是诱多。特别是在除权后,市场参与度可能发生变化。
- 有效突破特征:
- 股价放量突破布林带上轨。
- 突破当日成交量至少是前5日均量的1.5倍以上。
- 收盘价稳稳站在线上轨上方,而不是仅仅盘中触碰。
给小朋友也能听懂的比喻
为了让你更深刻地理解,我们可以打个比方。
想象你在玩一个跳房子游戏。地面画好的格子是布林带的中轨(平均值)。你跳的距离忽远忽近,这些距离的变化范围就是上下轨(标准差)。
现在,突然有人把整块地面平移了一下(这就是除权,价格变了,但相对关系没变)。如果你不调整你的视线(不复权),你会以为那个人突然向后倒退了十米(价格断层),从而吓得以为他摔倒了(卖出信号)。但实际上,他只是换了个地方继续跳,而且跳得更好了。
复权,就是让你戴上一种特殊的眼睛,能把地面平移的效果抵消掉,让你看到那个小人真实的跳跃轨迹。只有这样,你才能判断他是不是真的在向前冲刺(突破上轨)。
总结与建议
布林带选股,核心在于“趋势”和“波动率”。而除权,是破坏数据连续性的最大杀手。
- 永远使用前复权数据:无论是人工看盘还是程序选股,这是铁律。
- 除权后观察期:除权当天及随后1-2天,指标容易失真,建议观望,等待形态稳定。
- 结合多重指标:不要单靠布林带。结合MACD(看趋势动能)、成交量(看资金认可度)以及基本面(看分红是否合理),才能提高胜率。
- 警惕极端值:如果某只股票历史上分红极其频繁,前复权后的早期数据可能失真严重。此时,可以缩短布林带的周期(如从20日改为10日),或者改用后复权数据进行长期趋势判断,再用前复权进行短期交易决策。
希望这篇分享能帮你解开“除权后布林带失效”的谜团。记住,工具本身没有错,错的是使用工具的方式。处理好数据,你的选股策略才会像精密仪器一样准确。祝你在股市中,既能看懂趋势,又能避开陷阱,稳稳获利!
