halo 的技术博客

返回

做执行的人都知道一个反直觉的事实:同一笔大单,在开盘前 30 分钟下,和在中午 11:30 下,成交的「隐形成本」能差好几倍。

差在哪?不在价格,在流动性。而流动性在一天之内是高度有规律的——它跟着成交量走,成交量又跟着「信息什么时候来、机构在什么时候动手」走。这条规律几乎所有市场都成立,名字很直白:日内成交量 U 型曲线(U-shape)

本文不谈玄学,直接用 240 分钟的合成日内序列,把这条曲线画出来、把它的成本含义算出来、把「怎么利用它」落到一段可跑的 Python 上。

一、U 型曲线:开盘和收盘最肥,午盘最瘦#

日内成交量的形状,本质上由三股力量决定:

  • 开盘窗口:隔夜积累的新闻、券商晨会观点、盘前大宗,全部在集合竞价和开盘后集中释放;散户情绪也最浓。成交量第一个峰。
  • 午盘窗口(11:30~14:00):该消化的隔夜信息消化完了,下一批 catalysts(经济数据、公司公告)还没到,进入信息真空。成交量坍缩到日内最低。
  • 收盘窗口:指数调仓、基金净值管理、MOC(market-on-close)竞价、日内炒家平仓,全部挤在收盘前。成交量第二个峰。

我们用一段 240 分钟的合成序列刻画这件事:U 型基准 1 + 2.2·u²(u 是归一化时间,两端=1+2.2、中间=1),再叠加开盘与收盘的高斯 boost,并给每个分钟加乘性对数正态噪声(午盘流动性更脆,噪声更大)。

import numpy as np
rng = np.random.default_rng(20260717)
N_MIN = 240
t = np.arange(N_MIN)
center = (N_MIN - 1) / 2.0
u = (t - center) / center
base = 1.0 + 2.2 * u ** 2                         # U 型基准: 两端高、中间低
open_boost  = np.exp(-((t - 5) ** 2) / (2 * 8 ** 2)) * 1.3          # 开盘集合竞价延续
close_boost = np.exp(-((t - (N_MIN - 6)) ** 2) / (2 * 10 ** 2)) * 1.1
profile = base + open_boost + close_boost
noise = rng.lognormal(0.0, 0.18 + 0.12 * np.exp(-((t - center) ** 2) / (2 * 30 ** 2)), N_MIN)
vol_min = np.clip(profile * noise, 0.05, None)
vol_min = vol_min / vol_min.mean()                 # 归一化到日均=1
python

跑出来:开盘 15 分钟均量 2.28、午盘(108–132 分)均量 0.55、收盘 15 分钟均量 1.96,两端相对中段约 3.84 倍。高流动性分钟(成交量位于前 30%)占了全天的 30%。

日内成交量 U 型曲线:开盘与收盘最肥, 午盘最瘦

把成交量按时间累计,得到一条 S 型曲线——前 30 分钟和最后 30 分钟把大部分成交量「吃掉」,中间慢悠悠。这就是你择时下单价位的物理基础。

累计成交量 vs 时钟:S 型, 高流动性窗口在头尾

二、流动性窗口 = 执行成本窗口#

成交量不是装饰。对一笔真实订单而言,成交量越低,你吃掉的市场深度越薄,冲击成本和买卖价差越贵。我们用一个最简单的代理模型把这件事量化:

costt=c0+c1voltcost_{t} = c_0 + \frac{c_1}{vol_t}

成交量越低,成本越高。把上面算出的 vol_min 代进去:

cost = 0.8 + 2.5 / vol_min                       # 执行成本代理(bp), 与成交量反比
cost_mid   = cost[108:132].mean()                # 午盘
cost_open  = cost[:15].mean()                    # 开盘
cost_close = cost[-15:].mean()                   # 收盘
python

结果非常直观:午盘执行成本 5.65bp,开盘 1.93bp,收盘 2.16bp——午盘比开盘贵 2.93 倍。换句话说,同样是 1 万手,中午下手比开盘下手多付近 3 倍的隐形成本。

时段执行成本代理:午盘流动性最差、成本最高

实务含义:如果你要拆单卖一个不想砸盘的头寸,尽量把大块放在开盘和收盘;午盘那两个小时,要么少动,要么把单子切得更碎。

三、落到执行:大单调度,让单子自己找窗口#

光知道「午盘贵」还不够,得把它变成可执行的算法。最经典的对照就是 VWAP(成交量加权均价)调度 vs 均匀调度

假设要在盘中执行 1 万手(Q = 10000):

  • 均匀调度:每分钟下 Q / 240 手,无视流动性;
  • VWAP 调度:按当日成交量分布分配,q_t = Q · vol_t / Σvol_t,天然把单子压进高流动性窗口。

