第28章 市场微观结构:订单流分析,买卖盘口深度分析,成交量分布(Volume Profile),市场冲击模型

做市商这行干久了,你会发现一个道理:价格只是表象,订单流才是真相

我刚开始做衍生品做市的时候,整天盯着K线图,觉得价格涨跌就是一切。后来被市场狠狠教育了几次,才明白——你看到的那个成交价,其实是无数订单博弈后的结果。真正有价值的信息,藏在订单簿的每一层深度里,藏在每一笔成交的节奏里。

这一章,我们就来拆解市场微观结构。说白了,就是教你如何读懂市场的「心电图」。

28.1 订单流分析:读懂市场的呼吸

订单流分析,核心就一句话:谁在买,谁在卖,力度如何

我个人习惯把订单流分成两类:

  • 主动成交单(Taker):直接吃单,不挂单。这是「急脾气」的资金。
  • 被动挂单(Maker):挂在盘口等成交。这是「耐心」的资金。

你想想看,如果主动买单持续涌入,但价格不涨,说明什么?说明上方有巨量卖单在压着。这时候追多,大概率被埋。

核心指标:订单流失衡度(Order Flow Imbalance)

公式很简单:OFI = (主动买单量 - 主动卖单量) / (主动买单量 + 主动卖单量)

OFI > 0.3,说明买方主导;OFI < -0.3,卖方主导。介于之间,就是震荡。

我在项目中遇到过一种情况:OFI持续为正,但价格横盘不动。后来一查,是某个大户在偷偷挂冰山订单,一边吃单一边压价。嗯,这种时候,跟着OFI做多就是送钱。

28.2 买卖盘口深度分析:看穿订单簿的伪装

盘口深度,就是订单簿上各个价位的挂单量。但别只看第一档,那太浅了。

我建议你至少看五档,甚至十档。为什么?因为真正的「大单」往往藏在后面。

28.2.1 深度斜率分析

把各档位的挂单量画成曲线,看斜率。斜率陡峭,说明流动性集中;斜率平缓,说明流动性分散。

举个例子:

  • 买一价:100手
  • 买二价:200手
  • 买三价:500手

这种递增的深度,说明下方支撑很强。反之,如果买一价100手,买二价50手,买三价20手——这种递减结构,一碰就破。

避坑指南:我曾经被「虚假深度」坑过。有些做市商会挂大单制造假象,然后瞬间撤单。所以,我现在的策略是:只看「挂单时间超过3秒」的订单。那些秒挂秒撤的,直接过滤掉。

28.2.2 买卖盘口价差(Spread)

价差越小,流动性越好。但要注意,价差突然扩大,往往是市场变盘的信号。

我记得有一次,某个币种价差从0.01突然扩大到0.05,我立刻警觉,减了一半仓位。5分钟后,价格暴跌5%。

28.3 成交量分布(Volume Profile):找到市场的「价值区间」

Volume Profile(VP)和传统成交量最大的区别是:它把成交量按价格分布,而不是按时间分布

说白了,就是告诉你:在哪个价格区间,成交最活跃。

28.3.1 核心概念

  • 价值区间(Value Area, VA):成交量占比70%的价格区间。这是多空双方认可的价格范围。
  • 控制点(Point of Control, POC):成交量最大的那个价格。这是市场的「重心」。
  • 高成交量节点(High Volume Node, HVN):支撑/阻力位。
  • 低成交量节点(Low Volume Node, LVN):价格容易快速穿越的区域。

实战用法

当价格回到POC附近,且OFI显示买方发力,我会考虑入场。如果价格跌破VA下沿,且成交量放大,那就是止损信号。

28.3.2 代码示例:计算Volume Profile

下面是我用Python写的一个简化版VP计算函数。实际生产中,我会用C++重写,但原理一样。

import numpy as np
import pandas as pd

