市场微观结构:限价订单簿、买卖盘口、市场深度
各位,咱们今天聊点实在的。高频交易这行当,说白了就是跟市场微观结构打交道。你如果不懂订单簿,不懂盘口,那就像开车不看仪表盘——迟早要出事。
我个人习惯,每次开始一个新策略之前,第一件事就是先把目标品种的微观结构摸透。为什么?因为价格波动只是表象,真正的博弈全藏在订单簿里。
限价订单簿(LOB)——市场的“记账本”
限价订单簿,英文叫 Limit Order Book,简称 LOB。你可以把它想象成一个巨大的记账本,上面记录着所有交易者挂出来的买卖意愿。
每一笔限价订单,都包含三个要素:方向(买还是卖)、价格、数量。系统把这些订单按价格排序,买盘从高到低,卖盘从低到高,就形成了我们看到的订单簿。
核心要点:订单簿不是静态的。它每时每刻都在变化——有人挂单,有人撤单,有人成交。高频交易的核心,就是捕捉这些变化中的规律。
我在项目中遇到过一件事,印象很深。有一次我们跑一个套利策略,回测数据漂亮得不行,结果一上实盘就亏钱。查了半天,发现是订单簿的更新延迟问题。回测用的是 tick 级数据,但实盘里订单簿的 snapshot 和增量更新之间有微小的时差,就是这点时差,让我们的策略一直在吃哑巴亏。
买卖盘口——最直观的博弈前线
盘口,就是订单簿最顶层的几档数据。买一、卖一、买二、卖二……这些数字,是市场最直接的博弈信号。
举个例子,你看一个股票的盘口:
| 档位 | 买价 | 买量 | 卖价 | 卖量 |
|---|---|---|---|---|
| 1 | 100.01 | 500 | 100.02 | 300 |
| 2 | 100.00 | 1200 | 100.03 | 800 |
| 3 | 99.99 | 2000 | 100.04 | 1500 |
看到没?买一和卖一之间的差价,就是 spread。这个 spread 越小,说明市场流动性越好。买一挂了 500 手,卖一只有 300 手——这说明什么?说明卖方有点犹豫,或者买方在试探。
你想想看,如果卖一突然从 300 手变成 3000 手,价格还没变,那大概率是有人在压盘。这时候你冲进去买,可能就被套住了。
我的经验:别只看买一卖一。我习惯把前五档的挂单量加起来看。如果买盘前五档总量远大于卖盘前五档,但价格就是不涨,那多半是有人在下面托单,实际意图可能是出货。
市场深度——你能吃下多少“货”
市场深度,衡量的是你在某个价格水平上能成交多少量。深度越大,大单对价格的冲击就越小。
怎么算?很简单。比如你想买 10000 股,从卖一往下吃:
- 卖一 100.02 有 300 股,吃掉
- 卖二 100.03 有 800 股,吃掉
- 卖三 100.04 有 1500 股,吃掉
- ……一直吃到凑够 10000 股为止
最后成交的加权平均价,就是你的实际买入成本。这个成本跟当前卖一价的差距,就是 市场冲击成本。
我曾经犯过一个错误。当时做一个统计套利策略,觉得某个价差偏离了 3 个标准差,机会难得,直接一把梭进去。结果因为市场深度不够,我的单子把价格推回去了,等于是自己把套利空间给填平了。嗯,从那以后,我所有策略都加了深度检查。
订单簿的三种状态
做高频交易,你得学会“读”订单簿的状态。我一般把它分成三种:
- 均衡状态:买卖盘口力量相当,spread 稳定,订单簿呈“金字塔”形状——离最优价越远,挂单量越大。
- 失衡状态:某一侧明显厚实,另一侧单薄。比如买盘堆积如山,卖盘稀稀拉拉。这时候价格大概率要往上走。
- 稀疏状态:订单簿很“空”,几档之间差距大,spread 宽。这种情况通常出现在流动性差的品种或非交易活跃时段,进去容易,出来难。
注意:订单簿的状态是动态变化的。均衡可能瞬间变成失衡,因为一个大单撤单或进场。高频策略必须能实时感知这种变化,而不是每隔几秒刷新一次。
知识体系总览
下面这张图,是我自己整理的市场微观结构知识框架。你看一眼,心里就有数了。
用 Python 看一眼订单簿
光说不练假把式。咱们用 Python 拉一下真实的订单簿数据看看。这里以币安的 BTC/USDT 为例:
import requests
import json
# 获取币安 BTC/USDT 订单簿
url = "https://api.binance.com/api/v3/depth"
params = {"symbol": "BTCUSDT", "limit": 10}
resp = requests.get(url, params=params)
data = resp.json()
print("买盘(Bids):")
for bid in data["bids"][:5]:
print(f" 价格: {bid[0]}, 数量: {bid[1]}")
print("\n卖盘(Asks):")
for ask in data["asks"][:5]:
print(f" 价格: {ask[0]}, 数量: {ask[1]}")
# 计算买卖盘口总量
total_bid_vol = sum(float(b[1]) for b in data["bids"])
total_ask_vol = sum(float(a[1]) for a in data["asks"])
print(f"\n买盘总量: {total_bid_vol:.4f}")
print(f"卖盘总量: {total_ask_vol:.4f}")
print(f"买卖比: {total_bid_vol/total_ask_vol:.4f}")
这段代码很简单,但很实用。你跑一下就能看到当前市场的盘口情况。我一般会在策略启动前先跑一遍这个,看看市场深度够不够,spread 大不大。
小技巧:别只看一次 snapshot。我习惯连续拉 10 次,每次间隔 100 毫秒,观察订单簿的变化速度。如果变化剧烈,说明有人在搞事情,这时候策略参数要调得更保守一些。
避坑指南
最后,分享几个我踩过的坑:
- 别迷信盘口数据:有些大资金会挂假单,挂上去又撤掉,就是为了误导你。我见过最夸张的,有人在买一挂了 5000 个比特币,然后一秒内全撤了。
- 注意数据源延迟:交易所的 REST API 通常有几百毫秒的延迟。做高频交易,必须用 WebSocket 的增量数据流。
- 深度不是万能的:有些品种深度看起来很厚,但都是散户的单子,一有风吹草动全撤了。真正的深度,要看那些长期不动的“冰山订单”。
嗯,今天就先聊到这儿。市场微观结构这东西,越挖越深。你先把订单簿、盘口、深度这三个概念吃透,后面讲订单流、成交量分布的时候,你才能跟得上。