两种调度的实现差额(implementation shortfall, IS),就是对「每分钟分配量 × 该分钟成本代理」求和:

Q = 10000.0
uniform_qty = np.full(N_MIN, Q / N_MIN)
vwap_qty    = Q * vol_min / vol_min.sum()
exec_drift_uniform = (uniform_qty / Q) * cost * 100
exec_drift_vwap    = (vwap_qty    / Q) * cost * 100
is_uniform = np.sum(uniform_qty * exec_drift_uniform) / Q
is_vwap    = np.sum(vwap_qty    * exec_drift_vwap)    / Q
python

跑出来:均匀调度 IS = 1.67bp,VWAP 调度 IS = 1.48bp,VWAP 相对均匀节省 11.4%。注意这里成本代理是线性简化,真实市场里冲击成本是凸的(手数越大边际越贵),所以 VWAP 的实际优势会更大——这正是 VWAP 算法能存在几十年的根本原因。

1 万手大单调度:VWAP 把单子压进高流动性窗口

四、为什么这事在 A 股要重画#

美股的 U 型是「早盘峰 + 尾盘峰」双峰对称。A 股的日内成交量形状被 T+1 和收盘竞价改写了:

  • 尾盘峰异常突出:14:30 之后的「偷袭」和收盘竞价(market close)让最后 30 分钟成交量占比远高于美股,尾盘窗口比开盘更值得抢;
  • 午休断崖:11:30–13:00 是真实休市,午盘坍缩更彻底,但 13:00 重开后有一波「续开盘」的小峰;
  • T+1 下的隔夜不可交易:你今天买的,明天才能卖,所以「开盘窗口」对你而言是卖出的最佳流动性点,而不是买入。

所以 A 股的执行建议要反过来记:想减仓,优先开盘;想加仓,优先尾盘

五、六类真实陷阱(实战必看)#

  1. 合成曲线不等于真实日历:本文的 U 型是参数化设定,真实 U 型高度依赖市场。美股尾盘峰由 MOC 驱动,A 股由收盘竞价驱动,新兴市场可能午盘峰更平。实盘要先用自己的标的真实分钟成交量把曲线画出来再下结论。
  2. 特殊日完全打破 U 型:财报日、联储议息、指数调仓日(如 MSCI 季调)、期权到期日,成交量会在特定分钟爆量,把平滑的 U 型砸出尖峰。这些日子不能再套「午盘便宜」的经验。
  3. 成本代理的线性假设:cost = c0 + c1/vol 是线性的,真实冲击成本是的(手数翻倍,成本涨不止一倍)。VWAP 在真实凸成本下优势比本文 11.4% 更大,但均匀调度的劣势也被低估了。
  4. 波动率状态切换:高波动日(如 2020 年 3 月),成交量整体抬升但午盘坍缩比例变小——大家都在盯盘,午盘不再那么「真空」。U 型在危机时会变扁,择时窗口随之模糊。
  5. 大单改变市场:本文的 cost 是把 vol_min 当「外生流动性容量」,假设你 1 万手不改变它。真实大单会自己制造冲击、把流动性抽干,VWAP 的「跟着成交量走」本质是在赌自己的单子不改变全局分布——超过日均成交 10% 的大单,这个假设就破了。
  6. 跨市场时段错位:做跨资产/跨市场(如 A 股 + 港股 + 美股 ADR)时,各市场 U 型错位。A 股午休时港股还在交易,可以用跨市场流动性接力把单子挪到另一个还在高流动性的市场下,这是机构 TCA(交易成本分析)的进阶玩法。

六、小结:流动性会呼吸,别跟它对着干#

把这篇文章和「最优执行(Almgren-Chriss)」「VPIN 流动性风险」放在一起看,逻辑就通了:

  • 成交量 U 型 = 一天之内流动性在「呼吸」,开盘/收盘吸饱、午盘吐空;
  • 执行成本 = 流动性的倒数,午盘最贵;
  • VWAP / 调度算法 = 顺着呼吸节奏把单子喂进去,而不是均匀硬砸。

所谓「日内成交量季节性」,不是一个孤立的曲线形状,而是信息流、机构行为、交易制度三者在一天尺度上耦合的必然结果。它给你的实用洞见极简单:下单价位可以择时,而最好的择时锚,就是成交量本身。


代码与图表均由自包含 Python(numpy/scipy/matplotlib)真实计算,随机种子固定为 20260717,可完整复现。所有统计数字(开盘/午盘/收盘均量、U 型比、执行成本比、VWAP 相对均匀节省的实现差额)均来自文中脚本输出。成本代理为线性简化,真实冲击成本呈凸性,实战应以真实分钟级 TCA 数据重估。

日内成交量季节性:用 U 型曲线预测盘中流动性窗口
https://blog.halo26812.eu.org/blog/intraday-volume-seasonality
Author halo
Published at 2026年7月17日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