第二章 市场微观结构:订单簿结构、限价单与市价单、买卖价差与市场深度

做高频做市,说白了就是在跟市场微观结构打交道。你想想看,我们每天盯着的那些跳动的价格、闪烁的挂单,背后其实有一套非常精密的规则在运转。这一章,我就带你把这些底层的零件拆开看看。

2.1 订单簿结构:市场的“实时账本”

每个交易所背后都有一本“账本”,记录着所有交易者想买想卖的价格和数量。这本账本,就是订单簿(Order Book)。

我个人习惯把订单簿想象成一个两层楼的超市货架。左边是买家(Bid),右边是卖家(Ask)。买家想低价进货,所以出价从高到低排列;卖家想高价出货,所以出价从低到高排列。中间的空隙,就是买卖双方的价格差距。

核心要点:订单簿的每一档价格,都对应着一个挂单队列。队列的长度,就是该价格上的流动性深度。

举个例子,一个典型的订单簿长这样:

买价 (Bid) 买量 (Bid Size) 卖价 (Ask) 卖量 (Ask Size)
100.10 500 100.15 300
100.09 800 100.16 700
100.08 1200 100.17 900

这里,最优买价是100.10,最优卖价是100.15。中间这0.05的差价,就是买卖价差。我在项目中遇到过,有些新手会把订单簿当成静态数据,其实它每毫秒都在变化。你看到的瞬间,可能下一秒就完全不同了。

2.2 限价单与市价单:两种“武器”

交易指令就两种:限价单和市价单。理解它们的区别,是做市的基础。

  • 限价单(Limit Order):你指定一个价格,只有市场达到这个价格才成交。说白了,就是“我只愿意在这个价买/卖,不到我不干”。它提供流动性,但可能无法立即成交。
  • 市价单(Market Order):你不指定价格,直接按当前最优价成交。说白了,就是“我现在就要,多少钱都行”。它消耗流动性,但成交速度快。

为什么会这样?因为限价单是“挂单”,市价单是“吃单”。做市商的核心工作,就是挂出限价单,等待市价单来吃。我们赚的就是这个“等待”的差价。

我的经验:我曾经在回测时发现,如果限价单挂得太死板,遇到大单冲击时,你的单子会被瞬间吃掉,然后价格就跑了。所以,限价单的挂单策略,一定要考虑市场冲击和订单簿的实时变化。

2.3 买卖价差与市场深度:流动性的“温度计”

买卖价差(Bid-Ask Spread)和市场深度(Market Depth),是衡量市场流动性的两个核心指标。

  • 买卖价差:最优卖价减去最优买价。价差越小,说明市场越活跃,流动性越好。比如,大盘蓝筹股的价差可能只有0.01元,而冷门小盘股的价差可能高达0.10元。
  • 市场深度:指在某个价格水平上,能成交的总数量。深度越大,说明市场越能承受大额订单而不引起价格剧烈波动。

你想想看,如果价差很大,你作为做市商,每笔交易的利润空间就大,但成交概率低。如果价差很小,利润薄,但成交快。这就是一个权衡。

避坑指南:我曾经在某个流动性极差的品种上做市,价差看着挺大,但深度极浅。结果一个市价单进来,直接把价格打穿了好几档,我的限价单全部被套。嗯,这里要注意:只看价差不看深度,是新手最容易犯的错误。

2.4 知识体系结构图

下面这张图,把本章的核心逻辑串起来了。你可以看到,订单簿是基础,限价单和市价单是操作工具,而价差和深度是衡量市场状态的指标。做市策略,就是在这三者之间找到平衡。

市场微观结构 订单簿结构 限价单 vs 市价单 买卖价差 & 深度 买价/卖价队列 价格优先/时间优先 实时动态变化 限价单:提供流动性 市价单:消耗流动性 做市商的核心工具 价差:流动性温度计 深度:抗冲击能力 两者需综合评估 做市策略 = 订单簿理解 + 指令选择 + 价差/深度评估 三者缺一不可,共同构成高频做市的基础

2.5 实战中的代码片段

光说不练假把式。下面这段Python代码,演示了如何从交易所的WebSocket流中解析订单簿数据。我个人习惯用字典来存储订单簿,因为更新和查询都很快。

import json
import asyncio
import websockets

# 模拟一个简单的订单簿类
class OrderBook:
    def __init__(self):
        self.bids = {}  # 买价 -> 数量
        self.asks = {}  # 卖价 -> 数量
    
    def update(self, side, price, size):
        """更新订单簿,side: 'bid' 或 'ask'"""
        if side == 'bid':
            if size == 0:
                self.bids.pop(price, None)  # 数量为0,删除该档位
            else:
                self.bids[price] = size
        elif side == 'ask':
            if size == 0:
                self.asks.pop(price, None)
            else:
                self.asks[price] = size
    
    def get_top(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

# 模拟数据流处理
async def process_orderbook(ws_url):
    async with websockets.connect(ws_url) as ws:
        ob = OrderBook()
        async for message in ws:
            data = json.loads(message)
            # 假设数据格式: {"side": "bid", "price": 100.10, "size": 500}
            ob.update(data['side'], data['price'], data['size'])
            # 这里可以添加你的做市逻辑
            # 比如检查价差、计算最优挂单价格等

小提示:实际生产中,订单簿的更新频率极高。我建议用asyncio.Queue来做缓冲,避免处理速度跟不上数据流。另外,记得处理数据延迟和重连逻辑,这是高频交易里最容易出bug的地方。

好了,这一章的内容就到这里。市场微观结构是高频做市的“内功”,练好了,后面的招式才能发挥威力。记住,订单簿不是死的,它是活的,是市场情绪的实时投影。

专注资料整理