一、Order Book 深度解析:订单簿到底长什么样?

做美股量化交易,你第一个要面对的数据结构就是 Order Book。说白了,它就是交易所维护的一个实时账本——记录着当前所有未成交的买单和卖单。

我个人习惯把 Order Book 想象成一个「排队系统」。买方排一队,卖方排一队。谁的价格好谁排前面。嗯,就这么简单。

1.1 订单簿的核心结构

一个标准的 Level 2 订单簿,包含两个核心部分:

  • Bid(买方队列):按价格从高到低排列
  • Ask(卖方队列):按价格从低到高排列

每个价格档位上,都挂着对应的挂单量(Size)。

关键点:Bid 的最高价叫 Best Bid,Ask 的最低价叫 Best Ask。两者之间的差距就是 Spread(价差)。

我在项目中遇到过一个问题:有些新手会把 Bid 和 Ask 搞反。记住一个口诀——「买方想便宜,所以出价低;卖方想赚钱,所以要价高」。但 Bid 是买方愿意出的最高价,Ask 是卖方愿意接受的最低价。别弄混了。

1.2 用 Python 模拟一个订单簿

光说理论没意思,咱们直接上代码。下面这个例子,我用 Python 模拟了一个简化版的订单簿:

# 模拟一个简单的订单簿
order_book = {
    'bids': [  # 买方队列,价格从高到低
        {'price': 150.25, 'size': 1200},
        {'price': 150.20, 'size': 800},
        {'price': 150.15, 'size': 2500},
        {'price': 150.10, 'size': 1500},
    ],
    'asks': [  # 卖方队列,价格从低到高
        {'price': 150.30, 'size': 900},
        {'price': 150.35, 'size': 1800},
        {'price': 150.40, 'size': 1100},
        {'price': 150.45, 'size': 2200},
    ]
}

# 获取最佳买卖价
best_bid = order_book['bids'][0]['price']
best_ask = order_book['asks'][0]['price']
spread = best_ask - best_bid

print(f"Best Bid: {best_bid}, Best Ask: {best_ask}")
print(f"Spread: {spread:.2f}")

你想想看,这个结构其实很直观。每个价格档位就是一个「水位线」,挂单量就是水位线上的「水量」。水量越大,说明这个价格位置的支撑或阻力越强。

二、Price Level 与 Size:价格档位和挂单量的数据结构

接下来我们深入看看 Price Level 和 Size 的具体结构。这部分我建议你重点理解,因为它是所有高级策略的基础。

2.1 价格档位的组织方式

交易所不会把每个价格都列出来,而是只展示有挂单的价格档位。每个档位包含:

  • Price:价格,精确到小数点后两位(美股通常如此)
  • Size:该价格上的总挂单量(单位:股)
  • Order Count:该价格上有多少个独立的订单(有些数据源提供)

举个例子,苹果股票在 150.25 这个价位上有 1200 股挂单,这 1200 股可能是 3 个订单组成的(比如 500+400+300)。

我的经验:只看 Size 不够,还要看 Order Count。如果 Size 很大但 Order Count 很小,说明是大户在挂单,这个支撑/阻力往往更可靠。反之,如果 Size 大但 Order Count 也大,可能是散户聚集,容易被击穿。

2.2 数据更新的增量模式

Level 2 数据是实时推送的,每次更新只发送变化的部分。常见的更新类型有:

操作类型 说明 示例
Add 新增一个订单 在 150.25 增加 500 股买单
Cancel 撤销一个订单 在 150.25 减少 300 股买单
Execute 成交(部分或全部) 在 150.25 成交 200 股买单
Replace 修改订单(价格或数量) 把 150.25 的买单改为 150.30

我曾经踩过一个坑:以为每次推送都是完整的订单簿快照。结果用增量数据直接覆盖本地状态,导致数据错乱。后来才明白,必须维护一个本地订单簿,每次收到增量更新就做对应的增删改操作。

2.3 用 Python 处理增量更新

# 维护本地订单簿
local_book = {'bids': {}, 'asks': {}}

