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

做市商这行,说白了就是跟订单簿打交道。你每天盯着的那个不断跳动的数字墙,就是你的战场。我刚开始做量化的时候,总觉得订单簿就是个简单的买卖队列,后来吃了不少亏才明白——这玩意儿里面的门道深着呢。

2.1 限价单与市价单:两种最基本的武器

先说说最基础的东西。订单簿里只有两种订单:限价单和市价单。嗯,就这么简单,但组合起来能玩出花来。

限价单(Limit Order),就是你指定一个价格,挂在那里等别人来成交。比如你觉得BTC现在30000美元太贵了,想等它跌到29500再买,那就挂个限价买单。这玩意儿提供流动性,是咱们做市商的主要工具。

市价单(Market Order),就是不管三七二十一,按当前市场上最好的价格立刻成交。你想马上买入,那就吃一口卖一价的单子。这玩意儿消耗流动性,是交易员和散户常用的。

核心区别:

  • 限价单:提供流动性,承担不成交的风险,但能控制价格
  • 市价单:消耗流动性,保证成交,但可能滑点严重

我在项目中遇到过一件事。有一次我们做ETH的做市,有个新手同事挂了一堆限价单,结果行情突然暴跌,他的买单全被吃了,价格还在往下砸。他慌了,想撤单,但撤单速度跟不上行情变化。最后亏了不少。所以啊,限价单不是随便挂的,你得考虑市场冲击和撤单延迟。

2.2 订单簿的构建:从原始数据到实时状态机

订单簿怎么构建的?说白了就是维护两个有序列表:买单列表(Bids)和卖单列表(Asks)。买单按价格从高到低排,卖单按价格从低到高排。每个价格档位后面跟着该价格的总挂单量。

我习惯用Python来处理这个。给你看个简单的数据结构:

class OrderBook:
    def __init__(self):
        self.bids = {}  # 价格 -> 数量
        self.asks = {}  # 价格 -> 数量
        self.bid_levels = []  # 排序后的买单价格列表
        self.ask_levels = []  # 排序后的卖单价格列表
    
    def update(self, side, price, quantity):
        if quantity == 0:
            # 删除该价格档位
            if side == 'bid':
                self.bids.pop(price, None)
            else:
                self.asks.pop(price, None)
        else:
            # 更新或新增
            if side == 'bid':
                self.bids[price] = quantity
            else:
                self.asks[price] = quantity
        
        # 重新排序
        self.bid_levels = sorted(self.bids.keys(), reverse=True)
        self.ask_levels = sorted(self.asks.keys())

你想想看,交易所每秒会推送成千上万条订单簿更新。你如果每次都重新排序整个列表,性能肯定跟不上。我建议用红黑树或者跳表这种有序数据结构来维护。C++里用std::map,Python里可以用sortedcontainers库。

避坑指南:我曾经犯过一个错误——直接用字典存订单簿,每次更新都全量排序。结果回测跑得飞快,实盘一上就卡死了。后来改成增量更新,只维护价格档位的变化,性能提升了10倍不止。

2.3 买卖价差:做市商的利润来源

买卖价差(Bid-Ask Spread),就是卖一价减去买一价。这是做市商的核心利润来源。你低价买入,高价卖出,中间的差价就是你的收入。

但价差不是固定的。它受很多因素影响:

  • 流动性:交易量大的币种,价差通常很小。BTC/USDT的价差可能只有0.01%,而一些小币种可能达到0.5%甚至更高。
  • 波动性:行情剧烈波动时,做市商为了控制风险,会主动拉大价差。
  • 时间:凌晨流动性差,价差会变大。我一般会在凌晨调低挂单量,避免被大单吃掉。
  • 交易所:不同交易所的价差不一样。我记得有一次在某个二线交易所做市,价差是币安的3倍,但成交量只有币安的十分之一。

咱们做市商怎么定价?我常用的一个公式:

spread = base_spread + k * volatility + c * (1 / sqrt(volume))

其中:
- base_spread: 基础价差,根据币种和交易所设定
- k: 波动率系数,一般取0.5-2.0
- volatility: 近期波动率,可以用5分钟或15分钟的收益率标准差
- c: 流动性系数
- volume: 近期的成交量

这个公式不是万能的,但能给你一个起点。实际跑起来还得根据市场反馈不断调整。

2.4 市场深度:你的护城河有多宽

市场深度(Market Depth),就是订单簿上各个价格档位的挂单量总和。深度越大,说明市场越能承受大额交易而不产生大的价格波动。

我习惯看两个指标:

  • 深度表(Depth Table):列出前N档的累计挂单量。比如买一到买五的总量是多少。
  • 深度图(Depth Chart):把买单和卖单的累计量画成曲线,能直观看到市场的支撑和阻力位。

给你看个深度表的例子:

档位 买单价格 买单数量 累计买单 卖单价格 卖单数量 累计卖单
1 29950 12.5 12.5 30050 8.3 8.3
2 29900 20.1 32.6 30100 15.7 24.0
3 29850 35.0 67.6 30150 22.3 46.3
4 29800 18.2 85.8 30200 30.0 76.3
5 29750 42.0 127.8 30250 25.5 101.8

从这张表能看出什么?买单深度明显比卖单深。这说明市场在30000美元附近有较强的支撑。如果我是做市商,我会在卖单这边挂得稍微保守一点,避免被大单砸穿。

注意:深度数据是动态变化的。你以为买一有100个BTC撑着,下一秒可能就被撤单了。我见过有人根据深度数据做套利,结果撤单瞬间亏了十几万。所以啊,深度数据只能作为参考,不能完全依赖。

2.5 订单簿微观结构的核心逻辑

说了这么多,咱们来画张图,把整个知识体系串起来。

订单簿微观结构核心逻辑 订单簿 订单类型 限价单 市价单 订单簿构建 买单列表 卖单列表 核心指标 买卖价差 市场深度 做市策略:定价、挂单、风险管理 限价单提供流动性 → 构建订单簿 → 计算价差和深度 → 制定做市策略 市价单消耗流动性 → 影响订单簿 → 改变价差和深度 → 触发策略调整 反馈循环

这张图把咱们刚才讲的内容串起来了。订单簿是核心,左边是订单类型,中间是构建方法,右边是核心指标。最下面那条虚线表示反馈循环——市场深度变化会影响你的策略,你的策略又会反过来影响订单簿。

做市商说白了就是在跟市场博弈。你挂单,别人吃单;别人挂单,你吃单。谁的信息更全、反应更快、策略更优,谁就能赚钱。嗯,这就是博弈论在订单簿上的体现。

我的习惯:每天开盘前,我会先看一遍主要交易对的订单簿结构。哪个价格档位有大量挂单,哪个位置有支撑或阻力,心里有个数。然后根据这些信息调整当天的做市参数。这花不了几分钟,但能帮你避开很多坑。

好了,订单簿微观结构就讲到这里。记住一句话:订单簿是你的战场,限价单和市价单是你的武器,价差和深度是你的护城河。把这些搞明白了,做市商的路就走稳了一半。


公众号:蓝海资料掘金营,微信deep3321