halo 的技术博客

返回

上一篇《Almgren-Chriss 最优执行》把核心讲清了:把永久冲击、临时冲击、持仓波动风险写进一个目标函数,解出来不是匀速、也不是一股脑清仓,而是一条由「你多怕波动」决定的轨迹。那篇聚焦 TWAP 对比、Pareto 前沿和蒙特卡洛。

本篇不重复那些,而是把同一套框架往四个工程角度打透——这是实盘落地真正要回答的问题:

  1. 执行期限 T 该取多少天? 一天卖完和一个月卖完,成本结构天差地别。
  2. 最优的「交易速率」长什么样? 不是「每步卖多少股」,而是「每秒钟卖多少股」——这才是算法交易真正下单的东西。
  3. VWAP / TWAP 这种成交量加权基准,和 AC 最优差在哪? 经纪商最爱推 VWAP,但它是最优的吗?
  4. 调度偏了一点点,要付出多少代价? 你算好的轨迹,真到了盘口不可能精确执行,抖一点会怎样?

一、连续时间闭式解:交易速率 v*(t)#

回到 AC 设定。要在期限 T 内卖出总量 X,分 N 步(N 很大时就是连续时间)。价格受永久冲击 η·v 和临时冲击 τ·v 影响,持仓 x(t) 暴露在市场波动 σ 下。目标是

min_{v(·)}  E[cost] + (γ/2)·Var[cost]
plaintext

Almgren & Chriss (2001) 在连续时间下给出漂亮闭式解:

x*(t) = X · sinh(κ·(T−t)) / sinh(κ·T)          # 库存轨迹
v*(t) = − dx*/dt = X·κ·cosh(κ·(T−t)) / sinh(κ·T)  # 卖出速率
κ = sqrt( γ·σ² / (2τ) )                          # 由风险厌恶+波动+临时冲击决定
plaintext

κ 是整条曲线的「形状旋钮」:κ 越大(越怕波动),速率 v*(t)前置(开头猛卖、后面收尾);κ→0v*(t)→X/T,就是匀速。注意 x*(T)=0Σv*·dt=X——保证到期清仓。

二、执行期限 T 的权衡:拖久≠更便宜#

第一直觉可能是「慢慢卖冲击小,所以 T 越长越好」。错。T 越长,每步卖得越少、临时冲击 τ·Σn_k² 确实下来,但你的仓位在更长时间里暴露在波动下,波动风险 σ²·Σx_j² 反而涨上去。两个力反向,于是 T 和成本之间是权衡不是单调。

Ts = np.array([0.25, 0.5, 1.0, 2.0, 4.0, 8.0, 16.0, 32.0])
E_T, S_T = [], []
for T in Ts:
    x, _, dt, sigma, _ = ac_optimal(T)
    E, V = cost_stats(x, dt, sigma)
    E_T.append(E / (X * S0) * 1e4)                   # 期望冲击 (bps)
    S_T.append(np.sqrt(V) / (X * S0) * 1e4)          # 波动风险 (bps)
python

执行期限 T 的权衡:拖久→冲击成本下降,但波动风险先降后升

实测(bps):T=0.5 天冲击 5.0、风险 110.7;T=8 天冲击 5.8、风险 71.7。冲击成本是缓缓下降的,但波动风险在 T 极短时极高(仓位久拖不决),存在一个「既不太急也不太久」的平衡点。结论:T 不是越长越好,它和你的风险预算 γ 一起决定——γ 大(怕波动)就别拖,γ 小(不在乎)可以慢慢卖。

三、最优交易速率的形状:越怕波动越前置#

把不同 T 下的最优速率 v*(t) 和库存 x(t) 画出来:

for T, col in [(0.5, "orange"), (2.0, "blue"), (8.0, "green"), (32.0, "purple")]:
    x, n, dt, _, _ = ac_optimal(T)
    rate = n / dt                                    # 交易速率 (股/步)
    # 左图: rate vs 进度; 右图: x vs 进度
python

最优交易速率 v*(t) 与库存轨迹 x(t):期限越短越陡(越快清仓)

两条规律很清楚:

  • 库存轨迹 x(t) 越短越陡:T=0.5 天那条几乎一条直线砸到 0(一天内清仓),T=32 天那条缓坡下行(慢慢磨)。
  • 速率 v(t) 全都是「前置型」的*:开头速率最高、结尾趋于 0。这是因为 cosh(κ(T−t))/sinh(κT) 在 t 小的时候最大。换句话说,AC 最优天然是「早卖早脱手库存」——它宁可开头吃点临时冲击,也要尽快把暴露在波动里的库存卸掉。

注意:上一篇里 γ→0 退化为匀速 TWAP;本篇的连续解在 γ 很小时同样平滑成匀速,但只要有 γ>0,曲线就一定前置。这是 AC 框架的固有结构,不是调参凑出来的。

四、VWAP 基准 vs AC 最优:谁更优?#

经纪商推的 VWAP(成交量加权平均价)策略,本质是「按市场成交量分布拆单」——开盘收盘成交量大就多卖、午间少卖。这合理吗?和 AC 最优比一比(取 T=2 天):

def intraday_shape(N):
    k = np.arange(N)
    u = 0.5 - 0.5 * np.cos(2 * np.pi * (k + 0.5) / N)   # U 形日内节律
    return (0.4 + 0.6 * u) / (0.4 + 0.6 * u).mean()

