OBV指标的核心逻辑
OBV(On-Balance Volume)由乔·格兰维尔提出,核心思想是成交量领先于价格。当日收盘价高于前一日,则累加成交量;低于前一日,则累减成交量;持平则不变。OBV曲线反映多空资金的力量消长,价格上升伴随OBV上升,说明资金推动真实;价格上升而OBV下降,则上涨缺乏资金支持,反转概率高。
量化选股中,OBV可用于个股筛选、择时买卖和风险预警。与单纯看成交量不同,OBV将成交量方向化,形成连续曲线,便于计算统计特征。
量化选股中OBV的计算与处理
标准OBV计算:

import pandas as pd
import numpy as np
def calculate_obv(df):
# df包含'close','volume'列
obv = [0]
for i in range(1, len(df)):
if df['close'].iloc[i] > df['close'].iloc[i-1]:
obv.append(obv[-1] + df['volume'].iloc[i])
elif df['close'].iloc[i] < df['close'].iloc[i-1]:
obv.append(obv[-1] - df['volume'].iloc[i])
else:
obv.append(obv[-1])
df['obv'] = obv
return df
量化处理时需注意:复权价格必须使用后复权或前复权,避免除权导致信号失真;成交量单位统一为股或手;停牌日成交量设为零,OBV不变。
基于OBV的股价走势预测方法
1. OBV与价格背离
顶背离:价格创出新高,OBV未创新高,甚至走低,预示上涨动能衰竭。量化实现时,定义价格N日高点与OBV的N日高点,检测两者是否同步。
def detect_bearish_divergence(df, window=20):
price_high = df['close'].rolling(window).max()
obv_high = df['obv'].rolling(window).max()
# 价格新高但OBV未新高
cond = (df['close'] == price_high) & (df['obv'] < obv_high * 0.98)
return cond
底背离相反:价格创新低,OBV未创新低,资金暗中吸筹,预示底部形成。底背离信号在量化选股中可做买入初筛。
2. OBV均线交叉
对OBV取短期与长期均线,如5日与20日。短线上穿长线为金叉,下穿为死叉。结合价格趋势过滤:
df['obv_ma5'] = df['obv'].rolling(5).mean()
df['obv_ma20'] = df['obv'].rolling(20).mean()
df['signal'] = 0
df.loc[(df['obv_ma5'] > df['obv_ma20']) & (df['obv_ma5'].shift(1) <= df['obv_ma20'].shift(1)), 'signal'] = 1
df.loc[(df['obv_ma5'] < df['obv_ma20']) & (df['obv_ma5'].shift(1) >= df['obv_ma20'].shift(1)), 'signal'] = -1
金叉买入,死叉卖出。OBV均线交叉在震荡市中易产生假信号,需配合波动率过滤。
3. OBV斜率与趋势强度
计算OBV的N日线性回归斜率,斜率向上且为正,表明资金持续流入。斜率数值越大,趋势越强。量化选股可设定阈值:
from scipy.stats import linregress
def obv_slope(series, window=10):
slopes = []
for i in range(len(series)):
if i < window:
slopes.append(np.nan)
else:
y = series[i-window:i].values
x = np.arange(window)
slope = linregress(x, y).slope
slopes.append(slope)
return slopes
df['obv_slope'] = obv_slope(df['obv'], 10)
选出OBV斜率连续3日为正且递增的股票,作为强势候选。
4. OBV突破形态
OBV突破前期盘整平台高点,对应价格可能即将突破。量化识别:OBV创M日新高,而价格未创M日新高,视为领先信号。
def obv_breakout(df, m=30):
obv_max = df['obv'].rolling(m).max()
price_max = df['close'].rolling(m).max()
cond = (df['obv'] == obv_max) & (df['close'] < price_max * 0.98)
return cond
该信号出现后,若后续价格放量突破,则确认上涨。
OBV与其他指标共振
单一OBV信号胜率有限。量化选股中常与以下指标结合:
价格均线:OBV金叉且价格站上20日均线,买入胜率提升。
MACD:OBV底背离且MACD金叉,底部反转概率高。
RSI:OBV顶背离且RSI超买,卖出信号更可靠。
成交量比率:OBV上升且量比大于1.5,资金活跃。
多指标共振可设定权重打分,例如OBV背离40%、MACD金叉30%、均线多头30%,总分超过70分触发交易。
量化回测中的OBV参数优化
OBV本身无参数,但衍生信号有窗口期。窗口过短噪音大,过长滞后。针对A股市场,常用窗口为10-30日。量化回测需注意:
样本内优化窗口,样本外验证。
考虑交易成本,OBV信号频繁,滑点影响大。
分市场状态:趋势市OBV均线交叉有效,震荡市背离更有效。
参数优化代码示例:
best_sharpe = -np.inf
best_window = None
for w in range(5, 31):
df['obv_ma'] = df['obv'].rolling(w).mean()
df['signal'] = np.where(df['obv'] > df['obv_ma'], 1, 0)
df['ret'] = df['close'].pct_change().shift(-1) * df['signal']
sharpe = df['ret'].mean() / df['ret'].std() * np.sqrt(252)
if sharpe > best_sharpe:
best_sharpe = sharpe
best_window = w
实战注意事项
OBV在流动性差的股票中易被操纵,大盘股和指数ETF上更稳定。期货市场中,OBV需使用主力合约连续数据,并注意换月缺口。期货成交量含双边,与股票不同,OBV绝对值意义弱,更应关注相对变化。
量化选股使用OBV时,避免单纯依据OBV绝对值排序,应计算OBV的变动率、斜率、背离等衍生特征。结合基本面因子(如ROE、营收增速)可过滤垃圾股信号。
最终,OBV作为量价分析的经典工具,在量化框架下需转化为可计算、可回测的规则,并与风险管理结合。设置止损:OBV跌破其20日均线或价格跌破买入价5%时离场。仓位管理:单只股票OBV信号仓位不超过总资金10%。