3、冰山订单的算法框架:时间切片模型、成交量加权模型、动态调整模型
聊到冰山订单的算法实现,我脑子里第一个蹦出来的画面,是几年前在实盘环境里调试一个高频做市策略。当时订单簿上明明挂着大单,可一吃就没了——后来才发现,那是别人的冰山订单在“钓鱼”。
说白了,冰山订单的核心就一句话:把一个大单拆成无数个小单,分批扔进市场。但怎么拆、什么时候扔、扔多少,这里面的门道就深了。
我个人习惯把冰山订单的算法框架分成三大流派:时间切片模型、成交量加权模型、动态调整模型。咱们一个一个拆开看。
3.1 时间切片模型:最简单的“定时定量”
这个模型最直观。你想想看,我要卖100万股,不想让人看出来。那就把时间切成N段,每段扔固定数量的单子。
比如,交易时段是4小时(240分钟),我切成240个1分钟切片。每分钟扔4167股。嗯,就这么简单。
代码实现大概长这样:
class TimeSliceIceberg:
def __init__(self, total_qty, total_time, slices):
self.total_qty = total_qty
self.slice_qty = total_qty // slices
self.interval = total_time / slices
self.remaining = total_qty
def next_order(self, current_time):
# 计算当前应该在第几个切片
slice_idx = int(current_time / self.interval)
if slice_idx * self.slice_qty <= self.remaining:
return min(self.slice_qty, self.remaining)
return 0
优点:实现简单,逻辑清晰,回测时几乎不会出bug。
缺点:太死板了。市场在暴涨,你还在按部就班地卖;市场在暴跌,你还在傻乎乎地买。我曾经在一个震荡市里用这个模型,结果被来回打脸——每次都在最不利的价位成交。
3.2 成交量加权模型:跟着市场节奏走
这个模型就聪明多了。它不按时间切,而是按市场成交量来切。
核心逻辑是:市场成交了多少,我就跟着成交多少。比如,我设定一个参与率参数α=0.05,意思是市场每成交100股,我就成交5股。
公式很简单:
当前应成交量 = 市场累计成交量 × α - 已成交量
代码实现:
class VolumeWeightedIceberg:
def __init__(self, total_qty, participation_rate):
self.total_qty = total_qty
self.alpha = participation_rate # 参与率
self.executed = 0
def next_order(self, market_volume):
target = int(market_volume * self.alpha)
order_qty = target - self.executed
if order_qty > 0:
order_qty = min(order_qty, self.total_qty - self.executed)
self.executed += order_qty
return order_qty
return 0
这个模型的好处是:市场活跃时我多交易,市场冷清时我少交易。不会在流动性枯竭的时候硬往里冲。
我记得有一次做港股交易,下午3点半之后流动性骤降。如果用时间切片模型,我还在那硬挂单,结果被做市商吃得死死的。换成成交量加权模型后,自动减少了交易频率,成本降了将近30%。
3.3 动态调整模型:真正的“智能冰山”
前两个模型都是静态的——参数设好了就不变了。但市场是活的,你的算法也得是活的。
动态调整模型的核心思想是:根据市场状态实时调整下单策略。它会考虑三个维度:
- 价格偏离度:当前价格离我的目标价有多远
- 订单簿深度:买卖挂单的厚度如何
- 市场冲击成本:我每下一单,价格会滑多少
我设计过一个简单的动态调整模型,核心逻辑是:
class DynamicIceberg:
def __init__(self, total_qty, target_price):
self.total_qty = total_qty
self.target_price = target_price
self.executed = 0
def calc_order_size(self, current_price, bid_depth, ask_depth):
# 价格偏离度越大,下单越保守
price_dev = abs(current_price - self.target_price) / self.target_price
# 订单簿越薄,下单越小
liquidity = (bid_depth + ask_depth) / 2
# 动态调整下单量
base_qty = self.total_qty // 100
adjust_factor = max(0.1, 1 - price_dev * 10)
liquidity_factor = min(1, liquidity / 100000)
order_qty = int(base_qty * adjust_factor * liquidity_factor)
return min(order_qty, self.total_qty - self.executed)
这个模型的好处是:市场对你有利时,你加速交易;市场对你不利时,你减速甚至暂停。
我曾经在实盘中遇到过这种情况:一个大单刚挂出去,价格突然跳水。动态调整模型立刻检测到价格偏离度超过阈值,自动把下单量降到了原来的10%。等价格反弹回来,再恢复正常的交易节奏。这一波操作,帮我少亏了至少50个基点。
三种模型对比总结:
| 模型 | 核心逻辑 | 适用场景 | 风险点 |
|---|---|---|---|
| 时间切片 | 固定时间间隔下单 | 高流动性、低波动 | 市场突变时失效 |
| 成交量加权 | 按市场成交量比例下单 | 中等流动性 | 参数α难调优 |
| 动态调整 | 多因子实时决策 | 所有场景 | 实现复杂、过拟合风险 |
下面这张图,是我自己画的一个冰山订单算法框架图,帮你理清这三种模型的关系:
最后说一句,这三种模型没有绝对的好坏。我个人的建议是:从时间切片模型开始,跑通整个流程;然后升级到成交量加权模型,优化执行成本;最后再上动态调整模型,追求极致表现。一步到位搞动态调整,很容易掉进过拟合的坑里。
避坑指南:我曾经在一个项目里,一上来就搞动态调整模型,用了十几个因子。结果回测曲线漂亮得不行,实盘一跑就崩。后来才发现,那些因子在回测里是“伪相关”,实盘里根本没用。所以,先做减法,再做加法。
公众号:蓝海资料掘金营,微信deep3321