4. 市场微观结构:订单簿(Order Book)深度解析

做价差套利,尤其是高频那一套,你绕不开一个东西——订单簿

说白了,订单簿就是交易所的「实时账本」。它记录了所有交易者挂出来的买单和卖单。我个人习惯把它看作市场的「心电图」,每一笔挂单、撤单、成交,都是市场情绪的跳动。

嗯,咱们今天就把这东西彻底拆开看看。

4.1 买卖盘口:Bid 和 Ask 的博弈

订单簿最核心的两个概念:Bid(买盘)Ask(卖盘)

  • Bid:别人愿意出的最高买入价。说白了,就是「我最高出这个价买,谁卖给我?」
  • Ask:别人愿意接受的最低卖出价。就是「我最低这个价卖,谁要?」

Bid 和 Ask 之间的差价,叫 Spread(价差)。这个数字越小,说明市场越活跃,流动性越好。

核心公式:

Spread = Ask_Price - Bid_Price

Mid_Price = (Ask_Price + Bid_Price) / 2

我在项目中遇到过一种情况:某个冷门币种,Spread 能大到几个百分点。你想想看,这种品种做套利,还没进场就被价差吃掉了利润。所以,Spread 是我们筛选品种的第一道门槛

4.2 市场深度与流动性

光看 Spread 还不够。你得看 Depth(深度)

市场深度,指的是在某个价格水平上,有多少挂单量。深度越厚,说明这个价位能承接的资金量越大。

举个例子:

价格 买盘量(Bid Volume) 卖盘量(Ask Volume)
100.00 500 200
99.99 800 150
99.98 1200 100

你看,在 100.00 这个价位,买盘有 500 手,卖盘只有 200 手。这说明什么?说明买方力量更强,价格有向上突破的倾向。

我自己的经验是:做套利,一定要避开深度薄的品种。曾经有一次,我在一个深度只有几十手的品种上做价差,结果一个大单砸下来,直接把我的挂单打穿,滑点损失惨重。嗯,从那以后,我给自己定了个规矩:买卖盘口前五档的总深度,至少是单笔交易量的 10 倍以上,才考虑进场。

避坑指南:

我曾经以为只看「盘口总量」就够了,后来发现不对。你得看「盘口分布」。如果所有深度都集中在第一档,后面几档稀稀拉拉,那这个流动性是「虚胖」的。真正健康的深度,应该是从第一档到第五档,逐层递减,但每一层都有足够的量。

4.3 Tick 数据与快照数据

做高频,数据是命根子。订单簿数据分两种:Tick 数据快照数据

4.3.1 Tick 数据

Tick 数据,也叫逐笔数据。它记录的是每一笔成交的详细信息:

  • 成交价格
  • 成交量
  • 成交时间(精确到微秒甚至纳秒)
  • 买卖方向(买方主动还是卖方主动)

说白了,Tick 数据就是市场的「原始录像带」。你回放它,就能看到每一笔交易是怎么发生的。

我个人习惯用 Tick 数据来做订单流分析。比如,连续出现大额主动买单,说明有大资金在吃货,价格大概率要涨。

4.3.2 快照数据

快照数据,是某一时刻订单簿的完整状态。它记录了所有档位的买卖挂单情况。

交易所通常每隔几毫秒或几十毫秒推送一次快照。快照数据的好处是:你能看到市场的全貌。但坏处是:它不连续。两次快照之间发生了什么,你不知道。

我的建议:

做价差套利,快照数据是基础,Tick 数据是进阶

如果你刚开始做,先用快照数据搭建策略。等跑通了,再引入 Tick 数据做精细化优化。

4.4 知识体系结构图

下面这张图,是我自己梳理的订单簿知识体系。你一看就明白了:

订单簿(Order Book) 买卖盘口 市场深度与流动性 数据源 Bid(买盘) Ask(卖盘) Spread(价差) 深度分布 流动性评估 滑点控制 Tick 数据 快照数据 数据回放与回测 核心目标:理解市场微观结构,降低交易成本

4.5 实战:如何用 Python 解析订单簿快照

光说不练假把式。我给你看一段我实际用过的代码片段。这是从交易所 WebSocket 推送中解析订单簿快照的逻辑:

import json
from collections import defaultdict

class OrderBook:
    def __init__(self):
        self.bids = defaultdict(float)  # 价格 -> 数量
        self.asks = defaultdict(float)
    
    def update_snapshot(self, data):
        """
        更新订单簿快照
        data 格式:{'bids': [[price, qty], ...], 'asks': [[price, qty], ...]}
        """
        # 清空旧数据
        self.bids.clear()
        self.asks.clear()
        
        # 更新买单
        for price, qty in data['bids']:
            if float(qty) > 0:
                self.bids[float(price)] = float(qty)
        
        # 更新卖单
        for price, qty in data['asks']:
            if float(qty) > 0:
                self.asks[float(price)] = float(qty)
    
    def get_top_n(self, n=5):
        """获取前 n 档买卖盘口"""
        sorted_bids = sorted(self.bids.items(), reverse=True)[:n]
        sorted_asks = sorted(self.asks.items())[:n]
        return sorted_bids, sorted_asks
    
    def get_spread(self):
        """计算当前价差"""
        if not self.bids or not self.asks:
            return None
        best_bid = max(self.bids.keys())
        best_ask = min(self.asks.keys())
        return best_ask - best_bid

# 使用示例
ob = OrderBook()
sample_data = {
    'bids': [['100.00', '500'], ['99.99', '800']],
    'asks': [['100.01', '200'], ['100.02', '150']]
}
ob.update_snapshot(sample_data)
print(f"当前价差: {ob.get_spread():.4f}")

注意:

这段代码是简化版。实际生产中,你还要处理:

  • 增量更新(只推送变化的部分,而不是全量快照)
  • 数据校验(防止脏数据污染订单簿)
  • 时间戳对齐(不同交易所的时钟可能不同步)

我曾经因为没做数据校验,导致订单簿里出现了一个「幽灵挂单」,策略跟着它跑了半天才发现问题。嗯,血的教训。

4.6 小结

订单簿这东西,看着简单,但里面的门道很深。你只要把买卖盘口、市场深度、Tick 和快照这几个概念吃透了,做价差套利就有了坚实的基础。

记住一句话:订单簿是市场的「底牌」。虽然你只能看到一部分,但足够你做出很多判断了。


专注资料整理