def vwap_schedule(T):
    w = intraday_shape(N); w = w / w.sum()
    n = X * w
    x = np.concatenate([[X], X - np.cumsum(n)])
    return x, n, T / N

x_ac, n_ac, dt_ac, sigma_ac, _ = ac_optimal(2.0)
x_vw, n_vw, dt_vw = vwap_schedule(2.0)
python

AC 最优 vs VWAP:速率形状不同,成本各有侧重

成本拆解(T=2 天,bps):

策略期望冲击波动风险
AC 最优5.0103.1
VWAP5.1117.9

VWAP 的波动风险比 AC 高约 14bps——因为它按成交量而非风险排布,午间成交量低时它还捏着库存,而这些库存正暴露在波动里。AC 最优则纯粹按「风险最小」排布,所以风险更低,冲击成本几乎打平。一句话:VWAP 是「跟着流动性走」的工程启发式,AC 是「跟着风险走」的优化解;当你的目标就是控风险时,AC 严格更优。

(实际中 VWAP 仍有存在价值:它把「市场冲击」和「被对标基准」两件事一起解决了——很多考核就是看你跑赢 VWAP 多少。这是另一层目标,不在 AC 风险框架内。)

五、调度偏一点,代价多少?#

算好的轨迹,盘口不可能精确执行。用单参数家族 n_k ∝ exp(λ·k)(λ=0 匀速,λ>0 前置,λ<0 后置)扫描偏离,看目标函数怎么变:

lams = np.linspace(-2.0, 2.0, 41)
dt = 2.0 / N; sigma = daily_vol * S0 / np.sqrt(2.0)
obj = []
for lam in lams:
    w = np.exp(lam * np.arange(N)); n_f = X * w / w.sum()
    x_f = np.concatenate([[X], X - np.cumsum(n_f)])
    E_f, V_f = cost_stats(x_f, dt, sigma)
    obj.append(E_f + 0.5 * gamma * V_f)
python

偏离 AC 最优的代价:调度偏了,目标函数立刻抬升

曲线在 AC 最优点(λ≈最优前置斜率)处取到明显的最小值,往任意一侧偏都立刻抬升。这是 AC 框架的「最优性」最直接的证据:你算出的轨迹不是众多可行解里的一个,而是帕累托前沿上唯一的最优点;偏一点就多付一点。 这也解释了为什么生产环境要用执行算法(POV/IS 等)持续把实际成交拉回最优轨迹,而不是算一次就撒手。

六、真实陷阱(别直接照抄)#

  1. 线性冲击是最大简化。真实冲击非线性:大单冲击会加速恶化(常加 n_k^γ, γ>1)。线性模型系统性低估大单成本,最优轨迹因此「卖得太猛」。生产要用非线性/分段冲击校准。

  2. σ 被当成常数且期限均摊。本文 σ = daily_vol·S0/√T 假设波动在 T 内平稳,但盘中波动有 U 形(开盘收盘大)、危机骤升。若把波动当常数,优化会在其实很危险的时段还慢悠悠卖。进阶用时变波动或盘口深度动态调轨迹。

  3. 没有流动性约束。模型假设想卖多少就能卖多少(只是贵)。真实盘口有深度上限,单笔吃穿档位触发更狠冲击甚至挂不进。要加 n_k ≤ 盘口可容量 约束。

  4. VWAP 不等于 AC 最优,但也不该被神化。VWAP 赢在「对标基准」和「隐藏意图」,AC 赢在「风险最优」。选哪个取决于你的考核目标——若考核是「跑赢 VWAP」,那 AC 最优反而不是最优(它不优化基准差)。两层目标别混为一谈。

  5. γ 和冲击参数都要校准且会漂移。η、τ 随标的流动性、市场状态变;γ 随风险预算变。用历史冲击回归定期重估,别拿常数用一年。

  6. 调度误差不可忽略但可对冲。图 4 证明偏一点就多付,所以生产环境必须有「执行偏差监控 + 闭环修正」,并叠加一个方向判断层(认为要跌就前置更狠)——但那是决策层,别和成本优化双重计数。

七、小结#

Almgren-Chriss 的美,在于它把「执行」从拍脑袋变成一道有闭式解的优化:永久冲击、临时冲击、持仓波动风险写进一个目标,解出来是一条由 κ(=√(γσ²/2τ))决定的交易速率 v*(t)。本文把它往四个工程角度打透:

  • T 不是越长越好——冲击↓但波动风险↑,和 γ 一起权衡;
  • 最优速率天然前置——早卖早卸库存,这是框架固有结构;
  • VWAP 是流动性启发式,AC 是风险最优解——目标不同,别混;
  • 最优点是唯一的——偏一点就多付,所以必须闭环执行。

从「怎么选权重」(鲁棒优化)、「怎么把仓位变成交」(本篇)、到「怎么分混沌与秩序」(熵率状态识别)——量化的每一环,都是在给「看不见的市场结构」找一个可计算的替身。

最优执行 Almgren-Chriss:把大单拆成最优执行流
https://blog.halo26812.eu.org/blog/optimal-execution-almgren
Author halo
Published at 2026年7月16日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