第三章 交易量分布分析:成交量分布(VPVR)、成交量剖面、成交量加权平均价(VWAP)

交易量分析,说白了就是看钱往哪儿流。

价格可以骗人,但成交量很难造假。我做了这么多年量化,最深的体会就是:价格是表象,成交量才是真相。今天咱们就聊聊三个最实用的成交量分析工具——VPVR、成交量剖面和VWAP。

3.1 成交量分布(VPVR) —— 市场的“记忆曲线”

VPVR,全称是Volume Profile Visible Range。名字挺唬人,其实原理很简单:把每个价格水平上的成交量画出来

你想想看,如果某个价格区间成交量特别大,说明什么?说明多空双方在这个位置激烈博弈过。这个位置就成了“价值区域”,价格未来很容易被拉回来。

核心概念:

  • 价值区域(VA):成交量占比70%的价格区间
  • 控制点(POC):成交量最大的那个价格
  • 高量节点:成交量显著高于相邻价格的节点

我个人习惯把VPVR当作“支撑阻力地图”来用。价格到了高量节点附近,我会格外小心——要么突破,要么反转,很少会平淡地穿过去。

实战技巧:

我曾经在BTC上吃过亏。价格突破POC后我直接追多,结果被假突破打脸。后来我学乖了:突破POC后,必须等成交量确认。如果突破时成交量萎缩,大概率是陷阱。

3.1.1 VPVR的计算逻辑

计算其实不复杂。把价格区间分成若干“格子”(比如0.5%一个格子),然后统计每个格子内的成交量总和。

def calculate_vpvr(df, num_bins=100):
    """
    计算成交量分布(VPVR)
    df: 包含'high','low','volume'的DataFrame
    """
    price_min = df['low'].min()
    price_max = df['high'].max()
    bin_width = (price_max - price_min) / num_bins
    
    # 初始化每个价格区间的成交量
    volume_profile = {i: 0 for i in range(num_bins)}
    
    for _, row in df.iterrows():
        # 确定该K线覆盖的价格区间
        start_bin = int((row['low'] - price_min) / bin_width)
        end_bin = int((row['high'] - price_min) / bin_width)
        
        # 将成交量均匀分配到每个价格区间
        volume_per_bin = row['volume'] / (end_bin - start_bin + 1)
        for bin_idx in range(start_bin, end_bin + 1):
            volume_profile[bin_idx] += volume_per_bin
    
    # 找到控制点(POC)
    poc_bin = max(volume_profile, key=volume_profile.get)
    poc_price = price_min + (poc_bin + 0.5) * bin_width
    
    return volume_profile, poc_price, bin_width

注意:这里用的是均匀分配法,实际交易中成交量在K线内部可能不是均匀的。更精确的做法是用Tick数据,但计算量会大很多。我一般用1分钟K线做近似,效果已经够用了。

3.2 成交量剖面 —— 把时间维度加进去

VPVR只看价格和成交量,但忽略了时间。成交量剖面(Volume Profile)则把时间也考虑进来了。

什么意思呢?就是看每个时间段内,成交量在价格上的分布情况。比如开盘半小时、午盘、尾盘,各自的成交量分布可能完全不同。

我记得有一次做股指期货,发现尾盘30分钟的成交量剖面总是出现“双峰”结构。后来复盘发现,这是机构在调仓——一边平多一边开空。抓住这个规律后,我尾盘策略的胜率提高了不少。

3.2.1 时间分割的三种方式

分割方式 说明 适用场景
固定时间间隔 每30分钟一段 常规分析
成交量等量分割 每段成交量相等 高波动行情
关键事件分割 按数据发布、开盘收盘分割 事件驱动策略

我个人偏爱成交量等量分割。为什么呢?因为市场活跃的时候,信息密度高,需要更细的粒度;冷清的时候,粗一点也无所谓。

def volume_profile_by_time(df, time_bins=13):
    """
    按时间分割计算成交量剖面
    """
    # 假设df包含'datetime','price','volume'列
    df['time_bin'] = pd.cut(df['datetime'].dt.hour, 
                            bins=time_bins, 
                            labels=False)
    
    profile = {}
    for bin_id in range(time_bins):
        bin_data = df[df['time_bin'] == bin_id]
        # 对该时间段内的数据计算VPVR
        profile[bin_id] = calculate_vpvr(bin_data)
    
    return profile

避坑指南:我曾经把时间分割做得太细(比如1分钟一段),结果每个剖面都稀稀拉拉的,根本看不出规律。后来我总结:时间段的成交量至少要有总成交量的5%,否则统计意义不大。

3.3 成交量加权平均价(VWAP) —— 机构的“成本线”

VWAP,机构交易员最熟悉的指标之一。说白了就是按成交量加权的平均成交价格

为什么机构这么看重VWAP?因为大资金进出市场,最怕的就是滑点。VWAP就是他们的“锚”——低于VWAP买,高于VWAP卖,长期来看能跑赢市场平均成本。

3.3.1 VWAP的计算公式

公式很简单:

VWAP = Σ(价格 × 成交量) / Σ(成交量)

但实际应用中,我们通常计算的是日内累积VWAP,也就是从开盘到当前时刻的加权平均价。

def calculate_vwap(df):
    """
    计算日内累积VWAP
    df: 包含'price','volume'的DataFrame,按时间排序
    """
    df['cum_vol'] = df['volume'].cumsum()
    df['cum_pv'] = (df['price'] * df['volume']).cumsum()
    df['vwap'] = df['cum_pv'] / df['cum_vol']
    return df['vwap']

VWAP的三种用法:

  1. 趋势判断:价格在VWAP上方运行 = 多头强势;下方 = 空头强势
  2. 支撑阻力:VWAP本身就是一个动态的支撑/阻力位
  3. 偏离回归:价格远离VWAP时,有回归的倾向

嗯,这里要注意:VWAP是日内指标,跨日使用意义不大。我见过有人把5天的VWAP连起来用,结果发现跟移动平均线差不多,失去了VWAP本身的优势。

3.4 三个工具的组合使用

单独用哪个都差点意思,组合起来才是王炸。

我的习惯是:

  • 先用VPVR画出全局的支撑阻力地图
  • 再用成交量剖面看当前时间段的资金博弈情况
  • 最后用VWAP作为日内交易的“锚”

举个例子:如果VPVR显示当前价格处于高量节点附近,成交量剖面显示该时间段资金在持续流入,而价格刚好在VWAP上方——这时候做多,胜率会高很多。

重要提醒:这三个工具都是基于历史数据的。市场结构可能突然变化(比如突发消息、政策变动),这时候历史规律会失效。我2015年股灾时就吃过这个亏——VPVR显示的支撑位在熔断面前一文不值。

3.5 本章知识体系

下面这张图展示了三个工具之间的关系和适用场景:

交易量分布分析核心体系 VPVR 成交量分布 成交量剖面 时间+价格+成交量 VWAP 成交量加权平均价 核心功能 • 识别价值区域(VA) • 定位控制点(POC) • 发现高量节点 核心功能 • 时间维度分析 • 资金流向追踪 • 时段特征提取 核心功能 • 机构成本锚点 • 动态支撑阻力 • 偏离回归信号 组合策略应用 VPVR定区间 + 剖面看资金 + VWAP定入场 三者结合,形成完整的交易量分析体系

好了,这一章的内容就到这里。VPVR、成交量剖面和VWAP这三个工具,每一个单独拿出来都能写一本书。但作为量化交易者,我更看重的是它们如何协同工作。记住:工具是死的,组合是活的