def apply_update(update):
    """处理增量更新"""
    side = update['side']  # 'bid' or 'ask'
    price = update['price']
    size = update['size']
    action = update['action']  # 'add', 'cancel', 'execute'
    
    if action == 'add':
        local_book[side][price] = local_book[side].get(price, 0) + size
    elif action in ('cancel', 'execute'):
        local_book[side][price] = local_book[side].get(price, 0) - size
        # 如果该价格档位挂单量为0,删除该档位
        if local_book[side][price] <= 0:
            del local_book[side][price]
    
    # 按价格排序
    local_book[side] = dict(sorted(
        local_book[side].items(), 
        reverse=(side == 'bids')
    ))

三、Time & Sales:逐笔成交数据结构

Time & Sales,也叫 Tape(磁带数据),记录的是每一笔实际发生的交易。和订单簿不同,它记录的是「已经发生的事」,而不是「正在等待的事」。

3.1 逐笔成交的核心字段

每一笔成交记录通常包含以下信息:

  • Timestamp:成交时间,精确到毫秒甚至微秒
  • Price:成交价格
  • Size:成交数量
  • Exchange:成交的交易所代码(如 NYSE、NASDAQ)
  • Sale Condition:成交条件(如普通交易、大宗交易等)

注意:不同数据源的时间精度不一样。有的只到秒级,有的到毫秒级。做高频策略时,时间精度不够会导致信号延迟,直接影响收益。

3.2 逐笔成交与订单簿的关系

这两者其实是同一枚硬币的两面。订单簿展示的是「流动性池子」,逐笔成交展示的是「从池子里舀水的过程」。

举个例子:

  1. 订单簿显示 150.30 有 1000 股卖单
  2. 突然来了一笔 150.30 成交 800 股的记录
  3. 订单簿上 150.30 的挂单量减少 800 股

你看,逐笔成交就是订单簿变化的「原因」。我习惯把两者结合起来看——如果某价格档位频繁出现大额成交,说明这个位置有「真金白银」在博弈。

3.3 用 Python 解析逐笔成交数据

# 模拟逐笔成交数据
trades = [
    {'time': '09:30:00.123', 'price': 150.30, 'size': 800, 'exchange': 'N'},
    {'time': '09:30:00.456', 'price': 150.31, 'size': 200, 'exchange': 'Q'},
    {'time': '09:30:00.789', 'price': 150.29, 'size': 1500, 'exchange': 'N'},
]

# 计算累计成交量
total_volume = sum(t['size'] for t in trades)
vwap = sum(t['price'] * t['size'] for t in trades) / total_volume

print(f"总成交量: {total_volume} 股")
print(f"成交量加权均价(VWAP): {vwap:.2f}")

四、知识体系总览

下面这张图,我把本章的核心知识点串起来了。你可以把它当作一个「地图」,随时回来对照:

Level 2 数据结构知识体系 Order Book 订单簿 Price Level & Size Time & Sales 逐笔成交 核心组成 • Bid 买方队列(高价→低价) • Ask 卖方队列(低价→高价) • Best Bid / Best Ask / Spread 关键属性 • Price 价格(精确到分) • Size 挂单量(总股数) • Order Count 订单数量 记录字段 • Timestamp 时间戳 • Price / Size 成交价量 • Exchange / Sale Condition 三者关系:订单簿展示流动性 → 价格档位组织流动性 → 逐笔成交消耗流动性 增量更新操作类型 Add(新增)→ Cancel(撤销)→ Execute(成交)→ Replace(修改) 维护本地订单簿,每次增量更新做对应操作

嗯,以上就是本章的全部内容。数据结构是量化交易的基石,把这些搞明白了,后面讲策略的时候你才能跟得上。记住,数据本身不会说谎,但解读数据的方式决定了你的交易水平。

一句话总结:Order Book 是「将要发生」的,Time & Sales 是「已经发生」的,Price Level 是组织这些数据的「格子」。三者结合,才能看清市场的真实面貌。


专注资料整理