第一章 订单簿与市场深度分析
做高频交易这些年,我每天打交道最多的东西,就是订单簿。说白了,订单簿就是交易所给你的一张实时报价单——谁想买、谁想卖、出什么价、要多少量。你想想看,没有这个,你连市场在干嘛都不知道,还谈什么策略?
我个人习惯把订单簿比作一个战场的地图。买盘是防守方,卖盘是进攻方。你要做的,就是通过这张地图,判断下一秒谁会赢。
订单簿的数据结构
先看最基础的东西。订单簿长什么样?
交易所传过来的数据,通常是一个价格-数量的映射。买盘叫Bid,卖盘叫Ask。每个价格档位(Price Level)上,挂着所有未成交的订单总量。
举个例子,一个简化的订单簿长这样:
卖盘(Ask):
价格 100.05 数量 200
价格 100.04 数量 150
价格 100.03 数量 300
买盘(Bid):
价格 100.02 数量 250
价格 100.01 数量 180
价格 100.00 数量 400
这里有个关键点:价格优先,时间优先。买单出价高的排前面,卖单出价低的排前面。同一个价格,先来的先成交。
我在项目中遇到过一个问题——数据量太大。期货高频的订单簿,每秒可能更新几百次。如果用Python的list去存,性能根本扛不住。后来我改用sortedcontainers库,或者直接用C++的std::map,才把延迟压下去。
买卖盘口分析
盘口,就是订单簿最前面那几档。买一、卖一、买二、卖二……这些是市场最直接的博弈点。
我一般关注三个东西:
- 价差(Spread):卖一价减去买一价。价差越小,流动性越好。做高频交易,价差就是你的成本。
- 盘口厚度:每个价位的挂单量。厚度大,说明这个价位有支撑或阻力。
- 挂单变化:某个价位的挂单突然增加或减少,往往意味着大资金在行动。
举个例子,如果你看到买一价100.02上突然多了500手挂单,而之前只有250手。这说明有人在护盘,或者想在这个价位吸筹。这时候,你就要小心了——价格可能跌不下去。
市场深度计算
市场深度,说白了就是“你想吃掉多少量,价格会滑多少”。
计算方式很简单:从最优价格开始,累加每个价位的挂单量,直到达到目标数量。然后看平均成交价和当前价的差距。
比如,你想买1000手。当前卖一100.03有300手,卖二100.04有150手,卖三100.05有200手,卖四100.06有350手。那么:
吃掉卖一:300手,花费 300 * 100.03
吃掉卖二:150手,花费 150 * 100.04
吃掉卖三:200手,花费 200 * 100.05
吃掉卖四:350手,花费 350 * 100.06(但只需要350手中的350手)
总花费 = 300*100.03 + 150*100.04 + 200*100.05 + 350*100.06
平均成交价 = 总花费 / 1000
这个平均价和当前卖一价的差值,就是你的冲击成本。
我习惯用Python写一个快速计算函数:
def calc_market_depth(ask_book, target_qty):
"""
ask_book: 列表,每个元素是 (price, qty),按价格升序
target_qty: 目标买入数量
返回: (平均成交价, 冲击成本)
"""
total_cost = 0.0
filled = 0
for price, qty in ask_book:
take = min(qty, target_qty - filled)
total_cost += take * price
filled += take
if filled >= target_qty:
break
avg_price = total_cost / filled
impact = avg_price - ask_book[0][0]
return avg_price, impact
嗯,这里要注意:实际交易中,你的订单可能只吃掉一部分,剩下的会留在盘口。但做策略分析时,我们通常假设全部吃掉,这样算出来的冲击成本是上限。
盘口失衡指标构建
盘口失衡,就是买盘和卖盘的力量对比。如果买盘明显强于卖盘,价格大概率要涨。反之亦然。
最简单的指标是订单簿失衡率(Order Book Imbalance, OBI):
OBI = (买盘总量 - 卖盘总量) / (买盘总量 + 卖盘总量)
OBI的取值范围是[-1, 1]。正值表示买盘强,负值表示卖盘强。
但光看总量不够。我更喜欢看加权失衡指标——离最优价格越近的挂单,权重越大。因为近端挂单对价格的直接影响更大。
举个例子:
def weighted_imbalance(bid_book, ask_book, decay=0.9):
"""
bid_book: 买盘列表 [(price, qty), ...],按价格降序
ask_book: 卖盘列表 [(price, qty), ...],按价格升序
decay: 衰减因子,越远的价位权重越小
"""
bid_weighted = 0.0
ask_weighted = 0.0
weight = 1.0
for price, qty in bid_book:
bid_weighted += qty * weight
weight *= decay
weight = 1.0
for price, qty in ask_book:
ask_weighted += qty * weight
weight *= decay
return (bid_weighted - ask_weighted) / (bid_weighted + ask_weighted + 1e-8)
这个指标我用了很久。它比简单的总量失衡更敏感,能提前捕捉到盘口的变化。
知识体系总览
下面这张图,是我自己总结的订单簿分析框架。你可以把它当作一个检查清单:
这张图把订单簿分析拆成了四个模块。数据结构是地基,盘口分析和市场深度是工具,失衡指标是决策依据。最后,所有这些都服务于锁单和撤单策略——这也是我们后面章节要深入的内容。
好了,这一章就到这里。记住一句话:订单簿是你的眼睛,但别只看表面。挂单会撤,深度会变,指标会骗人。保持怀疑,持续验证,这才是高频交易者的生存之道。