def calculate_volume_profile(trades, price_bins=100):
    """
    trades: DataFrame, 包含 'price' 和 'volume' 列
    price_bins: 价格区间数量
    """
    price_min = trades['price'].min()
    price_max = trades['price'].max()
    bin_width = (price_max - price_min) / price_bins
    
    # 将价格分配到区间
    trades['price_bin'] = ((trades['price'] - price_min) / bin_width).astype(int)
    
    # 按区间聚合成交量
    vp = trades.groupby('price_bin')['volume'].sum()
    
    # 计算价值区间(70%成交量)
    total_volume = vp.sum()
    sorted_vp = vp.sort_values(ascending=False)
    cum_volume = 0
    value_area = []
    for price_bin, vol in sorted_vp.items():
        cum_volume += vol
        value_area.append(price_bin)
        if cum_volume / total_volume >= 0.7:
            break
    
    # POC:成交量最大的区间
    poc_bin = vp.idxmax()
    poc_price = price_min + (poc_bin + 0.5) * bin_width
    
    return {
        'vp': vp,
        'value_area': (min(value_area), max(value_area)),
        'poc': poc_price,
        'bin_width': bin_width
    }

注意:VP的计算周期很关键。我个人习惯用30分钟作为基础周期,太长会滞后,太短噪音太大。你可以根据品种的波动率调整。

28.4 市场冲击模型:你的订单会「推」动价格

做市商最怕什么?不是价格波动,而是自己的订单影响了价格

你想想看,如果你要卖1000手,但盘口只有500手的买单,你的订单就会吃掉所有买单,把价格砸下去。这就是市场冲击。

28.4.1 冲击模型的核心公式

最经典的模型是Almgren-Chriss模型。简化版如下:

市场冲击 = 永久冲击 + 临时冲击

永久冲击 = α * (订单量 / 总成交量)
临时冲击 = β * (订单量 / 盘口深度) * 价差

其中:
α 和 β 是经验参数,需要根据历史数据拟合
总成交量:过去N分钟的累计成交量
盘口深度:当前最优档的挂单量

我在项目中遇到过一个问题:临时冲击参数β设得太高,导致系统频繁撤单。后来我改成动态β——盘口深度越薄,β越大。这样更符合实际情况。

28.4.2 实战中的冲击控制

做市商的核心策略之一,就是把大单拆成小单

  • 如果订单量小于盘口深度的10%,直接吃单。
  • 如果订单量在10%-50%之间,拆成3-5笔,每笔间隔100-500毫秒。
  • 如果订单量超过50%,改用冰山订单,或者等待流动性恢复。

我的经验:冲击模型不是越复杂越好。我见过有人用深度学习预测冲击,结果过拟合得一塌糊涂。其实,一个简单的线性模型,加上动态参数,在大多数情况下就够用了。

28.5 知识体系总览

下面这张图,是我自己梳理的市场微观结构知识体系。你可以把它当作一个「检查清单」——每次做策略之前,过一遍这些维度。

市场微观结构知识体系 订单流分析 • 主动/被动订单 • 订单流失衡度 • 冰山订单识别 • 成交节奏分析 • 大单追踪 盘口深度分析 • 多档深度斜率 • 买卖价差分析 • 挂单持续时间 • 虚假深度检测 • 流动性分层 成交量分布 • 价值区间(VA) • 控制点(POC) • 高/低成交量节点 • 多周期VP对比 • 成交量缺口 市场冲击模型 • 永久/临时冲击 • Almgren-Chriss • 动态参数拟合 • 大单拆单策略 • 冰山订单算法 核心目标:降低信息不对称,优化订单执行 从「看价格」升级到「看订单流」

28.6 实战中的避坑指南

最后,分享几个我踩过的坑:

  1. 别迷信单一指标:OFI、VP、深度斜率,每个指标都有盲区。我习惯至少三个指标共振才出手。
  2. 注意数据延迟:订单流数据对延迟极其敏感。我曾经用WebSocket接收数据,延迟200ms,结果策略在实盘里完全失效。后来改成UDP直连,延迟降到5ms以内。
  3. 小心「假突破」:价格突破VA上沿,但成交量没有放大,往往是假突破。我吃过好几次这种亏。
  4. 冲击模型要定期重训:市场结构会变。我每个月都会重新拟合α和β参数,否则模型会慢慢失效。

一句话总结:市场微观结构分析,就是帮你从「盲人摸象」变成「庖丁解牛」。订单流是刀,盘口深度是骨,成交量分布是肉,冲击模型是力道。四者结合,你才能游刃有余。


交易系统化学习资料 微信Strategy888888