3. 买卖价差与交易成本:价差的构成与估算
做量化交易的朋友,一定对「买卖价差」不陌生。说白了,它就是你在市场上买进和卖出同一资产时,需要付出的那部分「过路费」。我刚开始做高频策略时,总觉得价差是个小数字,结果回测跑得漂亮,实盘一上就亏钱。后来才明白——价差背后藏着市场微观结构的核心秘密。
今天我们就来拆解一下,这个看似简单的价差,到底由什么构成,以及我们怎么精确地估算交易成本。
3.1 价差的三大构成
一个完整的买卖价差,其实不是铁板一块。它由三个部分叠加而成:逆向选择成本、订单处理成本、存货持有成本。我习惯把它们比作「三座大山」,每一座都压在做市商和交易者身上。
3.1.1 逆向选择成本
这是最隐蔽、也最致命的一块。什么叫逆向选择?简单说,就是市场上总有一些人比你更聪明、信息更灵通。当你挂单卖出时,对方可能已经知道马上有利空消息;当你买入时,对方可能提前看到了利好。
我在做期权做市商时,遇到过这么一件事:某只股票盘口突然出现大量买单,我习惯性地跟着调高了卖价。结果不到30秒,公司发布了业绩预增公告。嗯,那些提前买入的人,就是利用了信息优势。我作为做市商,被迫以不利价格成交,这部分损失就是逆向选择成本。
实际计算中,我们常用 Glosten-Milgrom模型 来分解。这个模型把价差拆成两部分:一部分补偿做市商的信息劣势,另一部分补偿运营成本。我个人习惯用订单簿的不平衡度来近似估算——当买单深度远大于卖单深度时,逆向选择成本会显著上升。
3.1.2 订单处理成本
这个就好理解了。交易所要收手续费,清算所要收结算费,券商要收通道费。这些硬性成本,最终都会体现在价差里。我记得有一次帮客户优化一个高频策略,发现他的订单处理成本占了总交易成本的60%。
订单处理成本通常包括:
- 交易所费用: 按成交金额或笔数收取
- 清算与结算费: 固定费用,与交易量关系不大
- 系统与网络成本: 服务器托管、行情数据订阅等
- 人工与合规成本: 风控、报备等后台支持
你想想看,如果一只股票价差只有0.01元,但每笔交易的手续费就要0.005元,那做市商几乎赚不到钱。所以流动性差的股票,价差自然就大——因为订单处理成本摊不薄。
3.1.3 存货持有成本
做市商手里必须持有一定数量的股票,才能随时提供流动性。但持有存货是有风险的——价格可能下跌,资金可能被占用,还有机会成本。
我曾经在2015年股灾期间做做市,手里囤了一堆中小板股票。结果市场连续跌停,我根本出不了货。那段时间的存货成本,直接把我前三个月的利润全吃掉了。
存货成本可以用 资本成本 + 风险溢价 来估算:
# 一个简单的存货成本估算函数
def inventory_cost(price, position, holding_period, volatility, risk_free_rate):
"""
price: 当前价格
position: 持仓数量
holding_period: 预期持有天数
volatility: 年化波动率
risk_free_rate: 无风险利率
"""
capital_cost = price * position * risk_free_rate * (holding_period / 365)
risk_premium = price * position * volatility * (holding_period / 365) ** 0.5
return capital_cost + risk_premium
这个函数虽然简单,但我在实盘里一直用。注意那个风险溢价项——波动率越高,存货成本就越大。这也是为什么高波动股票价差通常更大的原因。
3.2 有效价差与实现价差
光知道理论价差还不够。实际交易中,我们更关心的是「我到底花了多少钱」。这里有两个重要概念:有效价差和实现价差。
3.2.1 有效价差
有效价差衡量的是:你的成交价格相对于买卖报价中点的偏离程度。公式很简单:
有效价差 = 2 × |成交价格 - 买卖报价中点|
举个例子:某股票买一价10.00元,卖一价10.02元,中点就是10.01元。如果你以10.02元买入,有效价差就是2 × |10.02 - 10.01| = 0.02元。这正好等于报价价差。
但实际情况往往更复杂。我在做A股策略时发现,很多大单成交价会穿透报价价差——比如以10.03元成交,这时候有效价差就大于报价价差了。这说明市场深度不足,你的订单造成了价格冲击。
3.2.2 实现价差
实现价差则更进一步。它考虑的是:你成交之后,市场价格会怎么走?
实现价差 = 2 × |成交价格 - 成交后一段时间的中点价格|
为什么要看这个?因为如果你买入后,价格立刻上涨,说明你买在了相对低点——实际成本其实比有效价差要低。反之,如果买入后价格下跌,说明你被「接盘」了,成本更高。
我记得有一次做股指期货的套利策略,有效价差看起来只有0.2个点,但实现价差却高达0.8个点。为什么?因为我的订单太大,把价格推高了,等成交完市场又回落了。这就是典型的「价格冲击」和「逆向选择」共同作用的结果。
3.3 交易成本估算模型
好了,理论讲完了,我们来点实际的。怎么在策略中估算交易成本?我推荐三个模型,各有适用场景。
3.3.1 线性冲击模型
这是最简单的模型,假设价格冲击与交易量成正比:
def linear_impact(order_size, avg_daily_volume, spread, coefficient=0.5):
"""
线性价格冲击模型
order_size: 订单数量
avg_daily_volume: 日均成交量
spread: 买卖价差
coefficient: 冲击系数,通常0.1-1.0
"""
participation_rate = order_size / avg_daily_volume
impact = coefficient * spread * participation_rate
return impact
这个模型适合小单、流动性好的市场。但遇到大单,线性假设就不准了——实际冲击往往是非线性的。
3.3.2 平方根冲击模型
Almgren等人提出的模型,更符合实际:
def sqrt_impact(order_size, avg_daily_volume, volatility, spread):
"""
平方根价格冲击模型
"""
participation_rate = order_size / avg_daily_volume
permanent_impact = 0.142 * volatility * (participation_rate ** 0.5)
temporary_impact = 0.5 * spread * (participation_rate ** 0.5)
return permanent_impact + temporary_impact
这个模型把冲击分成了永久性冲击(改变市场均衡价格)和暂时性冲击(流动性消耗后的恢复)。我在做大宗交易策略时,一直用这个模型来估算最优下单路径。
3.3.3 基于订单簿的微观结构模型
如果你有Level 2行情数据,可以用更精细的模型。我个人最常用的是:
def order_book_impact(order_book, order_size, side='buy'):
"""
基于订单簿的价格冲击估算
order_book: 订单簿数据,包含价格和数量
order_size: 要交易的股数
side: 'buy' 或 'sell'
"""
remaining = order_size
total_cost = 0
avg_price = 0
levels = order_book['asks'] if side == 'buy' else order_book['bids']
for price, volume in levels:
if remaining <= 0:
break
trade_volume = min(remaining, volume)
total_cost += trade_volume * price
remaining -= trade_volume
if remaining > 0:
# 订单簿深度不足,需要额外估算
avg_price = total_cost / (order_size - remaining)
# 这里可以加入滑点惩罚
return avg_price * 1.05 # 假设5%的额外滑点
avg_price = total_cost / order_size
return avg_price
这个模型的好处是,它直接反映了当前市场的真实深度。但缺点也很明显——订单簿变化太快,你算出来的结果可能下一秒就失效了。
3.4 一张图总结
说了这么多,我们来画个结构图,把整个知识体系串起来:
这张图把整个章节的逻辑串起来了。从价差的三大构成出发,到如何用有效价差和实现价差来度量实际成本,最后落到三个估算模型上。我个人建议,做策略回测时至少用平方根模型,做高频交易时一定要用订单簿模型。
好了,这一章的内容就到这里。记住,下次你看到盘口上的买卖价差时,别只盯着那几分钱——背后藏着整个市场的博弈逻辑。