4、订单簿基础:限价单与市价单、订单簿结构、买卖盘口深度
做市的核心,说白了就是跟订单簿打交道。你每天盯着的那个买卖挂单列表,就是订单簿。我刚开始做量化的时候,觉得这东西不就是个价格列表嘛,有啥好研究的?后来在实盘中吃了不少亏,才明白——订单簿的每一层,都藏着市场参与者的真实意图。
今天咱们就把订单簿拆开揉碎了讲。限价单和市价单的区别、订单簿怎么组织、盘口深度怎么看。这些是基本功,但基本功往往最容易被忽视。
4.1 限价单与市价单:两种最基础的订单类型
先说说这两种订单。你想想看,你去菜市场买菜——
- 市价单:就是「老板,给我来两斤土豆,多少钱都行,马上要!」。你不在乎价格,只在乎成交速度。
- 限价单:就是「老板,土豆超过3块一斤我就不买了,你啥时候降到3块以下再卖给我」。你在乎价格,愿意等。
在交易系统里,这两种订单的行为完全不同。
市价单(Market Order)
市价单会立即以当前市场上可用的最优价格成交。如果你买,就吃掉卖一;如果卖盘不够,继续吃卖二、卖三……直到你的订单全部成交。
优点:成交速度快,几乎100%成交。
缺点:你无法控制成交价格。尤其在流动性差的时候,滑点可能大得吓人。
我记得有一次做回测,一个市价单在盘口深度只有几百张的合约上,直接打穿了三个价位,滑点损失比预期多了5倍。嗯,从那以后我再也不敢在低流动性品种上无脑用市价单了。
限价单(Limit Order)
限价单指定一个价格,只有市场价格达到或优于这个价格时才会成交。你挂一个买一价,等着别人来卖给你。
优点:你可以精确控制成交价格,甚至能赚到盘口差价。
缺点:可能永远无法成交,或者成交延迟很大。
做市商的核心工作之一,就是不断挂限价单、撤单、再挂。说白了,我们赚的就是限价单提供的流动性溢价。
核心区别一句话总结:市价单买速度,限价单买价格。做市商几乎只用限价单,偶尔用市价单来调整仓位。
4.2 订单簿结构:买卖双方的「战场地图」
订单簿,就是所有未成交限价单的集合。它按价格从高到低排列,分成买盘和卖盘两侧。
咱们来看一个典型的订单簿结构:
| 卖盘(Ask Side) | 价格 | 数量 | 累计数量 |
|---|---|---|---|
| 卖五 | 100.50 | 200 | 1500 |
| 卖四 | 100.40 | 300 | 1300 |
| 卖三 | 100.30 | 400 | 1000 |
| 卖二 | 100.20 | 350 | 600 |
| 卖一 | 100.10 | 250 | 250 |
| 买一 | 100.00 | 300 | 300 |
| 买二 | 99.90 | 500 | 800 |
| 买三 | 99.80 | 400 | 1200 |
| 买四 | 99.70 | 200 | 1400 |
| 买五 | 99.60 | 100 | 1500 |
这里有几个关键概念:
- 买一(Bid):当前最高的买入价格,100.00
- 卖一(Ask):当前最低的卖出价格,100.10
- 价差(Spread):卖一 - 买一 = 0.10。这是做市商能赚到的理论最大利润
- 盘口深度:每个价格上的挂单数量
我个人习惯把订单簿看作一个「价格-数量」的二维地图。买盘像一座山,卖盘像另一座山,中间那个山谷就是当前成交价。做市商的工作,就是在山谷两边来回搭桥。
4.3 买卖盘口深度:读懂市场的「呼吸」
盘口深度,说白了就是每个价位上挂了多少钱。它告诉你:如果你想大额交易,市场能承受多大的冲击。
举个例子。假设你想用市价单买入1000股,当前订单簿如下:
- 卖一:100.10,250股
- 卖二:100.20,350股
- 卖三:100.30,400股
你的1000股会这样成交:
- 先吃掉卖一的250股,成交价100.10
- 再吃掉卖二的350股,成交价100.20
- 再吃掉卖三的400股,成交价100.30
总成交金额 = 250×100.10 + 350×100.20 + 400×100.30 = 100,285元
平均成交价 = 100.285元
如果你只看卖一价格100.10,以为只需要100,100元就能买到,那就大错特错了。实际多花了185元。这就是滑点。
避坑指南:我曾经在写策略时,直接用卖一价格乘以数量来计算买入成本。结果回测跑得漂亮,实盘一跑就亏。后来才发现,大单必须考虑盘口深度,用「价格-数量加权平均」来计算真实成交价。
4.4 订单簿的实时变化:做市商的「心跳」
订单簿不是静止的。每一秒都有新订单进来、撤单、成交。做市商需要实时跟踪这些变化。
常见的订单簿事件有:
- 新增限价单:有人在某个价位挂单
- 撤单:有人取消了挂单
- 成交:限价单被市价单吃掉
- 修改:有人改了价格或数量(有些交易所支持)
我个人习惯用一个「增量更新」的方式来维护订单簿。每次只处理变化的部分,而不是全量替换。这样效率高得多。
下面是一个简单的订单簿维护代码示例:
class OrderBook:
def __init__(self):
self.bids = {} # 买盘,价格->数量
self.asks = {} # 卖盘,价格->数量
def update(self, side, price, quantity):
"""增量更新订单簿"""
if side == 'bid':
if quantity == 0:
# 数量为0表示撤单
self.bids.pop(price, None)
else:
self.bids[price] = quantity
elif side == 'ask':
if quantity == 0:
self.asks.pop(price, None)
else:
self.asks[price] = quantity
def get_top_of_book(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_bid, best_ask, best_ask - best_bid
def get_depth(self, levels=5):
"""获取指定深度的盘口"""
sorted_bids = sorted(self.bids.items(), reverse=True)[:levels]
sorted_asks = sorted(self.asks.items())[:levels]
return sorted_bids, sorted_asks
这段代码虽然简单,但已经能处理大部分场景了。实盘中,你还需要处理并发、延迟、数据对齐等问题。不过核心逻辑就是这个——维护一个价格到数量的映射。
4.5 盘口深度的可视化:一眼看懂市场结构
光看数字不够直观。我习惯把盘口深度画成图,一眼就能看出市场的「厚度」。
下面是我用SVG画的一个盘口深度示意图:
你看,买盘和卖盘像两座山。买盘越往下越厚(价格越低,愿意买的人越多),卖盘越往上越薄(价格越高,愿意卖的人越少)。这是正常的市场形态。
但有时候你会看到异常形态——比如某个价位突然出现巨量挂单,那可能是有人在「护盘」或者「砸盘」。做市商需要警惕这种异常信号。
注意:盘口深度是动态的。你看到的深度可能在下一秒就消失了(撤单)。做市策略不能完全依赖当前深度来决策,必须考虑「虚假深度」的风险。我曾经见过有人在关键价位挂大单,等价格靠近时瞬间撤单,诱骗其他交易者入场。
4.6 实战中的订单簿应用
说了这么多理论,咱们来点实际的。做市商怎么用订单簿?
- 定价:根据买一卖一价差,决定挂单价格。价差越大,挂单可以越宽
- 库存管理:通过盘口深度判断市场流动性,决定是否调整仓位
- 信号识别:大单吃单、撤单行为,可能预示价格即将变动
- 滑点控制:根据深度计算大单的预期滑点,决定是否拆单
我个人习惯在策略启动前,先跑一个「订单簿健康检查」:
- 价差是否在合理范围内?
- 买一卖一深度是否足够?
- 是否有异常的大单?
- 订单簿更新频率是否正常?
如果这些检查不过,我宁愿不交易,也不冒险进场。做市不是赌博,是概率游戏。订单簿就是你的概率计算器。
核心要点回顾:
- 限价单控制价格,市价单控制速度
- 订单簿是价格-数量的二维映射
- 盘口深度决定了大单的滑点成本
- 实时维护订单簿是做市的基础能力